Repository: intellij-rust/intellij-rust
Issue: Regression: incorrect resolution of enum variants

<!--
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.160.4233-212-nightly
* **Rust toolchain version:** 1.56.0 (09c42c458 2021-10-18) x86_64-unknown-linux-gnu
* **IDE name and version:** CLion 2021.2.2 (CL-212.5284.51)
* **Operating system:** Linux 5.4.0-89-generic
* **Macro expansion engine:** new
* **Name resolution engine:** new

## Problem description

After the last update the enum variants can be resolved incorrectly in some situataions. The error occurs when using fully qualified enum variants with brace initializers (or patterns). When the error occurs, the variant isn't highlighted as an enum variant (it looks like a plain identifier), and attempting "Go to definition" on the variant produces a list, which includes the enum variant but also many unrelated associated types with the same name.

## Steps to reproduce

```rust
pub enum Foo { Output }

fn f(x: Foo) {
    match x {
        Foo::Output { .. } => {}
    }
}

fn g1(x: Foo) {
    match x {
        Foo::Output => {}
    }
}

fn g2(x: Foo) {
    use Foo::*;
    match x {
        Output => {}
    }
}

fn g3(x: Foo) {
    use Foo::*;
    match x {
        Output { .. } => {}
    }
}
```

Here, the enum variant matches in g1, g2 and g3 are correctly resolved and highlighted, but the variant in f is not highlighted. Attempting "Go to definition" on that variant produces a list

* `crate::foo::Output`
* `core::future::into_future::IntoFuture::Output`
* and any other associated items named "Output", if such traits are present in your Cargo.toml dependencies. E.g. if you add `serde = { version = "1", features = ["derive"] }` to dependencies, the list includes `syn::parse::Parser::Output`.

In the case of a pattern, the variant is resolved incorrectly specifically when using the fully qualified brace syntax, as you can see above. For example, if the variant is a tuple 

```rust
pub enum Bar { Output(bool) }

fn f(x: Bar) {
    match x {
        Bar::Output { 0: _ } => {}
    }
}

fn g(x: Bar) {
    match x {
        Bar::Output(_) => {}
    }
}
```

then the variant in g is resolved correctly, while the variant in `f` suffers from the bug.

Duplicate: #8073

<!--
Please include as much of your codebase as needed to reproduce the error.
If the relevant files are large, please provide a link to a public repository or a [Gist](https://gist.github.com/).
-->

Changed files:
src/main/kotlin/org/rust/lang/core/resolve2/ModCollector.kt, src/main/kotlin/org/rust/lang/core/resolve/Namespace.kt, src/test/kotlin/org/rust/lang/core/resolve/RsResolveTest.kt, src/test/kotlin/org/rust/lang/core/resolve/RsConstArgumentResolveTest.kt, src/main/kotlin/org/rust/lang/core/resolve2/FacadeResolve.kt

diff --git a/src/main/kotlin/org/rust/lang/core/resolve/Namespace.kt b/src/main/kotlin/org/rust/lang/core/resolve/Namespace.kt
index 816965c1b..7c0448cb2 100644
--- a/src/main/kotlin/org/rust/lang/core/resolve/Namespace.kt
+++ b/src/main/kotlin/org/rust/lang/core/resolve/Namespace.kt
@@ -42,7 +42,7 @@ val RsNamedElement.namespaces: Set<Namespace> get() = when (this) {
     is RsConstant -> VALUES
     is RsFunction -> if (this.isProcMacroDef) MACROS else VALUES
 
-    is RsEnumVariant -> namespaces
+    is RsEnumVariant -> ENUM_VARIANT_NS
 
     is RsStructItem -> if (blockFields == null) TYPES_N_VALUES else TYPES
 
@@ -64,7 +64,7 @@ fun StubElement<*>.getNamespaces(crate: Crate): Set<Namespace> = when (this) {
     is RsConstantStub -> VALUES
     is RsFunctionStub -> if (IS_PROC_MACRO_DEF_PROP.getByStub(this, crate)) MACROS else VALUES
 
-    is RsEnumVariantStub -> namespaces
+    is RsEnumVariantStub -> ENUM_VARIANT_NS
 
     is RsStructItemStub -> if (blockFields == null) TYPES_N_VALUES else TYPES
 
@@ -75,8 +75,8 @@ fun StubElement<*>.getNamespaces(crate: Crate): Set<Namespace> = when (this) {
     else -> TYPES_N_VALUES
 }
 
-inline val RsEnumVariant.namespaces: Set<Namespace> get() = if (blockFields === null) VALUES else TYPES
-inline val RsEnumVariantStub.namespaces: Set<Namespace> get() = if (blockFields === null) VALUES else TYPES
+// https://rust-lang.github.io/rfcs/0234-variants-namespace.html
+val ENUM_VARIANT_NS: Set<Namespace> = TYPES_N_VALUES
 
 val RsUseSpeck.namespaces: Set<Namespace>
     get() = path
diff --git a/src/main/kotlin/org/rust/lang/core/resolve2/FacadeResolve.kt b/src/main/kotlin/org/rust/lang/core/resolve2/FacadeResolve.kt
index cc5e2ba54..1ea02c60b 100644
--- a/src/main/kotlin/org/rust/lang/core/resolve2/FacadeResolve.kt
+++ b/src/main/kotlin/org/rust/lang/core/resolve2/FacadeResolve.kt
@@ -602,7 +602,7 @@ fun VisItem.toPsi(info: RsModInfo, ns: Namespace): List<RsNamedElement> {
         val containingEnums = containingModData.toRsEnum(info)
         containingEnums.flatMap { containingEnum ->
             containingEnum.variants
-                .filter { it.name == name && ns in it.namespaces && matchesIsEnabledByCfg(it, this) }
+                .filter { it.name == name && ns in ENUM_VARIANT_NS && matchesIsEnabledByCfg(it, this) }
         }
     } else {
         val containingMods = containingModData.toScope(info)
diff --git a/src/main/kotlin/org/rust/lang/core/resolve2/ModCollector.kt b/src/main/kotlin/org/rust/lang/core/resolve2/ModCollector.kt
index 589bf96e6..61add9f89 100644
--- a/src/main/kotlin/org/rust/lang/core/resolve2/ModCollector.kt
+++ b/src/main/kotlin/org/rust/lang/core/resolve2/ModCollector.kt
@@ -22,7 +22,7 @@ import org.rust.lang.core.psi.RsBlock
 import org.rust.lang.core.psi.RsFile
 import org.rust.lang.core.psi.RsFileBase
 import org.rust.lang.core.psi.ext.*
-import org.rust.lang.core.resolve.namespaces
+import org.rust.lang.core.resolve.ENUM_VARIANT_NS
 import org.rust.lang.core.resolve.processModDeclResolveVariants
 import org.rust.lang.core.resolve2.util.DollarCrateHelper
 import org.rust.lang.core.resolve2.util.DollarCrateMap
@@ -288,7 +288,7 @@ private class ModCollector(
             val isVariantDeeplyEnabledByCfg = enumData.isDeeplyEnabledByCfg && variantPsi.isEnabledByCfgSelf(crate)
             val variantVisibility = if (isVariantDeeplyEnabledByCfg) Visibility.Public else Visibility.CfgDisabled
             val variant = VisItem(variantPath, variantVisibility)
-            val variantPerNs = PerNs.from(variant, variantPsi.namespaces)
+            val variantPerNs = PerNs.from(variant, ENUM_VARIANT_NS)
             enumData.addVisibleItem(variantName, variantPerNs)
         }
         return enumData
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 7c747b57f..1da3188ff 100644
--- a/src/test/kotlin/org/rust/lang/core/resolve/RsConstArgumentResolveTest.kt
+++ b/src/test/kotlin/org/rust/lang/core/resolve/RsConstArgumentResolveTest.kt
@@ -52,11 +52,11 @@ class RsConstArgumentResolveTest : RsResolveTestBase() {
     """)
 
     fun `test in the case of ambiguity const argument is resolved to a type 3`() = checkByCode("""
-        enum E { S, B }
+        mod inner { pub fn S() {} }
         struct S {}
              //X
 
-        use E::*;
+        use inner::*;
         struct Foo<const C: i32>();
         type Bar = Foo<S>;
                      //^
diff --git a/src/test/kotlin/org/rust/lang/core/resolve/RsResolveTest.kt b/src/test/kotlin/org/rust/lang/core/resolve/RsResolveTest.kt
index f6787c476..6a6ae37d3 100644
--- a/src/test/kotlin/org/rust/lang/core/resolve/RsResolveTest.kt
+++ b/src/test/kotlin/org/rust/lang/core/resolve/RsResolveTest.kt
@@ -675,6 +675,17 @@ class RsResolveTest : RsResolveTestBase() {
         }
     """)
 
+    fun `test enum variant in match pattern`() = checkByCode("""
+        pub enum E { A }
+                   //X
+        use E::*;
+        fn func(x: E) {
+            match x {
+                A { .. } => {}
+            } //^
+        }
+    """)
+
     fun `test enum variant with alias`() = checkByCode("""
         enum E { A }
                //X