Skip to content

Commit c69f6f3

Browse files
bors[bot]Veykril
andauthored
Merge #8266
8266: Fix generic arguments being incorrectly offset in qualified trait casts r=flodiebold a=Veykril We reverse the segments and generic args of the lowered path after building it, this wasn't accounted for when inserting the self parameter in `Type as Trait` segments. Fixes #5886 Co-authored-by: Lukas Wirth <[email protected]>
2 parents 2436621 + 6f0575f commit c69f6f3

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

crates/hir_def/src/path/lower.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
7474
// <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
7575
Some(trait_ref) => {
7676
let path = Path::from_src(trait_ref.path()?, hygiene)?;
77+
let num_segments = path.mod_path.segments.len();
7778
kind = path.mod_path.kind;
7879

7980
let mut prefix_segments = path.mod_path.segments;
@@ -85,7 +86,8 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
8586
generic_args.extend(prefix_args);
8687

8788
// Insert the type reference (T in the above example) as Self parameter for the trait
88-
let last_segment = generic_args.last_mut()?;
89+
let last_segment =
90+
generic_args.iter_mut().rev().nth(num_segments.saturating_sub(1))?;
8991
if last_segment.is_none() {
9092
*last_segment = Some(Arc::new(GenericArgs::empty()));
9193
};

crates/hir_ty/src/tests/traits.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3370,3 +3370,46 @@ fn test() {
33703370
"#]],
33713371
)
33723372
}
3373+
3374+
#[test]
3375+
fn qualified_path_as_qualified_trait() {
3376+
check_infer(
3377+
r#"
3378+
mod foo {
3379+
3380+
pub trait Foo {
3381+
type Target;
3382+
}
3383+
pub trait Bar {
3384+
type Output;
3385+
fn boo() -> Self::Output {
3386+
loop {}
3387+
}
3388+
}
3389+
}
3390+
3391+
struct F;
3392+
impl foo::Foo for F {
3393+
type Target = ();
3394+
}
3395+
impl foo::Bar for F {
3396+
type Output = <F as foo::Foo>::Target;
3397+
}
3398+
3399+
fn foo() {
3400+
use foo::Bar;
3401+
let x = <F as Bar>::boo();
3402+
}
3403+
3404+
"#,
3405+
expect![[r#"
3406+
132..163 '{ ... }': Bar::Output<Self>
3407+
146..153 'loop {}': !
3408+
151..153 '{}': ()
3409+
306..358 '{ ...o(); }': ()
3410+
334..335 'x': ()
3411+
338..353 '<F as Bar>::boo': fn boo<F>() -> <F as Bar>::Output
3412+
338..355 '<F as ...:boo()': ()
3413+
"#]],
3414+
);
3415+
}

0 commit comments

Comments
 (0)