Repository: rust-analyzer/rust-analyzer (rust)

Issue:
Explicit import not shadowing glob import
The code below compiles (with unused warnings), but RA errors with:
```
Missing structure fields:
- a
```

RA is using the `a::S` definition, when it should be using the `b::S` one instead.

```rust
mod a {
    pub struct S {
        pub a: bool,
    }
}
mod b {
    pub struct S {
        pub b: bool,
    }
}

use a::*;
use b::S;

fn main() {
    let _ = S {
        b: true,
    };
}
```

Pull request description:
Account for updated module ids when determining whether a resolution is changed
Fixes #4943

Patch:
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs
index b03ba939a5..c81b966c39 100644
--- a/crates/ra_hir_def/src/item_scope.rs
+++ b/crates/ra_hir_def/src/item_scope.rs
@@ -5,6 +5,7 @@ use hir_expand::name::Name;
 use once_cell::sync::Lazy;
 use ra_db::CrateId;
 use rustc_hash::FxHashMap;
+use test_utils::mark;
 
 use crate::{
     db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId,
@@ -126,19 +127,27 @@ impl ItemScope {
         let mut changed = false;
         let existing = self.visible.entry(name).or_default();
 
-        if existing.types.is_none() && def.types.is_some() {
-            existing.types = def.types;
-            changed = true;
-        }
-        if existing.values.is_none() && def.values.is_some() {
-            existing.values = def.values;
-            changed = true;
-        }
-        if existing.macros.is_none() && def.macros.is_some() {
-            existing.macros = def.macros;
-            changed = true;
+        macro_rules! check_changed {
+            ($changed:ident, $existing:expr, $def:expr) => {
+                match ($existing, $def) {
+                    (None, Some(_)) => {
+                        $existing = $def;
+                        $changed = true;
+                    }
+                    (Some(e), Some(d)) if e.0 != d.0 => {
+                        mark::hit!(import_shadowed);
+                        $existing = $def;
+                        $changed = true;
+                    }
+                    _ => {}
+                }
+            };
         }
 
+        check_changed!(changed, existing.types, def.types);
+        check_changed!(changed, existing.values, def.values);
+        check_changed!(changed, existing.macros, def.macros);
+
         changed
     }
 


Test patch:
diff --git a/crates/ra_hir_def/src/nameres/tests/globs.rs b/crates/ra_hir_def/src/nameres/tests/globs.rs
index 2b12c0daad..2f440975a9 100644
--- a/crates/ra_hir_def/src/nameres/tests/globs.rs
+++ b/crates/ra_hir_def/src/nameres/tests/globs.rs
@@ -229,3 +229,50 @@ fn glob_enum_group() {
     "###
     );
 }
+
+#[test]
+fn glob_shadowed_def() {
+    mark::check!(import_shadowed);
+    let map = def_map(
+        r###"
+        //- /lib.rs
+        mod foo;
+        mod bar;
+
+        use foo::*;
+        use bar::baz;
+
+        use baz::Bar;
+
+        //- /foo.rs
+        pub mod baz {
+            pub struct Foo;
+        }
+
+        //- /bar.rs
+        pub mod baz {
+            pub struct Bar;
+        }
+        "###,
+    );
+    assert_snapshot!(map, @r###"
+        ⋮crate
+        ⋮Bar: t v
+        ⋮bar: t
+        ⋮baz: t
+        ⋮foo: t
+        ⋮
+        ⋮crate::bar
+        ⋮baz: t
+        ⋮
+        ⋮crate::bar::baz
+        ⋮Bar: t v
+        ⋮
+        ⋮crate::foo
+        ⋮baz: t
+        ⋮
+        ⋮crate::foo::baz
+        ⋮Foo: t v
+    "###
+    );
+}