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.rs84
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