From c84cec15479f2f83acfad41cd52813d4a2462027 Mon Sep 17 00:00:00 2001 From: Hayashi Mikihiro <34ttrweoewiwe28@gmail.com> Date: Mon, 10 Feb 2025 10:50:11 +0900 Subject: [PATCH] Shadowing BuiltinType by Module Signed-off-by: Hayashi Mikihiro <34ttrweoewiwe28@gmail.com> --- crates/hir/src/source_analyzer.rs | 39 ++++++++++++++++++++++++++++++- crates/ide/src/goto_definition.rs | 34 +++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 23e7518883b5..c687e2d8a0cf 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -866,7 +866,8 @@ impl SourceAnalyzer { // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we are // trying to resolve foo::bar. - if path.parent_path().is_some() { + if let Some(parent_path) = path.parent_path() { + let parent_hir_path = Path::from_src(&mut ctx, parent_path); return match resolve_hir_path_qualifier(db, &self.resolver, &hir_path, &types_map) { None if meta_path.is_some() => path .first_segment() @@ -876,6 +877,42 @@ impl SourceAnalyzer { .map(PathResolution::ToolModule) }) .map(|it| (it, None)), + // Case the type name conflict with use module, + // e.g. + // ``` + // use std::str; + // fn main() { + // str::from_utf8(); // as module std::str + // str::len(); // as primitive type str + // str::no_exist_item(); // as primitive type str + // } + // ``` + Some(it) if matches!(it, PathResolution::Def(ModuleDef::BuiltinType(_))) => { + if let (Some(mod_path), Some(parent_hir_path)) = + (hir_path.mod_path(), parent_hir_path) + { + if let Some(ModuleDefId::ModuleId(id)) = self + .resolver + .resolve_module_path_in_items(db.upcast(), mod_path) + .take_types() + { + let parent_hir_name = + parent_hir_path.segments().get(1).map(|it| it.name); + let module = crate::Module { id }; + if module + .scope(db, None) + .into_iter() + .any(|(name, _)| Some(&name) == parent_hir_name) + { + return Some(( + PathResolution::Def(ModuleDef::Module(module)), + None, + )); + }; + } + } + Some((it, None)) + } // FIXME: We do not show substitutions for parts of path, because this is really complex // due to the interactions with associated items of `impl`s and associated items of associated // types. diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index bdafb701ff53..60a904233a9a 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -3290,4 +3290,38 @@ fn main() { "#, ); } + + #[test] + fn shadow_builtin_type_by_module() { + check( + r#" +mod Foo{ +pub mod str { + // ^^^ + pub fn foo() {} +} +} + +fn main() { + use Foo::str; + let s = st$0r::foo(); +} +"#, + ); + } + + #[test] + fn not_goto_module_because_str_is_builtin_type() { + check( + r#" +mod str { +pub fn foo() {} +} + +fn main() { + let s = st$0r::f(); +} +"#, + ); + } }