mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-14 06:03:58 +00:00
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 <lukastw97@gmail.com>
This commit is contained in:
commit
c69f6f31d1
2 changed files with 46 additions and 1 deletions
|
@ -74,6 +74,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
|
||||||
// <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
|
// <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
|
||||||
Some(trait_ref) => {
|
Some(trait_ref) => {
|
||||||
let path = Path::from_src(trait_ref.path()?, hygiene)?;
|
let path = Path::from_src(trait_ref.path()?, hygiene)?;
|
||||||
|
let num_segments = path.mod_path.segments.len();
|
||||||
kind = path.mod_path.kind;
|
kind = path.mod_path.kind;
|
||||||
|
|
||||||
let mut prefix_segments = path.mod_path.segments;
|
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>
|
||||||
generic_args.extend(prefix_args);
|
generic_args.extend(prefix_args);
|
||||||
|
|
||||||
// Insert the type reference (T in the above example) as Self parameter for the trait
|
// 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() {
|
if last_segment.is_none() {
|
||||||
*last_segment = Some(Arc::new(GenericArgs::empty()));
|
*last_segment = Some(Arc::new(GenericArgs::empty()));
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 = <F as foo::Foo>::Target;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo() {
|
||||||
|
use foo::Bar;
|
||||||
|
let x = <F as Bar>::boo();
|
||||||
|
}
|
||||||
|
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
132..163 '{ ... }': Bar::Output<Self>
|
||||||
|
146..153 'loop {}': !
|
||||||
|
151..153 '{}': ()
|
||||||
|
306..358 '{ ...o(); }': ()
|
||||||
|
334..335 'x': ()
|
||||||
|
338..353 '<F as Bar>::boo': fn boo<F>() -> <F as Bar>::Output
|
||||||
|
338..355 '<F as ...:boo()': ()
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue