evaluate UnevaluatedConst in unify

This commit is contained in:
hkalbasi 2023-05-25 19:37:04 +03:30
parent efd3094aba
commit 7ef185d65e
4 changed files with 89 additions and 1 deletions

View File

@ -575,6 +575,9 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
let field_ty = field_def.map_or(self.err_ty(), |it| {
field_types[it.local_id].clone().substitute(Interner, &substs)
});
// Field type might have some unknown types
// FIXME: we may want to emit a single type variable for all instance of type fields?
let field_ty = self.insert_type_vars(field_ty);
self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty));
}
if let Some(expr) = spread {

View File

@ -781,8 +781,16 @@ pub(super) fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
pub(super) fn insert_const_vars_shallow(&mut self, c: Const) -> Const {
let data = c.data(Interner);
match &data.value {
ConstValue::Concrete(cc) => match cc.interned {
ConstValue::Concrete(cc) => match &cc.interned {
crate::ConstScalar::Unknown => self.new_const_var(data.ty.clone()),
// try to evaluate unevaluated const. Replace with new var if const eval failed.
crate::ConstScalar::UnevaluatedConst(id, subst) => {
if let Ok(eval) = self.db.const_eval(*id, subst.clone()) {
eval
} else {
self.new_const_var(data.ty.clone())
}
}
_ => c,
},
_ => c,

View File

@ -1837,3 +1837,58 @@ fn foo() {
}",
);
}
#[test]
fn regression_14844() {
check_no_mismatches(
r#"
pub type Ty = Unknown;
pub struct Inner<T>();
pub struct Outer {
pub inner: Inner<Ty>,
}
fn main() {
_ = Outer {
inner: Inner::<i32>(),
};
}
"#,
);
check_no_mismatches(
r#"
pub const ONE: usize = 1;
pub struct Inner<const P: usize>();
pub struct Outer {
pub inner: Inner<ONE>,
}
fn main() {
_ = Outer {
inner: Inner::<1>(),
};
}
"#,
);
check_no_mismatches(
r#"
pub const ONE: usize = unknown();
pub struct Inner<const P: usize>();
pub struct Outer {
pub inner: Inner<ONE>,
}
fn main() {
_ = Outer {
inner: Inner::<1>(),
};
}
"#,
);
}

View File

@ -644,6 +644,28 @@ fn h() {
);
}
#[test]
fn evaluate_const_generics_in_types() {
check_diagnostics(
r#"
pub const ONE: usize = 1;
pub struct Inner<const P: usize>();
pub struct Outer {
pub inner: Inner<ONE>,
}
fn main() {
_ = Outer {
inner: Inner::<2>(),
//^^^^^^^^^^^^ error: expected Inner<1>, found Inner<2>
};
}
"#,
);
}
#[test]
fn type_mismatch_pat_smoke_test() {
check_diagnostics(