internal: Revert castable expectation and simplify

This commit is contained in:
Lukas Wirth 2023-02-10 16:08:47 +01:00
parent 8f5deb4ff2
commit 79492cb8ae
5 changed files with 88 additions and 31 deletions

View File

@ -219,6 +219,7 @@ struct InternedStandardTypes {
unknown: Ty,
bool_: Ty,
unit: Ty,
never: Ty,
}
impl Default for InternedStandardTypes {
@ -227,6 +228,7 @@ fn default() -> Self {
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 @@ fn resolve_va_list(&self) -> Option<AdtId> {
pub(crate) enum Expectation {
None,
HasType(Ty),
#[allow(dead_code)]
Castable(Ty),
RValueLikeUnsized(Ty),
}
@ -1102,6 +1105,10 @@ fn only_has_type(&self, table: &mut unify::InferenceTable<'_>) -> Option<Ty> {
}
}
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

View File

@ -51,7 +51,7 @@ fn deduce_sig_from_dyn_ty(&self, dyn_ty: &DynTy) -> Option<FnPointer> {
.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`

View File

@ -87,16 +87,15 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
&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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
.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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
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
@ -382,12 +383,9 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
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 +398,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
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 +423,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
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 +437,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
// 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 +455,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
});
}
}
TyKind::Never.intern(Interner)
self.result.standard_types.never.clone()
}
Expr::Return { expr } => {
if let Some(expr) = expr {
@ -466,7 +464,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
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 +477,14 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
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 +609,8 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
}
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 +827,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
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 +850,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
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 +1146,7 @@ fn infer_block(
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()),
);
}

View File

@ -112,7 +112,7 @@ fn resolve_value_path(
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()),
})
})

View File

@ -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
"#]],
);
}