From 41c7448e1242de8fadf7c46efd3171368b5ff92e Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 30 Mar 2021 02:08:33 +0200 Subject: [PATCH] Accurately classify assoc. types in paths --- crates/ide/src/goto_definition.rs | 15 +++++++++++ crates/ide_db/src/defs.rs | 41 +++++++++++++++++-------------- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index a2c97061f2f..c6556c4871e 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -917,6 +917,21 @@ fn f() -> impl Iterator {} ); } + #[test] + #[should_panic = "unresolved reference"] + fn unknown_assoc_ty() { + check( + r#" +trait Iterator { + type Item; + //^^^^ +} + +fn f() -> impl Iterator {} + "#, + ) + } + #[test] fn goto_def_for_assoc_ty_in_path_multiple() { check( diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs index 0d9808d2439..de0dc2a40f0 100644 --- a/crates/ide_db/src/defs.rs +++ b/crates/ide_db/src/defs.rs @@ -330,25 +330,30 @@ pub fn classify( } } - if ast::AssocTypeArg::cast(parent.clone()).is_some() { - // `Trait` - // ^^^^^ - 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` + // ^^^^^ + 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; } }