Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/item_scope.rs18
-rw-r--r--crates/hir-def/src/nameres/collector.rs77
-rw-r--r--crates/hir-ty/src/tests/regression.rs29
3 files changed, 99 insertions, 25 deletions
diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs
index 9e1efb9777..1303773b59 100644
--- a/crates/hir-def/src/item_scope.rs
+++ b/crates/hir-def/src/item_scope.rs
@@ -893,6 +893,24 @@ impl ItemScope {
self.macros.get_mut(name).expect("tried to update visibility of non-existent macro");
res.vis = vis;
}
+
+ pub(crate) fn update_def_types(&mut self, name: &Name, def: ModuleDefId, vis: Visibility) {
+ let res = self.types.get_mut(name).expect("tried to update def of non-existent type");
+ res.def = def;
+ res.vis = vis;
+ }
+
+ pub(crate) fn update_def_values(&mut self, name: &Name, def: ModuleDefId, vis: Visibility) {
+ let res = self.values.get_mut(name).expect("tried to update def of non-existent value");
+ res.def = def;
+ res.vis = vis;
+ }
+
+ pub(crate) fn update_def_macros(&mut self, name: &Name, def: MacroId, vis: Visibility) {
+ let res = self.macros.get_mut(name).expect("tried to update def of non-existent macro");
+ res.def = def;
+ res.vis = vis;
+ }
}
impl PerNs {
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 323060f61d..f51524c1b5 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -1209,42 +1209,69 @@ impl<'db> DefCollector<'db> {
// `ItemScope::push_res_with_import()`.
if let Some(def) = defs.types
&& let Some(prev_def) = prev_defs.types
- && def.def == prev_def.def
- && self.from_glob_import.contains_type(module_id, name.clone())
- && def.vis != prev_def.vis
- && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
{
- changed = true;
- // This import is being handled here, don't pass it down to
- // `ItemScope::push_res_with_import()`.
- defs.types = None;
- self.def_map.modules[module_id].scope.update_visibility_types(name, def.vis);
+ if def.def == prev_def.def
+ && self.from_glob_import.contains_type(module_id, name.clone())
+ && def.vis != prev_def.vis
+ && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
+ {
+ changed = true;
+ // This import is being handled here, don't pass it down to
+ // `ItemScope::push_res_with_import()`.
+ defs.types = None;
+ self.def_map.modules[module_id].scope.update_visibility_types(name, def.vis);
+ }
+ // When the source module's definition changed (e.g., due to an explicit import
+ // shadowing a glob), propagate the new definition to modules that glob-import from it.
+ // We check that the previous definition came from the same glob import to avoid
+ // incorrectly overwriting definitions from different glob sources.
+ //
+ // Note this is not a perfect fix, but it makes
+ // https://github.com/rust-lang/rust-analyzer/issues/19224 work for now until we
+ // implement a proper glob graph
+ else if def.def != prev_def.def && prev_def.import == def_import_type {
+ changed = true;
+ defs.types = None;
+ self.def_map.modules[module_id].scope.update_def_types(name, def.def, def.vis);
+ }
}
if let Some(def) = defs.values
&& let Some(prev_def) = prev_defs.values
- && def.def == prev_def.def
- && self.from_glob_import.contains_value(module_id, name.clone())
- && def.vis != prev_def.vis
- && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
{
- changed = true;
- // See comment above.
- defs.values = None;
- self.def_map.modules[module_id].scope.update_visibility_values(name, def.vis);
+ if def.def == prev_def.def
+ && self.from_glob_import.contains_value(module_id, name.clone())
+ && def.vis != prev_def.vis
+ && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
+ {
+ changed = true;
+ defs.values = None;
+ self.def_map.modules[module_id].scope.update_visibility_values(name, def.vis);
+ } else if def.def != prev_def.def
+ && prev_def.import.map(ImportOrExternCrate::from) == def_import_type
+ {
+ changed = true;
+ defs.values = None;
+ self.def_map.modules[module_id].scope.update_def_values(name, def.def, def.vis);
+ }
}
if let Some(def) = defs.macros
&& let Some(prev_def) = prev_defs.macros
- && def.def == prev_def.def
- && self.from_glob_import.contains_macro(module_id, name.clone())
- && def.vis != prev_def.vis
- && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
{
- changed = true;
- // See comment above.
- defs.macros = None;
- self.def_map.modules[module_id].scope.update_visibility_macros(name, def.vis);
+ if def.def == prev_def.def
+ && self.from_glob_import.contains_macro(module_id, name.clone())
+ && def.vis != prev_def.vis
+ && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
+ {
+ changed = true;
+ defs.macros = None;
+ self.def_map.modules[module_id].scope.update_visibility_macros(name, def.vis);
+ } else if def.def != prev_def.def && prev_def.import == def_import_type {
+ changed = true;
+ defs.macros = None;
+ self.def_map.modules[module_id].scope.update_def_macros(name, def.def, def.vis);
+ }
}
}
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index 4f1480c393..f6736905b8 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -2645,3 +2645,32 @@ where
"#,
);
}
+
+#[test]
+fn issue_21560() {
+ check_no_mismatches(
+ r#"
+mod bindings {
+ use super::*;
+ pub type HRESULT = i32;
+}
+use bindings::*;
+
+
+mod error {
+ use super::*;
+ pub fn nonzero_hresult(hr: HRESULT) -> crate::HRESULT {
+ hr
+ }
+}
+pub use error::*;
+
+mod hresult {
+ use super::*;
+ pub struct HRESULT(pub i32);
+}
+pub use hresult::HRESULT;
+
+ "#,
+ );
+}