From f47dc4de8d7aadea17dba023ece70e5b170274b1 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 14 Feb 2020 21:08:25 +0100 Subject: Check that impl self type matches up with expected self type in path mode Fixes #3144. --- crates/ra_hir_ty/src/marks.rs | 1 + crates/ra_hir_ty/src/method_resolution.rs | 9 +++++++ crates/ra_hir_ty/src/tests/method_resolution.rs | 32 +++++++++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/crates/ra_hir_ty/src/marks.rs b/crates/ra_hir_ty/src/marks.rs index 0f754eb9c..4e0828425 100644 --- a/crates/ra_hir_ty/src/marks.rs +++ b/crates/ra_hir_ty/src/marks.rs @@ -4,6 +4,7 @@ test_utils::marks!( type_var_cycles_resolve_completely type_var_cycles_resolve_as_possible type_var_resolves_to_int_var + impl_self_type_match_without_receiver match_ergonomics_ref coerce_merge_fail_fallback ); diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 5283bff28..4f8c52433 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs @@ -425,6 +425,15 @@ fn iterate_inherent_methods( if !is_valid_candidate(db, name, receiver_ty, item, self_ty) { continue; } + // we have to check whether the self type unifies with the type + // that the impl is for. If we have a receiver type, this + // already happens in `is_valid_candidate` above; if not, we + // check it here + if receiver_ty.is_none() && inherent_impl_substs(db, impl_block, self_ty).is_none() + { + test_utils::tested_by!(impl_self_type_match_without_receiver); + continue; + } if let Some(result) = callback(&self_ty.value, item) { return Some(result); } diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs index 1722563aa..1f767d324 100644 --- a/crates/ra_hir_ty/src/tests/method_resolution.rs +++ b/crates/ra_hir_ty/src/tests/method_resolution.rs @@ -963,6 +963,38 @@ fn test() { S2.into()<|>; } assert_eq!(t, "{unknown}"); } +#[test] +fn method_resolution_overloaded_method() { + test_utils::covers!(impl_self_type_match_without_receiver); + let t = type_at( + r#" +//- main.rs +struct Wrapper(T); +struct Foo(T); +struct Bar(T); + +impl Wrapper> { + pub fn new(foo_: T) -> Self { + Wrapper(Foo(foo_)) + } +} + +impl Wrapper> { + pub fn new(bar_: T) -> Self { + Wrapper(Bar(bar_)) + } +} + +fn main() { + let a = Wrapper::>::new(1.0); + let b = Wrapper::>::new(1.0); + (a, b)<|>; +} +"#, + ); + assert_eq!(t, "(Wrapper>, Wrapper>)") +} + #[test] fn method_resolution_encountering_fn_type() { type_at( -- cgit v1.2.3