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] #[test]
fn goto_def_for_assoc_ty_in_path_multiple() { fn goto_def_for_assoc_ty_in_path_multiple() {
check( check(

View file

@ -330,25 +330,30 @@ impl NameRefClass {
} }
} }
if ast::AssocTypeArg::cast(parent.clone()).is_some() { if let Some(assoc_type_arg) = ast::AssocTypeArg::cast(parent.clone()) {
// `Trait<Assoc = Ty>` 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)?; let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?;
if let PathResolution::Def(ModuleDef::Trait(tr)) = resolved { let resolved = sema.resolve_path(&path)?;
if let Some(ty) = tr if let PathResolution::Def(ModuleDef::Trait(tr)) = resolved {
.items(sema.db) // FIXME: resolve in supertraits
.iter() if let Some(ty) = tr
.filter_map(|assoc| match assoc { .items(sema.db)
hir::AssocItem::TypeAlias(it) => Some(*it), .iter()
_ => None, .filter_map(|assoc| match assoc {
}) hir::AssocItem::TypeAlias(it) => Some(*it),
.find(|alias| &alias.name(sema.db).to_string() == &name_ref.text()) _ => None,
{ })
return Some(NameRefClass::Definition(Definition::ModuleDef( .find(|alias| &alias.name(sema.db).to_string() == &name_ref.text())
ModuleDef::TypeAlias(ty), {
))); return Some(NameRefClass::Definition(Definition::ModuleDef(
ModuleDef::TypeAlias(ty),
)));
}
} }
return None;
} }
} }