Repository: intellij-rust/intellij-rust
Issue: the parking_lot crate does not receive syntax highlighting nor display of object type

For some reason, the lock() function of a parking_lot::Mutex<T> does not display. It exists, but the IDE does not pick it up

Changed files:
src/test/kotlin/org/rust/lang/core/resolve/RsPackageLibraryResolveTest.kt, src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt, src/test/kotlin/org/rust/lang/core/resolve/RsStdlibResolveTest.kt, src/main/kotlin/org/rust/lang/core/resolve/ItemResolution.kt, src/main/kotlin/org/rust/lang/core/psi/ext/RsPath.kt

diff --git a/src/main/kotlin/org/rust/lang/core/psi/ext/RsPath.kt b/src/main/kotlin/org/rust/lang/core/psi/ext/RsPath.kt
index 3e8a1c6da..76a4d3924 100644
--- a/src/main/kotlin/org/rust/lang/core/psi/ext/RsPath.kt
+++ b/src/main/kotlin/org/rust/lang/core/psi/ext/RsPath.kt
@@ -12,6 +12,7 @@ import com.intellij.psi.stubs.IStubElementType
 import org.rust.lang.core.macros.RsExpandedElement
 import org.rust.lang.core.psi.RsElementTypes.*
 import org.rust.lang.core.psi.RsPath
+import org.rust.lang.core.psi.RsUseSpeck
 import org.rust.lang.core.psi.RsVis
 import org.rust.lang.core.psi.tokenSetOf
 import org.rust.lang.core.resolve.ref.RsPathReference
@@ -53,6 +54,16 @@ enum class PathKind {
     CRATE
 }
 
+val RsPath.qualifier: RsPath?
+    get() {
+        path?.let { return it }
+        var ctx = context
+        while (ctx is RsPath) {
+            ctx = ctx.context
+        }
+        return (ctx as? RsUseSpeck)?.qualifier
+    }
+
 abstract class RsPathImplMixin : RsStubbedElementImpl<RsPathStub>,
                                  RsPath {
     constructor(node: ASTNode) : super(node)
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 bc638ba54..499a803cf 100644
--- a/src/main/kotlin/org/rust/lang/core/resolve/ItemResolution.kt
+++ b/src/main/kotlin/org/rust/lang/core/resolve/ItemResolution.kt
@@ -91,14 +91,22 @@ fun processItemDeclarations(
         }
     }
 
+    val isEdition2018 = scope.isEdition2018
     for (speck in itemImports) {
         check(speck.useGroup == null)
         val path = speck.path ?: continue
         val name = speck.nameInScope ?: continue
+
+        if (isEdition2018 && speck.alias == null && path.isAtom) {
+            // Use items like `use foo;` or `use foo::{self}` are meaningless on 2018 edition.
+            // We should ignore it or it breaks resolve of such `foo` in other places.
+            ItemResolutionTestmarks.extraAtomUse.hit()
+            continue
+        }
         if (processMultiResolveWithNs(name, ns, path.reference, processor)) return true
     }
 
-    if (withPrivateImports && Namespace.Types in ns && scope is RsFile && scope.isCrateRoot && !scope.isEdition2018) {
+    if (withPrivateImports && Namespace.Types in ns && scope is RsFile && !isEdition2018 && scope.isCrateRoot) {
         // Rust injects implicit `extern crate std` in every crate root module unless it is
         // a `#![no_std]` crate, in which case `extern crate core` is injected. However, if
         // there is a (unstable?) `#![no_core]` attribute, nothing is injected.
@@ -235,6 +243,14 @@ private val CACHED_ITEM_DECLS: Key<CachedValue<List<ScopeEntry>>> =
 private val CACHED_ITEM_DECLS_WITH_PRIVATE_IMPORTS: Key<CachedValue<List<ScopeEntry>>> =
     Key.create("CACHED_ITEM_DECLS_WITH_PRIVATE_IMPORTS")
 
+private val RsPath.isAtom: Boolean
+    get() = when (kind) {
+        PathKind.IDENTIFIER -> qualifier == null
+        PathKind.SELF -> qualifier?.isAtom == true
+        else -> false
+    }
+
 object ItemResolutionTestmarks {
     val externCrateSelfWithoutAlias = Testmark("externCrateSelfWithoutAlias")
+    val extraAtomUse = Testmark("extraAtomUse")
 }
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 65dc7bd82..477be5c4b 100644
--- a/src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt
+++ b/src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt
@@ -308,16 +308,6 @@ private fun findDependencyCrateByName(context: RsElement, name: String): RsFile?
     return found
 }
 
-private val RsPath.qualifier: RsPath?
-    get() {
-        path?.let { return it }
-        var ctx = context
-        while (ctx is RsPath) {
-            ctx = ctx.context
-        }
-        return (ctx as? RsUseSpeck)?.qualifier
-    }
-
 fun processPathResolveVariants(lookup: ImplLookup, path: RsPath, isCompletion: Boolean, processor: RsResolveProcessor): Boolean {
     val parent = path.context
     if (parent is RsMacroCall) {
diff --git a/src/test/kotlin/org/rust/lang/core/resolve/RsPackageLibraryResolveTest.kt b/src/test/kotlin/org/rust/lang/core/resolve/RsPackageLibraryResolveTest.kt
index d543ad9aa..81af107db 100644
--- a/src/test/kotlin/org/rust/lang/core/resolve/RsPackageLibraryResolveTest.kt
+++ b/src/test/kotlin/org/rust/lang/core/resolve/RsPackageLibraryResolveTest.kt
@@ -642,4 +642,35 @@ class RsPackageLibraryResolveTest : RsResolveTestBase() {
             }
         """)
     }
+
+    // Issue https://github.com/intellij-rust/intellij-rust/issues/3846
+    @MockEdition(CargoWorkspace.Edition.EDITION_2018)
+    fun `test extra use of crate name 1`() = stubOnlyResolve("""
+    //- dep-lib/lib.rs
+        pub struct Foo;
+    //- lib.rs
+        use dep_lib_target;
+        use dep_lib_target::Foo;
+                          //^ dep-lib/lib.rs
+    """, ItemResolutionTestmarks.extraAtomUse)
+
+    @MockEdition(CargoWorkspace.Edition.EDITION_2018)
+    fun `test "extra use of crate name 1" with alias`() = stubOnlyResolve("""
+    //- dep-lib/lib.rs
+        pub struct Foo;
+    //- lib.rs
+        use dep_lib_target as dep;
+        use dep::Foo;
+                 //^ dep-lib/lib.rs
+    """)
+
+    @MockEdition(CargoWorkspace.Edition.EDITION_2018)
+    fun `test extra use of crate name 2`() = stubOnlyResolve("""
+    //- dep-lib/lib.rs
+        pub struct Foo;
+    //- lib.rs
+        use dep_lib_target::{self};
+        use dep_lib_target::Foo;
+                          //^ dep-lib/lib.rs
+    """, ItemResolutionTestmarks.extraAtomUse)
 }
diff --git a/src/test/kotlin/org/rust/lang/core/resolve/RsStdlibResolveTest.kt b/src/test/kotlin/org/rust/lang/core/resolve/RsStdlibResolveTest.kt
index 4261ac834..2a71fe9ea 100644
--- a/src/test/kotlin/org/rust/lang/core/resolve/RsStdlibResolveTest.kt
+++ b/src/test/kotlin/org/rust/lang/core/resolve/RsStdlibResolveTest.kt
@@ -649,4 +649,14 @@ class RsStdlibResolveTest : RsResolveTestBase() {
         use crate::std::mem;
                  //^ unresolved
     """)
+
+    @MockEdition(CargoWorkspace.Edition.EDITION_2018)
+    fun `test extra use of prelude item`() = stubOnlyResolve("""
+    //- main.rs
+        use Vec;
+
+        fn main() {
+            let a = Vec::<i32>::new();
+        }         //^ .../vec.rs
+    """, ItemResolutionTestmarks.extraAtomUse)
 }