From 6f0575f08adca0c8a8f38a301913a1cfe636eb94 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 30 Mar 2021 21:43:23 +0200 Subject: Fix generic arguments being incorrectly offset in qualified trait casts --- crates/hir_def/src/path/lower.rs | 4 +++- crates/hir_ty/src/tests/traits.rs | 43 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs index 505493a74..4de951fd3 100644 --- a/crates/hir_def/src/path/lower.rs +++ b/crates/hir_def/src/path/lower.rs @@ -74,6 +74,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option // >::Foo desugars to Trait::Foo Some(trait_ref) => { let path = Path::from_src(trait_ref.path()?, hygiene)?; + let num_segments = path.mod_path.segments.len(); kind = path.mod_path.kind; let mut prefix_segments = path.mod_path.segments; @@ -85,7 +86,8 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option generic_args.extend(prefix_args); // Insert the type reference (T in the above example) as Self parameter for the trait - let last_segment = generic_args.last_mut()?; + let last_segment = + generic_args.iter_mut().rev().nth(num_segments.saturating_sub(1))?; if last_segment.is_none() { *last_segment = Some(Arc::new(GenericArgs::empty())); }; diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 2ba97f814..65b71fdfa 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs @@ -3370,3 +3370,46 @@ fn test() { "#]], ) } + +#[test] +fn qualified_path_as_qualified_trait() { + check_infer( + r#" +mod foo { + + pub trait Foo { + type Target; + } + pub trait Bar { + type Output; + fn boo() -> Self::Output { + loop {} + } + } +} + +struct F; +impl foo::Foo for F { + type Target = (); +} +impl foo::Bar for F { + type Output = ::Target; +} + +fn foo() { + use foo::Bar; + let x = ::boo(); +} + + "#, + expect![[r#" + 132..163 '{ ... }': Bar::Output + 146..153 'loop {}': ! + 151..153 '{}': () + 306..358 '{ ...o(); }': () + 334..335 'x': () + 338..353 '::boo': fn boo() -> ::Output + 338..355 '