From 759cb07891d6c9583095d7a1423619b36bc3d547 Mon Sep 17 00:00:00 2001 From: cynecx Date: Mon, 31 May 2021 20:04:18 +0200 Subject: hir_ty: use correct receiver_ty in method resolution --- crates/hir_ty/src/infer/expr.rs | 13 +----- crates/hir_ty/src/method_resolution.rs | 3 +- crates/hir_ty/src/tests/simple.rs | 78 ++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 12 deletions(-) (limited to 'crates') diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 41ef45326..f73bf43b2 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -890,7 +890,7 @@ impl<'a> InferenceContext<'a> { method_name, ) }); - let (derefed_receiver_ty, method_ty, substs) = match resolved { + let (receiver_ty, method_ty, substs) = match resolved { Some((ty, func)) => { let ty = canonicalized_receiver.decanonicalize_ty(ty); let generics = generics(self.db.upcast(), func.into()); @@ -916,16 +916,7 @@ impl<'a> InferenceContext<'a> { } None => (self.err_ty(), Vec::new(), self.err_ty()), }; - // Apply autoref so the below unification works correctly - // FIXME: return correct autorefs from lookup_method - let actual_receiver_ty = match self.resolve_ty_shallow(&expected_receiver_ty).as_reference() - { - Some((_, lifetime, mutability)) => { - TyKind::Ref(mutability, lifetime, derefed_receiver_ty).intern(&Interner) - } - _ => derefed_receiver_ty, - }; - self.unify(&expected_receiver_ty, &actual_receiver_ty); + self.unify(&expected_receiver_ty, &receiver_ty); self.check_call_arguments(args, ¶m_tys); self.normalize_associated_types_in(ret_ty) diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 08e385a42..af6b6cda7 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -721,7 +721,8 @@ fn iterate_inherent_methods( cov_mark::hit!(impl_self_type_match_without_receiver); continue; } - if callback(&self_ty.value, item) { + let receiver_ty = receiver_ty.map(|x| &x.value).unwrap_or(&self_ty.value); + if callback(receiver_ty, item) { return true; } } diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs index 5c70a1fc0..ac312981d 100644 --- a/crates/hir_ty/src/tests/simple.rs +++ b/crates/hir_ty/src/tests/simple.rs @@ -2634,3 +2634,81 @@ fn f() { "#]], ) } + +#[test] +fn infer_boxed_self_receiver() { + check_infer( + r#" +#[lang = "deref"] +pub trait Deref { + type Target; + fn deref(&self) -> &Self::Target; +} + +struct Box(T); + +impl Deref for Box { + type Target = T; + fn deref(&self) -> &Self::Target; +} + +struct Foo(T); + +impl Foo { + fn get_inner<'a>(self: &'a Box) -> &'a T {} + + fn get_self<'a>(self: &'a Box) -> &'a Self {} + + fn into_inner(self: Box) -> Self {} +} + +fn main() { + let boxed = Box(Foo(0_i32)); + + let bad1 = boxed.get_inner(); + let good1 = Foo::get_inner(&boxed); + + let bad2 = boxed.get_self(); + let good2 = Foo::get_self(&boxed); + + let inner = boxed.into_inner(); +} + "#, + expect![[r#" + 67..71 'self': &Self + 175..179 'self': &Box + 259..263 'self': &Box> + 289..291 '{}': () + 313..317 'self': &Box> + 346..348 '{}': () + 368..372 'self': Box> + 393..395 '{}': () + 409..630 '{ ...r(); }': () + 419..424 'boxed': Box> + 427..430 'Box': Box>(Foo) -> Box> + 427..442 'Box(Foo(0_i32))': Box> + 431..434 'Foo': Foo(i32) -> Foo + 431..441 'Foo(0_i32)': Foo + 435..440 '0_i32': i32 + 453..457 'bad1': &i32 + 460..465 'boxed': Box> + 460..477 'boxed....nner()': &i32 + 487..492 'good1': &i32 + 495..509 'Foo::get_inner': fn get_inner(&Box>) -> &i32 + 495..517 'Foo::g...boxed)': &i32 + 510..516 '&boxed': &Box> + 511..516 'boxed': Box> + 528..532 'bad2': &Foo + 535..540 'boxed': Box> + 535..551 'boxed....self()': &Foo + 561..566 'good2': &Foo + 569..582 'Foo::get_self': fn get_self(&Box>) -> &Foo + 569..590 'Foo::g...boxed)': &Foo + 583..589 '&boxed': &Box> + 584..589 'boxed': Box> + 601..606 'inner': Foo + 609..614 'boxed': Box> + 609..627 'boxed....nner()': Foo + "#]], + ); +} -- cgit v1.2.3