mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-14 06:03:58 +00:00
Merge #5423
5423: Correctly resolve assoc. types in path bindings r=matklad a=jonas-schievink Previously invoking goto def on `impl Iterator<Item<|> = ()>` would go to `Iterator`, not `Item`. This fixes that. Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
This commit is contained in:
commit
2777f8c295
2 changed files with 102 additions and 0 deletions
|
@ -881,6 +881,86 @@ pub mod module {
|
||||||
macro_rules! _mac { () => { () } }
|
macro_rules! _mac { () => { () } }
|
||||||
pub use crate::_mac as mac;
|
pub use crate::_mac as mac;
|
||||||
}
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_def_for_assoc_ty_in_path() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
trait Iterator {
|
||||||
|
type Item;
|
||||||
|
//^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f() -> impl Iterator<Item<|> = u8> {}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_def_for_assoc_ty_in_path_multiple() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
trait Iterator {
|
||||||
|
type A;
|
||||||
|
//^
|
||||||
|
type B;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f() -> impl Iterator<A<|> = u8, B = ()> {}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
trait Iterator {
|
||||||
|
type A;
|
||||||
|
type B;
|
||||||
|
//^
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f() -> impl Iterator<A = u8, B<|> = ()> {}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_def_for_assoc_ty_ufcs() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
trait Iterator {
|
||||||
|
type Item;
|
||||||
|
//^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
fn g() -> <() as Iterator<Item<|> = ()>>::Item {}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_def_for_assoc_ty_ufcs_multiple() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
trait Iterator {
|
||||||
|
type A;
|
||||||
|
//^
|
||||||
|
type B;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn g() -> <() as Iterator<A<|> = (), B = u8>>::B {}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
trait Iterator {
|
||||||
|
type A;
|
||||||
|
type B;
|
||||||
|
//^
|
||||||
|
}
|
||||||
|
|
||||||
|
fn g() -> <() as Iterator<A = (), B<|> = u8>>::A {}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -254,6 +254,28 @@ pub fn classify_name_ref(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ast::AssocTypeArg::cast(parent.clone()).is_some() {
|
||||||
|
// `Trait<Assoc = Ty>`
|
||||||
|
// ^^^^^
|
||||||
|
let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?;
|
||||||
|
let resolved = sema.resolve_path(&path)?;
|
||||||
|
if let PathResolution::Def(ModuleDef::Trait(tr)) = resolved {
|
||||||
|
if let Some(ty) = tr
|
||||||
|
.items(sema.db)
|
||||||
|
.iter()
|
||||||
|
.filter_map(|assoc| match assoc {
|
||||||
|
hir::AssocItem::TypeAlias(it) => Some(*it),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.find(|alias| alias.name(sema.db).to_string() == **name_ref.text())
|
||||||
|
{
|
||||||
|
return Some(NameRefClass::Definition(Definition::ModuleDef(
|
||||||
|
ModuleDef::TypeAlias(ty),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) {
|
if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) {
|
||||||
if let Some(path) = macro_call.path() {
|
if let Some(path) = macro_call.path() {
|
||||||
if path.qualifier().is_none() {
|
if path.qualifier().is_none() {
|
||||||
|
|
Loading…
Reference in a new issue