Repository: intellij-rust/intellij-rust
Issue: Wrong name resolution for const arguments

<!--
Hello and thank you for the issue!
If you would like to report a bug, we have added some points below that you can fill out.
Feel free to remove all the irrelevant text to request a new feature.
-->

## Environment

* **IntelliJ Rust plugin version:** 0.4.159.4191-212-nightly
* **Rust toolchain version:** 1.57.0-nightly (addb4da68 2021-09-25) x86_64-apple-darwin
* **IDE name and version:** CLion 2021.2.3 (CL-212.5457.51)
* **Operating system:** macOS 12.0.1
* **Macro expansion engine:** new
* **Name resolution engine:** new

## Problem description

Expected:
```rust
struct N;
     //X
fn foo<const N: i32>() {
    foo::<N>();
}       //^
```

Actual:
```rust
struct N;
fn foo<const N: i32>() {
           //X
    foo::<N>();
}       //^
```

Note, in this case everything is ok:

```rust
struct N { f: i32 }
     //X
fn foo<const N: i32>() {
    foo::<N>();
}       //^
```


Changed files:
src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt, src/main/kotlin/org/rust/lang/core/resolve/ItemResolution.kt, src/test/kotlin/org/rust/lang/core/resolve/RsConstArgumentResolveTest.kt

diff --git a/src/main/kotlin/org/rust/lang/core/resolve/ItemResolution.kt b/src/main/kotlin/org/rust/lang/core/resolve/ItemResolution.kt
index 69c5f0c9b..c708ca7eb 100644
--- a/src/main/kotlin/org/rust/lang/core/resolve/ItemResolution.kt
+++ b/src/main/kotlin/org/rust/lang/core/resolve/ItemResolution.kt
@@ -157,7 +157,7 @@ fun processItemDeclarations(
         if (isAtLeastEdition2018 && !scope.isCrateRoot) {
             val crateRoot = scope.crateRoot
             if (crateRoot != null) {
-                val result = processWithShadowingAndUpdateScope(directlyDeclaredNames, originalProcessor) { shadowingProcessor ->
+                val result = processWithShadowingAndUpdateScope(directlyDeclaredNames, ns, originalProcessor) { shadowingProcessor ->
                     crateRoot.processExpandedItemsExceptImplsAndUses { item ->
                         if (item is RsExternCrateItem) {
                             processExternCrateItem(item, shadowingProcessor, true)
@@ -173,7 +173,7 @@ fun processItemDeclarations(
         // "extern_prelude" feature. Extern crate names can be resolved as if they were in the prelude.
         // See https://blog.rust-lang.org/2018/10/25/Rust-1.30.0.html#module-system-improvements
         // See https://github.com/rust-lang/rust/pull/54404/
-        val result = processWithShadowingAndUpdateScope(directlyDeclaredNames, originalProcessor) { shadowingProcessor ->
+        val result = processWithShadowingAndUpdateScope(directlyDeclaredNames, ns, originalProcessor) { shadowingProcessor ->
             val isCompletion = ipm == ItemProcessingMode.WITH_PRIVATE_IMPORTS_N_EXTERN_CRATES_COMPLETION
             processExternCrateResolveVariants(
                 scope,
@@ -215,7 +215,7 @@ fun processItemDeclarations(
         } ?: continue
 
         val found = recursionGuard(mod, {
-            processWithShadowing(directlyDeclaredNames, originalProcessor) { shadowingProcessor ->
+            processWithShadowing(directlyDeclaredNames, ns, originalProcessor) { shadowingProcessor ->
                 processItemOrEnumVariantDeclarations(
                     mod,
                     ns,
diff --git a/src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt b/src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt
index 454ec84c1..e06e821ff 100644
--- a/src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt
+++ b/src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt
@@ -1578,11 +1578,11 @@ private fun processLexicalDeclarations(
             val guardPat = scope.matchArmGuard?.pat
             if (guardPat == null || scope.expr != cameFrom) return processPattern(scope.pat, processor)
             val prevScope = mutableMapOf<String, Set<Namespace>>()
-            val stop = processWithShadowingAndUpdateScope(prevScope, processor) { shadowingProcessor ->
+            val stop = processWithShadowingAndUpdateScope(prevScope, ns, processor) { shadowingProcessor ->
                 processPattern(guardPat, shadowingProcessor)
             }
             if (stop) return true
-            return processWithShadowing(prevScope, processor) { shadowingProcessor ->
+            return processWithShadowing(prevScope, ns, processor) { shadowingProcessor ->
                 processPattern(scope.pat, shadowingProcessor)
             }
         }
@@ -1606,7 +1606,7 @@ fun processNestedScopesUpwards(
     }
     val prevScope = mutableMapOf<String, Set<Namespace>>()
     val stop = walkUp(scopeStart, { it is RsMod }) { cameFrom, scope ->
-        processWithShadowingAndUpdateScope(prevScope, processor) { shadowingProcessor ->
+        processWithShadowingAndUpdateScope(prevScope, ns, processor) { shadowingProcessor ->
             val ipm = when {
                 scope !is RsMod -> ItemProcessingMode.WITH_PRIVATE_IMPORTS
                 isCompletion -> ItemProcessingMode.WITH_PRIVATE_IMPORTS_N_EXTERN_CRATES_COMPLETION
@@ -1622,7 +1622,7 @@ fun processNestedScopesUpwards(
 
     val prelude = findPrelude(scopeStart)
     if (prelude != null) {
-        return processWithShadowing(prevScope, processor) { shadowingProcessor ->
+        return processWithShadowing(prevScope, ns, processor) { shadowingProcessor ->
             processItemDeclarations(prelude, ns, shadowingProcessor, ItemProcessingMode.WITHOUT_PRIVATE_IMPORTS)
         }
     }
@@ -1662,14 +1662,18 @@ private tailrec fun PsiFile.unwrapCodeFragments(): PsiFile {
 
 inline fun processWithShadowingAndUpdateScope(
     prevScope: MutableMap<String, Set<Namespace>>,
+    ns: Set<Namespace>,
     processor: RsResolveProcessor,
     f: (RsResolveProcessor) -> Boolean
 ): Boolean {
     val currScope = mutableMapOf<String, Set<Namespace>>()
     val shadowingProcessor = createProcessor(processor.name) { e ->
         val prevNs = prevScope[e.name]
-        if (prevNs != null && (e.element as? RsNamedElement)?.namespaces?.intersects(prevNs) == true) {
-            return@createProcessor false
+        if (prevNs != null) {
+            val newNs = (e.element as? RsNamedElement)?.namespaces
+            if (newNs != null && !ns.intersects(newNs.minus(prevNs))) {
+                return@createProcessor false
+            }
         }
         val result = processor(e)
         if (e.isInitialized) {
@@ -1689,13 +1693,14 @@ inline fun processWithShadowingAndUpdateScope(
 
 inline fun processWithShadowing(
     prevScope: Map<String, Set<Namespace>>,
+    ns: Set<Namespace>,
     originalProcessor: RsResolveProcessor,
     f: (RsResolveProcessor) -> Boolean
 ): Boolean {
     val processor = createProcessor(originalProcessor.name) { e ->
-        val prevNs = prevScope[e.name]
-        (prevNs == null || (e.element as? RsNamedElement)?.namespaces?.intersects(prevNs) != true)
-            && originalProcessor(e)
+        val prevNs = prevScope[e.name] ?: return@createProcessor originalProcessor(e)
+        val newNs = (e.element as? RsNamedElement)?.namespaces
+        (newNs == null || ns.intersects(newNs.minus(prevNs))) && originalProcessor(e)
     }
     return f(processor)
 }
diff --git a/src/test/kotlin/org/rust/lang/core/resolve/RsConstArgumentResolveTest.kt b/src/test/kotlin/org/rust/lang/core/resolve/RsConstArgumentResolveTest.kt
index 7ea1c5506..44d920e41 100644
--- a/src/test/kotlin/org/rust/lang/core/resolve/RsConstArgumentResolveTest.kt
+++ b/src/test/kotlin/org/rust/lang/core/resolve/RsConstArgumentResolveTest.kt
@@ -94,6 +94,15 @@ class RsConstArgumentResolveTest : RsResolveTestBase() {
         }       //^
     """)
 
+    fun `test type is preferred in an upper scope (unit struct)`() = checkByCode("""
+        struct N;
+             //X
+        fn bar<T>() {}
+        fn foo<const N: i32>() {
+            bar::<N>();
+        }       //^
+    """)
+
     // Method call arguments:
 
     fun `test disambiguate type argument in method call`() = checkByCode("""