diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index e8fa3c56ec..859dcfc1c7 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -114,16 +114,15 @@ fn resolve_doc_path( let path = ast::Path::parse(link).ok()?; let modpath = ModPath::from_src(db.upcast(), path, &Hygiene::new_unhygienic()).unwrap(); let resolved = resolver.resolve_module_path_in_items(db.upcast(), &modpath); - if resolved == PerNs::none() { - if let Some(trait_id) = resolver.resolve_module_path_in_trait_items(db.upcast(), &modpath) { - return Some(ModuleDefId::TraitId(trait_id)); - }; - } - let def = match ns { - Some(Namespace::Types) => resolved.take_types()?, - Some(Namespace::Values) => resolved.take_values()?, - Some(Namespace::Macros) => return None, - None => resolved.iter_items().find_map(|it| it.as_module_def_id())?, + let resolved = if resolved == PerNs::none() { + resolver.resolve_module_path_in_trait_assoc_items(db.upcast(), &modpath)? + } else { + resolved }; - Some(def) + match ns { + Some(Namespace::Types) => resolved.take_types(), + Some(Namespace::Values) => resolved.take_values(), + Some(Namespace::Macros) => None, + None => resolved.iter_items().find_map(|it| it.as_module_def_id()), + } } diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index a11439c3b5..123f23ff92 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs @@ -20,10 +20,10 @@ use crate::{ path::{ModPath, PathKind}, per_ns::PerNs, visibility::{RawVisibility, Visibility}, - AdtId, AssocContainerId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, - FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, LifetimeParamId, LocalModuleId, - Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, - VariantId, + AdtId, AssocContainerId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, + EnumVariantId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, LifetimeParamId, + LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, + TypeParamId, VariantId, }; #[derive(Debug, Clone, Default)] @@ -144,15 +144,28 @@ impl Resolver { self.resolve_module_path(db, path, BuiltinShadowMode::Module) } - pub fn resolve_module_path_in_trait_items( + pub fn resolve_module_path_in_trait_assoc_items( &self, db: &dyn DefDatabase, path: &ModPath, - ) -> Option { + ) -> Option { let (item_map, module) = self.module_scope()?; - let (module_res, ..) = item_map.resolve_path(db, module, path, BuiltinShadowMode::Module); + let (module_res, idx) = item_map.resolve_path(db, module, path, BuiltinShadowMode::Module); match module_res.take_types()? { - ModuleDefId::TraitId(it) => Some(it), + ModuleDefId::TraitId(it) => { + let idx = idx?; + let unresolved = &path.segments()[idx..]; + let assoc = match unresolved { + [it] => it, + _ => return None, + }; + let &(_, assoc) = db.trait_data(it).items.iter().find(|(n, _)| n == assoc)?; + Some(match assoc { + AssocItemId::FunctionId(it) => PerNs::values(it.into(), Visibility::Public), + AssocItemId::ConstId(it) => PerNs::values(it.into(), Visibility::Public), + AssocItemId::TypeAliasId(it) => PerNs::types(it.into(), Visibility::Public), + }) + } _ => None, } } diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 49a06a2851..008aaab358 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -2077,6 +2077,7 @@ pub struct B$0ar "#]], ); } + #[test] fn test_hover_intra_link_reference_to_trait_method() { check(