Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/source_analyzer.rs')
| -rw-r--r-- | crates/hir/src/source_analyzer.rs | 84 |
1 files changed, 55 insertions, 29 deletions
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index ba5ceef00a..586e55f42a 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -25,7 +25,7 @@ use hir_def::{ lower::LowerCtx, nameres::MacroSubNs, path::{ModPath, Path, PathKind}, - resolver::{Resolver, TypeNs, ValueNs, resolver_for_scope}, + resolver::{ModuleOrTypeNs, Resolver, TypeNs, ValueNs, resolver_for_scope}, type_ref::{Mutability, TypesMap, TypesSourceMap}, }; use hir_expand::{ @@ -1365,6 +1365,23 @@ pub(crate) fn resolve_hir_path_as_attr_macro( .map(Into::into) } +fn resolve_path_in_module_or_type_ns( + db: &dyn HirDatabase, + resolver: &Resolver, + path: &Path, +) -> Option<(ModuleOrTypeNs, Option<usize>)> { + let mut types = resolver + .resolve_path_in_type_ns(db.upcast(), path) + .map(|(ty, remaining_idx, _)| (ty, remaining_idx)) + .peekable(); + let (ty, _) = types.peek()?; + match ty { + ModuleOrTypeNs::ModuleNs(_) => types + .find_or_first(|(ty, _)| matches!(ty, ModuleOrTypeNs::TypeNs(TypeNs::BuiltinType(_)))), + ModuleOrTypeNs::TypeNs(_) => types.next(), + } +} + fn resolve_hir_path_( db: &dyn HirDatabase, resolver: &Resolver, @@ -1384,10 +1401,10 @@ fn resolve_hir_path_( resolver.type_owner(), ) .lower_ty_ext(type_ref); - res.map(|ty_ns| (ty_ns, path.segments().first())) + res.map(|ty_ns| (ModuleOrTypeNs::TypeNs(ty_ns), path.segments().first())) } None => { - let (ty, remaining_idx, _) = resolver.resolve_path_in_type_ns(db.upcast(), path)?; + let (ty, remaining_idx) = resolve_path_in_module_or_type_ns(db, resolver, path)?; match remaining_idx { Some(remaining_idx) => { if remaining_idx + 1 == path.segments().len() { @@ -1403,25 +1420,30 @@ fn resolve_hir_path_( // If we are in a TypeNs for a Trait, and we have an unresolved name, try to resolve it as a type // within the trait's associated types. - if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) { + if let (Some(unresolved), ModuleOrTypeNs::TypeNs(TypeNs::TraitId(trait_id))) = + (&unresolved, &ty) + { if let Some(type_alias_id) = - db.trait_items(trait_id).associated_type_by_name(unresolved.name) + db.trait_items(*trait_id).associated_type_by_name(unresolved.name) { return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into())); } } let res = match ty { - TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), - TypeNs::GenericParam(id) => PathResolution::TypeParam(id.into()), - TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { - PathResolution::Def(Adt::from(it).into()) - } - TypeNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()), - TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), - TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()), - TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), - TypeNs::TraitAliasId(it) => PathResolution::Def(TraitAlias::from(it).into()), + ModuleOrTypeNs::TypeNs(ty) => match ty { + TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), + TypeNs::GenericParam(id) => PathResolution::TypeParam(id.into()), + TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { + PathResolution::Def(Adt::from(it).into()) + } + TypeNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()), + TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), + TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()), + TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), + TypeNs::TraitAliasId(it) => PathResolution::Def(TraitAlias::from(it).into()), + }, + ModuleOrTypeNs::ModuleNs(it) => PathResolution::Def(ModuleDef::Module(it.into())), }; match unresolved { Some(unresolved) => resolver @@ -1517,10 +1539,10 @@ fn resolve_hir_path_qualifier( resolver.type_owner(), ) .lower_ty_ext(type_ref); - res.map(|ty_ns| (ty_ns, path.segments().first())) + res.map(|ty_ns| (ModuleOrTypeNs::TypeNs(ty_ns), path.segments().first())) } None => { - let (ty, remaining_idx, _) = resolver.resolve_path_in_type_ns(db.upcast(), path)?; + let (ty, remaining_idx) = resolve_path_in_module_or_type_ns(db, resolver, path)?; match remaining_idx { Some(remaining_idx) => { if remaining_idx + 1 == path.segments().len() { @@ -1536,25 +1558,29 @@ fn resolve_hir_path_qualifier( // If we are in a TypeNs for a Trait, and we have an unresolved name, try to resolve it as a type // within the trait's associated types. - if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) { + if let (Some(unresolved), &ModuleOrTypeNs::TypeNs(TypeNs::TraitId(trait_id))) = + (&unresolved, &ty) + { if let Some(type_alias_id) = db.trait_items(trait_id).associated_type_by_name(unresolved.name) { return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into())); } } - let res = match ty { - TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), - TypeNs::GenericParam(id) => PathResolution::TypeParam(id.into()), - TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { - PathResolution::Def(Adt::from(it).into()) - } - TypeNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()), - TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), - TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()), - TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), - TypeNs::TraitAliasId(it) => PathResolution::Def(TraitAlias::from(it).into()), + ModuleOrTypeNs::TypeNs(ty) => match ty { + TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), + TypeNs::GenericParam(id) => PathResolution::TypeParam(id.into()), + TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { + PathResolution::Def(Adt::from(it).into()) + } + TypeNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()), + TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), + TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()), + TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), + TypeNs::TraitAliasId(it) => PathResolution::Def(TraitAlias::from(it).into()), + }, + ModuleOrTypeNs::ModuleNs(it) => PathResolution::Def(ModuleDef::Module(it.into())), }; match unresolved { Some(unresolved) => resolver |