diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index ae185759a5..7e941854a2 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -105,9 +105,8 @@ pub enum TypeNs { BuiltinType(BuiltinType), TraitId(TraitId), TraitAliasId(TraitAliasId), - // Module belong to type ns, but the resolver is used when all module paths - // are fully resolved. - // ModuleId(ModuleId) + + ModuleId(ModuleId), } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -249,6 +248,24 @@ impl Resolver { } Scope::BlockScope(m) => { if let Some(res) = m.resolve_path_in_type_ns(db, path) { + let res = match res.0 { + TypeNs::ModuleId(_) if res.1.is_none() => { + if let Some(ModuleDefId::BuiltinType(builtin)) = BUILTIN_SCOPE + .get(first_name) + .and_then(|builtin| builtin.take_types()) + { + ( + TypeNs::BuiltinType(builtin), + remaining_idx(), + None, + ResolvePathResultPrefixInfo::default(), + ) + } else { + res + } + } + _ => res, + }; return Some(res); } } @@ -1193,11 +1210,12 @@ fn to_type_ns(per_ns: PerNs) -> Option<(TypeNs, Option)> { ModuleDefId::TraitId(it) => TypeNs::TraitId(it), ModuleDefId::TraitAliasId(it) => TypeNs::TraitAliasId(it), + ModuleDefId::ModuleId(it) => TypeNs::ModuleId(it), + ModuleDefId::FunctionId(_) | ModuleDefId::ConstId(_) | ModuleDefId::MacroId(_) - | ModuleDefId::StaticId(_) - | ModuleDefId::ModuleId(_) => return None, + | ModuleDefId::StaticId(_) => return None, }; Some((res, def.import)) } diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index eba54b3a51..950c8cadd4 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -1666,7 +1666,8 @@ impl<'a> InferenceContext<'a> { TypeNs::AdtId(AdtId::EnumId(_)) | TypeNs::BuiltinType(_) | TypeNs::TraitId(_) - | TypeNs::TraitAliasId(_) => { + | TypeNs::TraitAliasId(_) + | TypeNs::ModuleId(_) => { // FIXME diagnostic (self.err_ty(), None) } diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs index 86a97e923e..bc2d9d9080 100644 --- a/crates/hir-ty/src/lower/path.rs +++ b/crates/hir-ty/src/lower/path.rs @@ -279,7 +279,9 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { TypeNs::BuiltinType(it) => self.lower_path_inner(it.into(), infer_args), TypeNs::TypeAliasId(it) => self.lower_path_inner(it.into(), infer_args), // FIXME: report error - TypeNs::EnumVariantId(_) => return (TyKind::Error.intern(Interner), None), + TypeNs::EnumVariantId(_) | TypeNs::ModuleId(_) => { + return (TyKind::Error.intern(Interner), None); + } }; self.skip_resolved_segment(); @@ -310,6 +312,9 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { TypeNs::BuiltinType(_) => { prohibit_generics_on_resolved(GenericArgsProhibitedReason::PrimitiveTy) } + TypeNs::ModuleId(_) => { + prohibit_generics_on_resolved(GenericArgsProhibitedReason::Module) + } TypeNs::AdtId(_) | TypeNs::EnumVariantId(_) | TypeNs::TypeAliasId(_) diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index 3c449f6e32..b1c478d1bf 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -210,6 +210,9 @@ fn resolve_assoc_or_field( // XXX: Do these get resolved? return None; } + TypeNs::ModuleId(_) => { + return None; + } }; // Resolve inherent items first, then trait items, then fields. diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 7a5c52d734..6a39f9cab8 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -1527,6 +1527,7 @@ fn resolve_hir_path_( 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()), + TypeNs::ModuleId(it) => PathResolution::Def(ModuleDef::Module(it.into())), }; match unresolved { Some(unresolved) => resolver @@ -1654,6 +1655,7 @@ fn resolve_hir_path_qualifier( 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()), + TypeNs::ModuleId(it) => PathResolution::Def(ModuleDef::Module(it.into())), }; match unresolved { Some(unresolved) => resolver diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index 23ec729e57..a7c8a92f0e 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -3330,6 +3330,150 @@ pub fn foo() {} fn main() { let s = st$0r::f(); } +"#, + ); + } + + #[test] + fn struct_shadow_by_module() { + check( + r#" +mod foo { + pub mod bar { + // ^^^ + pub type baz = usize; + } +} +struct bar; +fn main() { + use foo::bar; + let x: ba$0r::baz = 5; + +} +"#, + ); + } + + #[test] + fn type_alias_shadow_by_module() { + check( + r#" +mod foo { + pub mod bar { + // ^^^ + pub fn baz() {} + } +} + +trait Qux {} + +fn item() { + use foo::bar; + ba$0r::baz(); +} +} +"#, + ); + + check( + r#" +mod foo { + pub mod bar { + // ^^^ + pub fn baz() {} + } +} + +fn item(x: bar) { + use foo::bar; + let x: bar$0 = x; +} +"#, + ); + } + + #[test] + fn trait_shadow_by_module() { + check( + r#" +pub mod foo { + pub mod Bar {} + // ^^^ +} + +trait Bar {} + +fn main() { + use foo::Bar; + fn f() {} +} + "#, + ); + } + + #[test] + fn const_shadow_by_module() { + check( + r#" +pub mod foo { + pub struct u8 {} + pub mod bar { + pub mod u8 {} + } +} + +fn main() { + use foo::u8; + { + use foo::bar::u8; + + fn f1() {} + } + fn f2() {} +} +"#, + ); + + check( + r#" +pub mod foo { + pub struct u8 {} + // ^^ + pub mod bar { + pub mod u8 {} + } +} + +fn main() { + use foo::u8; + { + use foo::bar::u8; + + fn f1() {} + } + fn f2() {} +} +"#, + ); + + check( + r#" +pub mod foo { + pub struct buz {} + pub mod bar { + pub mod buz {} + // ^^^ + } +} + +fn main() { + use foo::buz; + { + use foo::bar::buz; + + fn f1() {} + } +} "#, ); }