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:
bors 2023-02-10 15:44:04 +00:00
commit d9c020d426
5 changed files with 101 additions and 43 deletions

View File

@ -219,6 +219,7 @@ struct InternedStandardTypes {
unknown: Ty, unknown: Ty,
bool_: Ty, bool_: Ty,
unit: Ty, unit: Ty,
never: Ty,
} }
impl Default for InternedStandardTypes { impl Default for InternedStandardTypes {
@ -227,6 +228,7 @@ impl Default for InternedStandardTypes {
unknown: TyKind::Error.intern(Interner), unknown: TyKind::Error.intern(Interner),
bool_: TyKind::Scalar(Scalar::Bool).intern(Interner), bool_: TyKind::Scalar(Scalar::Bool).intern(Interner),
unit: TyKind::Tuple(0, Substitution::empty(Interner)).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 { pub(crate) enum Expectation {
None, None,
HasType(Ty), HasType(Ty),
#[allow(dead_code)]
Castable(Ty), Castable(Ty),
RValueLikeUnsized(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: /// Comment copied from rustc:
/// Disregard "castable to" expectations because they /// Disregard "castable to" expectations because they
/// can lead us astray. Consider for example `if cond /// can lead us astray. Consider for example `if cond

View File

@ -51,7 +51,7 @@ impl InferenceContext<'_> {
.map(to_chalk_trait_id) .map(to_chalk_trait_id)
.collect(); .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)]); let bounds = dyn_ty.bounds.clone().substitute(Interner, &[self_ty.cast(Interner)]);
for bound in bounds.iter(Interner) { for bound in bounds.iter(Interner) {
// NOTE(skip_binders): the extracted types are rebound by the returned `FnPointer` // 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)?; let arg = projection.substitution.as_slice(Interner).get(1)?;
if let Some(subst) = arg.ty(Interner)?.as_tuple() { if let Some(subst) = arg.ty(Interner)?.as_tuple() {
let generic_args = subst.as_slice(Interner); 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 { for arg in generic_args {
sig_tys.push(arg.ty(Interner)?.clone()); sig_tys.push(arg.ty(Interner)?.clone());
} }

View File

@ -87,16 +87,15 @@ impl<'a> InferenceContext<'a> {
let expected = &expected.adjust_for_branches(&mut self.table); let expected = &expected.adjust_for_branches(&mut self.table);
self.infer_expr( self.infer_expr(
condition, 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 condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
let mut both_arms_diverge = Diverges::Always; 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); let then_ty = self.infer_expr_inner(then_branch, expected);
both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe); 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); coerce.coerce(self, Some(then_branch), &then_ty);
let else_ty = match else_branch { let else_ty = match else_branch {
Some(else_branch) => self.infer_expr_inner(else_branch, expected), Some(else_branch) => self.infer_expr_inner(else_branch, expected),
@ -113,7 +112,7 @@ impl<'a> InferenceContext<'a> {
&Expr::Let { pat, expr } => { &Expr::Let { pat, expr } => {
let input_ty = self.infer_expr(expr, &Expectation::none()); let input_ty = self.infer_expr(expr, &Expectation::none());
self.infer_pat(pat, &input_ty, BindingMode::default()); 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: _ } => { Expr::Block { statements, tail, label, id: _ } => {
let old_resolver = mem::replace( let old_resolver = mem::replace(
@ -188,10 +187,12 @@ impl<'a> InferenceContext<'a> {
.intern(Interner) .intern(Interner)
} }
&Expr::Loop { body, label } => { &Expr::Loop { body, label } => {
// FIXME: should be:
// let ty = expected.coercion_target_type(&mut self.table);
let ty = self.table.new_type_var(); let ty = self.table.new_type_var();
let (breaks, ()) = let (breaks, ()) =
self.with_breakable_ctx(BreakableKind::Loop, ty, label, |this| { 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 { match breaks {
@ -199,16 +200,16 @@ impl<'a> InferenceContext<'a> {
self.diverges = Diverges::Maybe; self.diverges = Diverges::Maybe;
breaks breaks
} }
None => TyKind::Never.intern(Interner), None => self.result.standard_types.never.clone(),
} }
} }
&Expr::While { condition, body, label } => { &Expr::While { condition, body, label } => {
self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| { self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| {
this.infer_expr( this.infer_expr(
condition, 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 // 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.infer_pat(pat, &pat_ty, BindingMode::default());
self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| { 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 // 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 } => { Expr::Closure { body, args, ret_type, arg_types, closure_kind } => {
assert_eq!(args.len(), arg_types.len()); 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 // collect explicitly written argument types
for arg_type in arg_types.iter() { for arg_type in arg_types.iter() {
@ -255,7 +256,8 @@ impl<'a> InferenceContext<'a> {
num_binders: 0, num_binders: 0,
sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false }, sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false },
substitution: FnSubst( 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); .intern(Interner);
@ -317,16 +319,16 @@ impl<'a> InferenceContext<'a> {
Expr::Call { callee, args, .. } => { Expr::Call { callee, args, .. } => {
let callee_ty = self.infer_expr(*callee, &Expectation::none()); let callee_ty = self.infer_expr(*callee, &Expectation::none());
let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone()); let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone());
let mut res = None; let (res, derefed_callee) = 'b: {
let mut derefed_callee = callee_ty.clone(); // manual loop to be able to access `derefs.table`
// manual loop to be able to access `derefs.table` while let Some((callee_deref_ty, _)) = derefs.next() {
while let Some((callee_deref_ty, _)) = derefs.next() { let res = derefs.table.callable_sig(&callee_deref_ty, args.len());
res = derefs.table.callable_sig(&callee_deref_ty, args.len()); if res.is_some() {
if res.is_some() { break 'b (res, callee_deref_ty);
derefed_callee = callee_deref_ty; }
break;
} }
} (None, callee_ty.clone())
};
// if the function is unresolved, we use is_varargs=true to // if the function is unresolved, we use is_varargs=true to
// suppress the arg count diagnostic here // suppress the arg count diagnostic here
let is_varargs = let is_varargs =
@ -382,12 +384,9 @@ impl<'a> InferenceContext<'a> {
let expected = expected.adjust_for_branches(&mut self.table); let expected = expected.adjust_for_branches(&mut self.table);
let result_ty = if arms.is_empty() { let result_ty = if arms.is_empty() {
TyKind::Never.intern(Interner) self.result.standard_types.never.clone()
} else { } else {
match &expected { expected.coercion_target_type(&mut self.table)
Expectation::HasType(ty) => ty.clone(),
_ => self.table.new_type_var(),
}
}; };
let mut coerce = CoerceMany::new(result_ty); let mut coerce = CoerceMany::new(result_ty);
@ -400,7 +399,7 @@ impl<'a> InferenceContext<'a> {
if let Some(guard_expr) = arm.guard { if let Some(guard_expr) = arm.guard {
self.infer_expr( self.infer_expr(
guard_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, is_break: false,
}); });
}; };
TyKind::Never.intern(Interner) self.result.standard_types.never.clone()
} }
Expr::Break { expr, label } => { Expr::Break { expr, label } => {
let val_ty = if let Some(expr) = *expr { let val_ty = if let Some(expr) = *expr {
@ -439,7 +438,7 @@ impl<'a> InferenceContext<'a> {
// avoiding the borrowck // avoiding the borrowck
let mut coerce = mem::replace( let mut coerce = mem::replace(
&mut ctxt.coerce, &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? // 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 } => { Expr::Return { expr } => {
if let Some(expr) = expr { if let Some(expr) = expr {
@ -466,7 +465,7 @@ impl<'a> InferenceContext<'a> {
let unit = TyBuilder::unit(); let unit = TyBuilder::unit();
let _ = self.coerce(Some(tgt_expr), &unit, &self.return_ty.clone()); let _ = self.coerce(Some(tgt_expr), &unit, &self.return_ty.clone());
} }
TyKind::Never.intern(Interner) self.result.standard_types.never.clone()
} }
Expr::Yield { expr } => { Expr::Yield { expr } => {
if let Some((resume_ty, yield_ty)) = self.resume_yield_tys.clone() { if let Some((resume_ty, yield_ty)) = self.resume_yield_tys.clone() {
@ -479,14 +478,14 @@ impl<'a> InferenceContext<'a> {
resume_ty resume_ty
} else { } else {
// FIXME: report error (yield expr in non-generator) // FIXME: report error (yield expr in non-generator)
TyKind::Error.intern(Interner) self.result.standard_types.unknown.clone()
} }
} }
Expr::Yeet { expr } => { Expr::Yeet { expr } => {
if let &Some(expr) = expr { if let &Some(expr) = expr {
self.infer_expr_inner(expr, &Expectation::None); self.infer_expr_inner(expr, &Expectation::None);
} }
TyKind::Never.intern(Interner) self.result.standard_types.never.clone()
} }
Expr::RecordLit { path, fields, spread, .. } => { Expr::RecordLit { path, fields, spread, .. } => {
let (ty, def_id) = self.resolve_variant(path.as_deref(), false); let (ty, def_id) = self.resolve_variant(path.as_deref(), false);
@ -611,8 +610,8 @@ impl<'a> InferenceContext<'a> {
} }
Expr::Cast { expr, type_ref } => { Expr::Cast { expr, type_ref } => {
let cast_ty = self.make_ty(type_ref); let cast_ty = self.make_ty(type_ref);
let _inner_ty = // FIXME: propagate the "castable to" expectation
self.infer_expr_inner(*expr, &Expectation::Castable(cast_ty.clone())); let _inner_ty = self.infer_expr_inner(*expr, &Expectation::None);
// FIXME check the cast... // FIXME check the cast...
cast_ty cast_ty
} }
@ -829,7 +828,7 @@ impl<'a> InferenceContext<'a> {
self.infer_expr_coerce(initializer, &Expectation::has_type(elem_ty)); self.infer_expr_coerce(initializer, &Expectation::has_type(elem_ty));
self.infer_expr( self.infer_expr(
repeat, repeat,
&Expectation::has_type( &Expectation::HasType(
TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner),
), ),
); );
@ -852,7 +851,7 @@ impl<'a> InferenceContext<'a> {
TyKind::Array(coerce.complete(), len).intern(Interner) TyKind::Array(coerce.complete(), len).intern(Interner)
} }
Expr::Literal(lit) => match lit { Expr::Literal(lit) => match lit {
Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(Interner), Literal::Bool(..) => self.result.standard_types.bool_.clone(),
Literal::String(..) => { Literal::String(..) => {
TyKind::Ref(Mutability::Not, static_lifetime(), TyKind::Str.intern(Interner)) TyKind::Ref(Mutability::Not, static_lifetime(), TyKind::Str.intern(Interner))
.intern(Interner) .intern(Interner)
@ -1148,7 +1147,7 @@ impl<'a> InferenceContext<'a> {
if let Some(expr) = else_branch { if let Some(expr) = else_branch {
self.infer_expr_coerce( self.infer_expr_coerce(
*expr, *expr,
&Expectation::has_type(Ty::new(Interner, TyKind::Never)), &Expectation::HasType(self.result.standard_types.never.clone()),
); );
} }

View File

@ -112,7 +112,7 @@ impl<'a> InferenceContext<'a> {
let ty = TyBuilder::value_ty(self.db, typable, parent_substs) let ty = TyBuilder::value_ty(self.db, typable, parent_substs)
.fill(|x| { .fill(|x| {
it.next().unwrap_or_else(|| match 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()), ParamKind::Const(ty) => consteval::unknown_const_as_generic(ty.clone()),
}) })
}) })

View File

@ -3200,6 +3200,8 @@ fn func() {
"#, "#,
); );
} }
// FIXME
#[test] #[test]
fn castable_to() { fn castable_to() {
check_infer( check_infer(
@ -3224,10 +3226,60 @@ fn func() {
120..122 '{}': () 120..122 '{}': ()
138..184 '{ ...0]>; }': () 138..184 '{ ...0]>; }': ()
148..149 'x': Box<[i32; 0]> 148..149 'x': Box<[i32; 0]>
152..160 'Box::new': fn new<[i32; 0]>([i32; 0]) -> Box<[i32; 0]> 152..160 'Box::new': fn new<[{unknown}; 0]>([{unknown}; 0]) -> Box<[{unknown}; 0]>
152..164 'Box::new([])': Box<[i32; 0]> 152..164 'Box::new([])': Box<[{unknown}; 0]>
152..181 'Box::n...2; 0]>': Box<[i32; 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
"#]], "#]],
); );
} }