From c679482d7effad2ed9e18c24cdb96e6baefeb02c Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 5 Mar 2024 13:05:57 +0100 Subject: [PATCH] Add method resolution deref inference var test --- crates/hir-ty/src/infer/expr.rs | 14 ++++++-------- crates/hir-ty/src/infer/unify.rs | 17 +++++++++-------- crates/hir-ty/src/tests/method_resolution.rs | 15 +++++++++++++++ 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 231eea041b..a3dab1fd9d 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -312,15 +312,13 @@ impl InferenceContext<'_> { Expr::Call { callee, args, .. } => { let callee_ty = self.infer_expr(*callee, &Expectation::none()); let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone(), false); - 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); - } + let (res, derefed_callee) = loop { + let Some((callee_deref_ty, _)) = derefs.next() else { + break (None, callee_ty.clone()); + }; + if let Some(res) = derefs.table.callable_sig(&callee_deref_ty, args.len()) { + break (Some(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 diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs index c3614e4452..18029adbaf 100644 --- a/crates/hir-ty/src/infer/unify.rs +++ b/crates/hir-ty/src/infer/unify.rs @@ -289,14 +289,14 @@ impl<'a> InferenceTable<'a> { } fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty { + let is_diverging = self + .type_variable_table + .get(iv.index() as usize) + .map_or(false, |data| data.contains(TypeVariableFlags::DIVERGING)); + if is_diverging { + return TyKind::Never.intern(Interner); + } match kind { - _ if self - .type_variable_table - .get(iv.index() as usize) - .map_or(false, |data| data.contains(TypeVariableFlags::DIVERGING)) => - { - TyKind::Never - } TyVariableKind::General => TyKind::Error, TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)), TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)), @@ -438,6 +438,7 @@ impl<'a> InferenceTable<'a> { where T: HasInterner + TypeFoldable, { + // TODO check this vec here 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 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) .fill(|it| { let arg = match it { diff --git a/crates/hir-ty/src/tests/method_resolution.rs b/crates/hir-ty/src/tests/method_resolution.rs index c837fae3fe..049941a94f 100644 --- a/crates/hir-ty/src/tests/method_resolution.rs +++ b/crates/hir-ty/src/tests/method_resolution.rs @@ -1795,6 +1795,21 @@ fn test() { ); } +#[test] +fn deref_into_inference_var() { + check_types( + r#" +//- minicore:deref +struct A(T); +impl core::ops::Deref for A {} +impl A { fn foo(&self) {} } +fn main() { + A(0).foo(); + //^^^^^^^^^^ () +} +"#, + ); +} #[test] fn receiver_adjustment_autoref() { check(