Accurately classify assoc. types in paths

This commit is contained in:
Jonas Schievink 2021-03-30 02:08:33 +02:00
parent b3ca06e4fd
commit 41c7448e12
2 changed files with 38 additions and 18 deletions

View File

@ -917,6 +917,21 @@ fn f() -> impl Iterator<Item$0 = u8> {}
);
}
#[test]
#[should_panic = "unresolved reference"]
fn unknown_assoc_ty() {
check(
r#"
trait Iterator {
type Item;
//^^^^
}
fn f() -> impl Iterator<Invalid$0 = u8> {}
"#,
)
}
#[test]
fn goto_def_for_assoc_ty_in_path_multiple() {
check(

View File

@ -330,25 +330,30 @@ impl NameRefClass {
}
}
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(assoc_type_arg) = ast::AssocTypeArg::cast(parent.clone()) {
if assoc_type_arg.name_ref().as_ref() == Some(name_ref) {
// `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 {
// FIXME: resolve in supertraits
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),
)));
}
}
return None;
}
}