Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: if item exsits on module, resolve as module instead of type #19088

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion crates/hir/src/source_analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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.
Expand Down
34 changes: 34 additions & 0 deletions crates/ide/src/goto_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
"#,
);
}
}