Add method resolution deref inference var test

This commit is contained in:
Lukas Wirth 2024-03-05 13:05:57 +01:00
parent d21f88883b
commit c679482d7e
3 changed files with 30 additions and 16 deletions

View file

@ -312,15 +312,13 @@ impl InferenceContext<'_> {
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(), false); let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone(), false);
let (res, derefed_callee) = 'b: { let (res, derefed_callee) = loop {
// manual loop to be able to access `derefs.table` let Some((callee_deref_ty, _)) = derefs.next() else {
while let Some((callee_deref_ty, _)) = derefs.next() { break (None, callee_ty.clone());
let res = derefs.table.callable_sig(&callee_deref_ty, args.len()); };
if res.is_some() { if let Some(res) = derefs.table.callable_sig(&callee_deref_ty, args.len()) {
break 'b (res, callee_deref_ty); break (Some(res), callee_deref_ty);
} }
}
(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

View file

@ -289,14 +289,14 @@ impl<'a> InferenceTable<'a> {
} }
fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty { fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
match kind { let is_diverging = self
_ if self
.type_variable_table .type_variable_table
.get(iv.index() as usize) .get(iv.index() as usize)
.map_or(false, |data| data.contains(TypeVariableFlags::DIVERGING)) => .map_or(false, |data| data.contains(TypeVariableFlags::DIVERGING));
{ if is_diverging {
TyKind::Never return TyKind::Never.intern(Interner);
} }
match kind {
TyVariableKind::General => TyKind::Error, TyVariableKind::General => TyKind::Error,
TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)), TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)),
TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)), TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)),
@ -438,6 +438,7 @@ impl<'a> InferenceTable<'a> {
where where
T: HasInterner<Interner = Interner> + TypeFoldable<Interner>, T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
{ {
// TODO check this vec here
self.resolve_with_fallback_inner(&mut Vec::new(), t, &fallback) self.resolve_with_fallback_inner(&mut Vec::new(), t, &fallback)
} }
@ -798,7 +799,7 @@ impl<'a> InferenceTable<'a> {
let trait_data = self.db.trait_data(fn_once_trait); let trait_data = self.db.trait_data(fn_once_trait);
let output_assoc_type = trait_data.associated_type_by_name(&name![Output])?; let output_assoc_type = trait_data.associated_type_by_name(&name![Output])?;
let mut arg_tys = vec![]; let mut arg_tys = Vec::with_capacity(num_args);
let arg_ty = TyBuilder::tuple(num_args) let arg_ty = TyBuilder::tuple(num_args)
.fill(|it| { .fill(|it| {
let arg = match it { let arg = match it {

View file

@ -1795,6 +1795,21 @@ fn test() {
); );
} }
#[test]
fn deref_into_inference_var() {
check_types(
r#"
//- minicore:deref
struct A<T>(T);
impl core::ops::Deref for A<u32> {}
impl A<i32> { fn foo(&self) {} }
fn main() {
A(0).foo();
//^^^^^^^^^^ ()
}
"#,
);
}
#[test] #[test]
fn receiver_adjustment_autoref() { fn receiver_adjustment_autoref() {
check( check(