Repository: intellij-rust/intellij-rust
Issue: `asm!` macro cannot be resolved on nightly

<!--
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.155.4090-212-nightly
* **Rust toolchain version:** 1.56.0-nightly (29ef6cf16 2021-08-31) x86_64-apple-darwin
* **IDE name and version:** IntelliJ IDEA 2021.2.2 Preview Ultimate Edition (IU-212.5284.19)
* **Operating system:** macOS 10.15.6
* **Macro expansion engine:** new
* **Name resolution engine:** new

## Problem description
On nightly, `asm` macro [became](https://github.com/rust-lang/rust/pull/87227) [macro 2.0](https://rust-lang.github.io/rfcs/1584-macros.html) and was moved to another module. As a result, the plugin can't resolve it and doesn't annotate its usage without `unsafe` block as an error

## Steps to reproduce
```rust
#![feature(asm)]

fn main() {
    asm!("nop");
}

```

<!--
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/psi/ext/RsMacroCall.kt
src/main/kotlin/org/rust/lang/core/completion/RsPartialMacroArgumentCompletionProvider.kt
src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt
src/test/kotlin/org/rust/lang/core/resolve/RsStdlibResolveTest.kt
src/test/kotlin/org/rust/lang/core/macros/decl/RsMacroGraphWalkerTest.kt
src/main/kotlin/org/rust/lang/core/resolve2/FacadeResolve.kt

diff --git a/src/main/kotlin/org/rust/lang/core/completion/RsPartialMacroArgumentCompletionProvider.kt b/src/main/kotlin/org/rust/lang/core/completion/RsPartialMacroArgumentCompletionProvider.kt
index 3ac9b83e6..a52828d6c 100644
--- a/src/main/kotlin/org/rust/lang/core/completion/RsPartialMacroArgumentCompletionProvider.kt
+++ b/src/main/kotlin/org/rust/lang/core/completion/RsPartialMacroArgumentCompletionProvider.kt
@@ -48,7 +48,7 @@ object RsPartialMacroArgumentCompletionProvider : RsCompletionProvider() {
 
         val bodyTextRange = macroCall.bodyTextRange ?: return
         val macroCallBody = macroCall.macroBody ?: return
-        val macro = macroCall.resolveToMacro() ?: return
+        val macro = macroCall.resolveToMacro() as? RsMacro ?: return  // TODO macro 2
         val graph = macro.graph ?: return
         val offsetInArgument = parameters.offset - bodyTextRange.startOffset
 
diff --git a/src/main/kotlin/org/rust/lang/core/psi/ext/RsMacroCall.kt b/src/main/kotlin/org/rust/lang/core/psi/ext/RsMacroCall.kt
index 624cb80a1..4d9003c41 100644
--- a/src/main/kotlin/org/rust/lang/core/psi/ext/RsMacroCall.kt
+++ b/src/main/kotlin/org/rust/lang/core/psi/ext/RsMacroCall.kt
@@ -14,7 +14,6 @@ import com.intellij.psi.stubs.IStubElementType
 import com.intellij.psi.tree.TokenSet
 import com.intellij.psi.util.CachedValueProvider
 import com.intellij.psi.util.CachedValuesManager
-import org.rust.cargo.project.settings.rustSettings
 import org.rust.cargo.project.settings.toolchain
 import org.rust.cargo.toolchain.RsToolchainBase
 import org.rust.lang.core.crate.Crate
@@ -156,8 +155,8 @@ val RsMacroCall.bodyHash: HashCode?
         }
     }
 
-fun RsMacroCall.resolveToMacro(): RsMacro? =
-    path.reference?.resolve() as? RsMacro
+fun RsMacroCall.resolveToMacro(): RsMacroDefinitionBase? =
+    path.reference?.resolve() as? RsMacroDefinitionBase
 
 val RsMacroCall.expansionFlatten: List<RsExpandedElement>
     get() {
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 792be0359..af6c7438d 100644
--- a/src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt
+++ b/src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt
@@ -865,7 +865,7 @@ fun processMacroCallPathResolveVariants(path: RsPath, isCompletion: Boolean, pro
                     ?.resolveToMacroAndProcessLocalInnerMacros(processor) {
                         /* this code will be executed if new resolve can't be used */
                         val def = expandedFrom.resolveToMacro() ?: return@resolveToMacroAndProcessLocalInnerMacros null
-                        if (!def.hasMacroExportLocalInnerMacros) return@resolveToMacroAndProcessLocalInnerMacros null
+                        if (def !is RsMacro || !def.hasMacroExportLocalInnerMacros) return@resolveToMacroAndProcessLocalInnerMacros null
                         val crateRoot = def.crateRoot as? RsFile ?: return@resolveToMacroAndProcessLocalInnerMacros false
                         processAll(exportedMacros(crateRoot), processor)
                     }
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 7d273d27c..33658c912 100644
--- a/src/main/kotlin/org/rust/lang/core/resolve2/FacadeResolve.kt
+++ b/src/main/kotlin/org/rust/lang/core/resolve2/FacadeResolve.kt
@@ -136,23 +136,17 @@ private fun ModData.processMacros(
 ): Boolean {
     val isQualified = macroPath == null || macroPath is RsPath && macroPath.qualifier != null
 
-    for ((name, perNs) in visibleItems.entriesWithName(processor.name)) {
-        for (visItem in perNs.macros) {
-            val isLegacyMacroDeclaredInSameMod = !isQualified && legacyMacros[name].orEmpty().any {
-                (!isAttrOrDerive || it is ProcMacroDefInfo) && it.path.parent == path
-            }
-            if (isLegacyMacroDeclaredInSameMod) {
-                // Resolve order for unqualified macros:
-                // - textual macros in same mod
-                // - scoped macros (imported by `use`)
-                // - textual macros
-                continue
-            }
-            val macro = visItem.scopedMacroToPsi(defMap, project) ?: continue
-            val visibilityFilter = visItem.visibility.createFilter(project)
-            if (processor(name, macro, visibilityFilter)) return true
+    val stop = processScopedMacros(processor, defMap, project) { name ->
+        val isLegacyMacroDeclaredInSameMod = !isQualified && legacyMacros[name].orEmpty().any {
+            (!isAttrOrDerive || it is ProcMacroDefInfo) && it.path.parent == path
         }
+        // Resolve order for unqualified macros:
+        // - textual macros in same mod
+        // - scoped macros (imported by `use`)
+        // - textual macros
+        !isLegacyMacroDeclaredInSameMod
     }
+    if (stop) return true
 
     if (!isQualified) {
         check(macroPath != null)
@@ -169,11 +163,32 @@ private fun ModData.processMacros(
             val macro = macroInfo.legacyMacroToPsi(macroContainingMod, macroDefMap) ?: continue
             if (processor(name, macro)) return true
         }
+
+        defMap.prelude?.let { prelude ->
+            if (prelude.processScopedMacros(processor, defMap, project)) return true
+        }
     }
 
     return false
 }
 
+private fun ModData.processScopedMacros(
+    processor: RsResolveProcessor,
+    defMap: CrateDefMap,
+    project: Project,
+    filter: (name: String) -> Boolean = { true },
+): Boolean {
+    for ((name, perNs) in visibleItems.entriesWithName(processor.name)) {
+        for (visItem in perNs.macros) {
+            if (!filter(name)) continue
+            val macro = visItem.scopedMacroToPsi(defMap, project) ?: continue
+            val visibilityFilter = visItem.visibility.createFilter(project)
+            if (processor(name, macro, visibilityFilter)) return true
+        }
+    }
+    return false
+}
+
 private fun filterMacrosByIndex(macroInfos: List<MacroDefInfo>, macroIndex: MacroIndex?): MacroDefInfo? =
     when {
         macroIndex != null -> macroInfos.getLastBefore(macroIndex)
@@ -379,7 +394,8 @@ private val RsPath.pathSegmentsAdjusted: List<String>?
                 is CantUseNewResolve -> {
                     val expandedFrom = callExpandedFrom.resolveToMacro() ?: return segments
                     val crateId = expandedFrom.containingCrate?.id ?: return segments
-                    expandedFrom.hasMacroExportLocalInnerMacros to crateId
+                    val hasMacroExportLocalInnerMacros = expandedFrom is RsMacro && expandedFrom.hasMacroExportLocalInnerMacros
+                    hasMacroExportLocalInnerMacros to crateId
                 }
                 InfoNotFound -> return segments
                 is RsModInfo -> {
diff --git a/src/test/kotlin/org/rust/lang/core/macros/decl/RsMacroGraphWalkerTest.kt b/src/test/kotlin/org/rust/lang/core/macros/decl/RsMacroGraphWalkerTest.kt
index 122ae52ac..4a339a7ab 100644
--- a/src/test/kotlin/org/rust/lang/core/macros/decl/RsMacroGraphWalkerTest.kt
+++ b/src/test/kotlin/org/rust/lang/core/macros/decl/RsMacroGraphWalkerTest.kt
@@ -9,6 +9,7 @@ import org.intellij.lang.annotations.Language
 import org.rust.ProjectDescriptor
 import org.rust.RsTestBase
 import org.rust.WithStdlibRustProjectDescriptor
+import org.rust.lang.core.psi.RsMacro
 import org.rust.lang.core.psi.RsMacroCall
 import org.rust.lang.core.psi.ext.*
 
@@ -16,7 +17,7 @@ class RsMacroGraphWalkerTest : RsTestBase() {
     private fun check(@Language("Rust") code: String, expected: HashSet<FragmentKind>) {
         InlineFile(code)
         val macroCall = myFixture.file.descendantsOfType<RsMacroCall>().single()
-        val macro = macroCall.resolveToMacro()!!
+        val macro = macroCall.resolveToMacro() as RsMacro
         val graph = macro.graph!!
 
         val position = myFixture.file.findElementAt(myFixture.caretOffset - 1)!!
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 40d1a810f..937d26d87 100644
--- a/src/test/kotlin/org/rust/lang/core/resolve/RsStdlibResolveTest.kt
+++ b/src/test/kotlin/org/rust/lang/core/resolve/RsStdlibResolveTest.kt
@@ -276,6 +276,15 @@ class RsStdlibResolveTest : RsResolveTestBase() {
         }   //^ ...libcore/macros/mod.rs|...core/src/macros/mod.rs
     """)
 
+    // macro 2.0 since rust 1.55
+    fun `test asm macro`() = stubOnlyResolve("""
+    //- main.rs
+        #![feature(asm)]
+        fn main() {
+            asm!("nop");
+        } //^ ...core/src/lib.rs|...libcore/macros/mod.rs|...core/src/macros/mod.rs
+    """)
+
     fun `test iterating a vec`() = stubOnlyResolve("""
     //- main.rs
         struct FooBar;