8250: More accurately classify assoc. types in paths r=jonas-schievink a=jonas-schievink

Previously `Iterator<Whoops$0 = ()>` would go to the `Iterator` trait. This fixes that and correctly marks `Whoops` as unresolved.

bors r+

Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
This commit is contained in:
bors[bot] 2021-03-30 00:10:30 +00:00 committed by GitHub
commit 904bdff224
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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 @@ pub fn classify(
}
}
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;
}
}