mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 01:17:27 +00:00
Auto merge of #14120 - Veykril:castable, r=Veykril
internal: Revert castable expectation and simplify Unfixes https://github.com/rust-lang/rust-analyzer/issues/11571, the PR for that introduced some regressions (tried fixing them but doing what rustc does there specifically does not help, probably because something else affects it as well there)
This commit is contained in:
commit
d9c020d426
5 changed files with 101 additions and 43 deletions
|
@ -219,6 +219,7 @@ struct InternedStandardTypes {
|
|||
unknown: Ty,
|
||||
bool_: Ty,
|
||||
unit: Ty,
|
||||
never: Ty,
|
||||
}
|
||||
|
||||
impl Default for InternedStandardTypes {
|
||||
|
@ -227,6 +228,7 @@ impl Default for InternedStandardTypes {
|
|||
unknown: TyKind::Error.intern(Interner),
|
||||
bool_: TyKind::Scalar(Scalar::Bool).intern(Interner),
|
||||
unit: TyKind::Tuple(0, Substitution::empty(Interner)).intern(Interner),
|
||||
never: TyKind::Never.intern(Interner),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1024,6 +1026,7 @@ impl<'a> InferenceContext<'a> {
|
|||
pub(crate) enum Expectation {
|
||||
None,
|
||||
HasType(Ty),
|
||||
#[allow(dead_code)]
|
||||
Castable(Ty),
|
||||
RValueLikeUnsized(Ty),
|
||||
}
|
||||
|
@ -1102,6 +1105,10 @@ impl Expectation {
|
|||
}
|
||||
}
|
||||
|
||||
fn coercion_target_type(&self, table: &mut unify::InferenceTable<'_>) -> Ty {
|
||||
self.only_has_type(table).unwrap_or_else(|| table.new_type_var())
|
||||
}
|
||||
|
||||
/// Comment copied from rustc:
|
||||
/// Disregard "castable to" expectations because they
|
||||
/// can lead us astray. Consider for example `if cond
|
||||
|
|
|
@ -51,7 +51,7 @@ impl InferenceContext<'_> {
|
|||
.map(to_chalk_trait_id)
|
||||
.collect();
|
||||
|
||||
let self_ty = TyKind::Error.intern(Interner);
|
||||
let self_ty = self.result.standard_types.unknown.clone();
|
||||
let bounds = dyn_ty.bounds.clone().substitute(Interner, &[self_ty.cast(Interner)]);
|
||||
for bound in bounds.iter(Interner) {
|
||||
// NOTE(skip_binders): the extracted types are rebound by the returned `FnPointer`
|
||||
|
@ -67,7 +67,7 @@ impl InferenceContext<'_> {
|
|||
let arg = projection.substitution.as_slice(Interner).get(1)?;
|
||||
if let Some(subst) = arg.ty(Interner)?.as_tuple() {
|
||||
let generic_args = subst.as_slice(Interner);
|
||||
let mut sig_tys = Vec::new();
|
||||
let mut sig_tys = Vec::with_capacity(generic_args.len() + 1);
|
||||
for arg in generic_args {
|
||||
sig_tys.push(arg.ty(Interner)?.clone());
|
||||
}
|
||||
|
|
|
@ -87,16 +87,15 @@ impl<'a> InferenceContext<'a> {
|
|||
let expected = &expected.adjust_for_branches(&mut self.table);
|
||||
self.infer_expr(
|
||||
condition,
|
||||
&Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(Interner)),
|
||||
&Expectation::HasType(self.result.standard_types.bool_.clone()),
|
||||
);
|
||||
|
||||
let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
|
||||
let mut both_arms_diverge = Diverges::Always;
|
||||
|
||||
let result_ty = self.table.new_type_var();
|
||||
let then_ty = self.infer_expr_inner(then_branch, expected);
|
||||
both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe);
|
||||
let mut coerce = CoerceMany::new(result_ty);
|
||||
let mut coerce = CoerceMany::new(expected.coercion_target_type(&mut self.table));
|
||||
coerce.coerce(self, Some(then_branch), &then_ty);
|
||||
let else_ty = match else_branch {
|
||||
Some(else_branch) => self.infer_expr_inner(else_branch, expected),
|
||||
|
@ -113,7 +112,7 @@ impl<'a> InferenceContext<'a> {
|
|||
&Expr::Let { pat, expr } => {
|
||||
let input_ty = self.infer_expr(expr, &Expectation::none());
|
||||
self.infer_pat(pat, &input_ty, BindingMode::default());
|
||||
TyKind::Scalar(Scalar::Bool).intern(Interner)
|
||||
self.result.standard_types.bool_.clone()
|
||||
}
|
||||
Expr::Block { statements, tail, label, id: _ } => {
|
||||
let old_resolver = mem::replace(
|
||||
|
@ -188,10 +187,12 @@ impl<'a> InferenceContext<'a> {
|
|||
.intern(Interner)
|
||||
}
|
||||
&Expr::Loop { body, label } => {
|
||||
// FIXME: should be:
|
||||
// let ty = expected.coercion_target_type(&mut self.table);
|
||||
let ty = self.table.new_type_var();
|
||||
let (breaks, ()) =
|
||||
self.with_breakable_ctx(BreakableKind::Loop, ty, label, |this| {
|
||||
this.infer_expr(body, &Expectation::has_type(TyBuilder::unit()));
|
||||
this.infer_expr(body, &Expectation::HasType(TyBuilder::unit()));
|
||||
});
|
||||
|
||||
match breaks {
|
||||
|
@ -199,16 +200,16 @@ impl<'a> InferenceContext<'a> {
|
|||
self.diverges = Diverges::Maybe;
|
||||
breaks
|
||||
}
|
||||
None => TyKind::Never.intern(Interner),
|
||||
None => self.result.standard_types.never.clone(),
|
||||
}
|
||||
}
|
||||
&Expr::While { condition, body, label } => {
|
||||
self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| {
|
||||
this.infer_expr(
|
||||
condition,
|
||||
&Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(Interner)),
|
||||
&Expectation::HasType(this.result.standard_types.bool_.clone()),
|
||||
);
|
||||
this.infer_expr(body, &Expectation::has_type(TyBuilder::unit()));
|
||||
this.infer_expr(body, &Expectation::HasType(TyBuilder::unit()));
|
||||
});
|
||||
|
||||
// the body may not run, so it diverging doesn't mean we diverge
|
||||
|
@ -224,7 +225,7 @@ impl<'a> InferenceContext<'a> {
|
|||
|
||||
self.infer_pat(pat, &pat_ty, BindingMode::default());
|
||||
self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| {
|
||||
this.infer_expr(body, &Expectation::has_type(TyBuilder::unit()));
|
||||
this.infer_expr(body, &Expectation::HasType(TyBuilder::unit()));
|
||||
});
|
||||
|
||||
// the body may not run, so it diverging doesn't mean we diverge
|
||||
|
@ -234,7 +235,7 @@ impl<'a> InferenceContext<'a> {
|
|||
Expr::Closure { body, args, ret_type, arg_types, closure_kind } => {
|
||||
assert_eq!(args.len(), arg_types.len());
|
||||
|
||||
let mut sig_tys = Vec::new();
|
||||
let mut sig_tys = Vec::with_capacity(arg_types.len() + 1);
|
||||
|
||||
// collect explicitly written argument types
|
||||
for arg_type in arg_types.iter() {
|
||||
|
@ -255,7 +256,8 @@ impl<'a> InferenceContext<'a> {
|
|||
num_binders: 0,
|
||||
sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false },
|
||||
substitution: FnSubst(
|
||||
Substitution::from_iter(Interner, sig_tys.clone()).shifted_in(Interner),
|
||||
Substitution::from_iter(Interner, sig_tys.iter().cloned())
|
||||
.shifted_in(Interner),
|
||||
),
|
||||
})
|
||||
.intern(Interner);
|
||||
|
@ -317,16 +319,16 @@ impl<'a> InferenceContext<'a> {
|
|||
Expr::Call { callee, args, .. } => {
|
||||
let callee_ty = self.infer_expr(*callee, &Expectation::none());
|
||||
let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone());
|
||||
let mut res = None;
|
||||
let mut derefed_callee = callee_ty.clone();
|
||||
// manual loop to be able to access `derefs.table`
|
||||
while let Some((callee_deref_ty, _)) = derefs.next() {
|
||||
res = derefs.table.callable_sig(&callee_deref_ty, args.len());
|
||||
if res.is_some() {
|
||||
derefed_callee = callee_deref_ty;
|
||||
break;
|
||||
let (res, derefed_callee) = 'b: {
|
||||
// manual loop to be able to access `derefs.table`
|
||||
while let Some((callee_deref_ty, _)) = derefs.next() {
|
||||
let res = derefs.table.callable_sig(&callee_deref_ty, args.len());
|
||||
if res.is_some() {
|
||||
break 'b (res, callee_deref_ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
(None, callee_ty.clone())
|
||||
};
|
||||
// if the function is unresolved, we use is_varargs=true to
|
||||
// suppress the arg count diagnostic here
|
||||
let is_varargs =
|
||||
|
@ -382,12 +384,9 @@ impl<'a> InferenceContext<'a> {
|
|||
let expected = expected.adjust_for_branches(&mut self.table);
|
||||
|
||||
let result_ty = if arms.is_empty() {
|
||||
TyKind::Never.intern(Interner)
|
||||
self.result.standard_types.never.clone()
|
||||
} else {
|
||||
match &expected {
|
||||
Expectation::HasType(ty) => ty.clone(),
|
||||
_ => self.table.new_type_var(),
|
||||
}
|
||||
expected.coercion_target_type(&mut self.table)
|
||||
};
|
||||
let mut coerce = CoerceMany::new(result_ty);
|
||||
|
||||
|
@ -400,7 +399,7 @@ impl<'a> InferenceContext<'a> {
|
|||
if let Some(guard_expr) = arm.guard {
|
||||
self.infer_expr(
|
||||
guard_expr,
|
||||
&Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(Interner)),
|
||||
&Expectation::HasType(self.result.standard_types.bool_.clone()),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -425,7 +424,7 @@ impl<'a> InferenceContext<'a> {
|
|||
is_break: false,
|
||||
});
|
||||
};
|
||||
TyKind::Never.intern(Interner)
|
||||
self.result.standard_types.never.clone()
|
||||
}
|
||||
Expr::Break { expr, label } => {
|
||||
let val_ty = if let Some(expr) = *expr {
|
||||
|
@ -439,7 +438,7 @@ impl<'a> InferenceContext<'a> {
|
|||
// avoiding the borrowck
|
||||
let mut coerce = mem::replace(
|
||||
&mut ctxt.coerce,
|
||||
CoerceMany::new(self.result.standard_types.unknown.clone()),
|
||||
CoerceMany::new(expected.coercion_target_type(&mut self.table)),
|
||||
);
|
||||
|
||||
// FIXME: create a synthetic `()` during lowering so we have something to refer to here?
|
||||
|
@ -457,7 +456,7 @@ impl<'a> InferenceContext<'a> {
|
|||
});
|
||||
}
|
||||
}
|
||||
TyKind::Never.intern(Interner)
|
||||
self.result.standard_types.never.clone()
|
||||
}
|
||||
Expr::Return { expr } => {
|
||||
if let Some(expr) = expr {
|
||||
|
@ -466,7 +465,7 @@ impl<'a> InferenceContext<'a> {
|
|||
let unit = TyBuilder::unit();
|
||||
let _ = self.coerce(Some(tgt_expr), &unit, &self.return_ty.clone());
|
||||
}
|
||||
TyKind::Never.intern(Interner)
|
||||
self.result.standard_types.never.clone()
|
||||
}
|
||||
Expr::Yield { expr } => {
|
||||
if let Some((resume_ty, yield_ty)) = self.resume_yield_tys.clone() {
|
||||
|
@ -479,14 +478,14 @@ impl<'a> InferenceContext<'a> {
|
|||
resume_ty
|
||||
} else {
|
||||
// FIXME: report error (yield expr in non-generator)
|
||||
TyKind::Error.intern(Interner)
|
||||
self.result.standard_types.unknown.clone()
|
||||
}
|
||||
}
|
||||
Expr::Yeet { expr } => {
|
||||
if let &Some(expr) = expr {
|
||||
self.infer_expr_inner(expr, &Expectation::None);
|
||||
}
|
||||
TyKind::Never.intern(Interner)
|
||||
self.result.standard_types.never.clone()
|
||||
}
|
||||
Expr::RecordLit { path, fields, spread, .. } => {
|
||||
let (ty, def_id) = self.resolve_variant(path.as_deref(), false);
|
||||
|
@ -611,8 +610,8 @@ impl<'a> InferenceContext<'a> {
|
|||
}
|
||||
Expr::Cast { expr, type_ref } => {
|
||||
let cast_ty = self.make_ty(type_ref);
|
||||
let _inner_ty =
|
||||
self.infer_expr_inner(*expr, &Expectation::Castable(cast_ty.clone()));
|
||||
// FIXME: propagate the "castable to" expectation
|
||||
let _inner_ty = self.infer_expr_inner(*expr, &Expectation::None);
|
||||
// FIXME check the cast...
|
||||
cast_ty
|
||||
}
|
||||
|
@ -829,7 +828,7 @@ impl<'a> InferenceContext<'a> {
|
|||
self.infer_expr_coerce(initializer, &Expectation::has_type(elem_ty));
|
||||
self.infer_expr(
|
||||
repeat,
|
||||
&Expectation::has_type(
|
||||
&Expectation::HasType(
|
||||
TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner),
|
||||
),
|
||||
);
|
||||
|
@ -852,7 +851,7 @@ impl<'a> InferenceContext<'a> {
|
|||
TyKind::Array(coerce.complete(), len).intern(Interner)
|
||||
}
|
||||
Expr::Literal(lit) => match lit {
|
||||
Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(Interner),
|
||||
Literal::Bool(..) => self.result.standard_types.bool_.clone(),
|
||||
Literal::String(..) => {
|
||||
TyKind::Ref(Mutability::Not, static_lifetime(), TyKind::Str.intern(Interner))
|
||||
.intern(Interner)
|
||||
|
@ -1148,7 +1147,7 @@ impl<'a> InferenceContext<'a> {
|
|||
if let Some(expr) = else_branch {
|
||||
self.infer_expr_coerce(
|
||||
*expr,
|
||||
&Expectation::has_type(Ty::new(Interner, TyKind::Never)),
|
||||
&Expectation::HasType(self.result.standard_types.never.clone()),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ impl<'a> InferenceContext<'a> {
|
|||
let ty = TyBuilder::value_ty(self.db, typable, parent_substs)
|
||||
.fill(|x| {
|
||||
it.next().unwrap_or_else(|| match x {
|
||||
ParamKind::Type => TyKind::Error.intern(Interner).cast(Interner),
|
||||
ParamKind::Type => self.result.standard_types.unknown.clone().cast(Interner),
|
||||
ParamKind::Const(ty) => consteval::unknown_const_as_generic(ty.clone()),
|
||||
})
|
||||
})
|
||||
|
|
|
@ -3200,6 +3200,8 @@ fn func() {
|
|||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
// FIXME
|
||||
#[test]
|
||||
fn castable_to() {
|
||||
check_infer(
|
||||
|
@ -3224,10 +3226,60 @@ fn func() {
|
|||
120..122 '{}': ()
|
||||
138..184 '{ ...0]>; }': ()
|
||||
148..149 'x': Box<[i32; 0]>
|
||||
152..160 'Box::new': fn new<[i32; 0]>([i32; 0]) -> Box<[i32; 0]>
|
||||
152..164 'Box::new([])': Box<[i32; 0]>
|
||||
152..160 'Box::new': fn new<[{unknown}; 0]>([{unknown}; 0]) -> Box<[{unknown}; 0]>
|
||||
152..164 'Box::new([])': Box<[{unknown}; 0]>
|
||||
152..181 'Box::n...2; 0]>': Box<[i32; 0]>
|
||||
161..163 '[]': [i32; 0]
|
||||
161..163 '[]': [{unknown}; 0]
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn castable_to1() {
|
||||
check_infer(
|
||||
r#"
|
||||
struct Ark<T>(T);
|
||||
impl<T> Ark<T> {
|
||||
fn foo(&self) -> *const T {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
fn f<T>(t: Ark<T>) {
|
||||
Ark::foo(&t) as *const ();
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
47..51 'self': &Ark<T>
|
||||
65..88 '{ ... }': *const T
|
||||
75..82 '&self.0': &T
|
||||
76..80 'self': &Ark<T>
|
||||
76..82 'self.0': T
|
||||
99..100 't': Ark<T>
|
||||
110..144 '{ ... (); }': ()
|
||||
116..124 'Ark::foo': fn foo<T>(&Ark<T>) -> *const T
|
||||
116..128 'Ark::foo(&t)': *const T
|
||||
116..141 'Ark::f...nst ()': *const ()
|
||||
125..127 '&t': &Ark<T>
|
||||
126..127 't': Ark<T>
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
// FIXME
|
||||
#[test]
|
||||
fn castable_to2() {
|
||||
check_infer(
|
||||
r#"
|
||||
fn func() {
|
||||
let x = &0u32 as *const _;
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
10..44 '{ ...t _; }': ()
|
||||
20..21 'x': *const {unknown}
|
||||
24..29 '&0u32': &u32
|
||||
24..41 '&0u32 ...onst _': *const {unknown}
|
||||
25..29 '0u32': u32
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue