Unnamed repository; edit this file 'description' to name the repository.
Add method resolution deref inference var test
Lukas Wirth 2024-03-11
parent d21f888 · commit c679482
-rw-r--r--crates/hir-ty/src/infer/expr.rs14
-rw-r--r--crates/hir-ty/src/infer/unify.rs17
-rw-r--r--crates/hir-ty/src/tests/method_resolution.rs15
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<Interner = Interner> + TypeFoldable<Interner>,
{
+ // 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
@@ -1796,6 +1796,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]
fn receiver_adjustment_autoref() {
check(
r#"