Skip to content

Commit

Permalink
Merge #10749 #10750
Browse files Browse the repository at this point in the history
10749: Use `processElementsWithMacros` when resolving pattern binding r=missingdays a=missingdays



10750: Fix inspection "Unused must_use" for `tokio::main` proc macro r=dima74 a=dima74

We don't expand `tokio::main` async function, so return type of such function was considered as `impl Future`, though actually `tokio::main` expands to function returning unit

Co-authored-by: evgeny.bovykin <evgeny.bovykin@jetbrains.com>
Co-authored-by: Dmitry Murzin <dmitry.murzin@jetbrains.com>
  • Loading branch information
3 people committed Jul 26, 2023
3 parents 230ad2e + b5c154b + 0bd6317 commit 6a6cb28
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 16 deletions.
Expand Up @@ -18,6 +18,7 @@ import org.rust.ide.inspections.RsProblemsHolder
import org.rust.ide.inspections.RsWithMacrosInspectionVisitor
import org.rust.ide.utils.template.newTemplateBuilder
import org.rust.lang.core.psi.*
import org.rust.lang.core.psi.KnownProcMacroKind.*
import org.rust.lang.core.psi.ext.RsItemElement
import org.rust.lang.core.psi.ext.expandedStmtsAndTailExpr
import org.rust.lang.core.psi.ext.findFirstMetaItem
Expand Down Expand Up @@ -85,8 +86,14 @@ private class InspectionResult(@InspectionMessage val description: String, val f

private fun inspectAndProposeFixes(expr: RsExpr): InspectionResult? {
val fixes = mutableListOf<LocalQuickFix>()
val function = when (expr) {
is RsDotExpr -> expr.methodCall?.getFunctionCallContext()?.function
is RsCallExpr -> expr.getFunctionCallContext()?.function
else -> null
}
if (isAsyncHardcodedProcMacro(function)) return null
val description = checkTypeMustUse(expr.type, expr, fixes)
?: checkFuncMustUse(expr)
?: checkFuncMustUse(function)
?: return null
if (expr.returnsStdResult()) {
fixes += FixAddExpect(expr)
Expand All @@ -96,14 +103,18 @@ private fun inspectAndProposeFixes(expr: RsExpr): InspectionResult? {
return InspectionResult(description, fixes)
}

private fun checkFuncMustUse(expr: RsExpr): @Nls String? {
val func = when (expr) {
is RsDotExpr -> expr.methodCall?.getFunctionCallContext()?.function
is RsCallExpr -> expr.getFunctionCallContext()?.function
else -> null
} ?: return null
if (!func.hasMustUseAttr()) return null
return RsBundle.message("inspection.UnusedMustUse.description.function.attribute", func.name.toString())
// `#[tokio::main] async fn main() { ... }` actually doesn't return `Future`
private fun isAsyncHardcodedProcMacro(function: RsFunction?): Boolean {
if (function == null) return false
val hardcodedProcMacros = ProcMacroAttribute.getHardcodedProcMacroAttributes(function)
return hardcodedProcMacros.any {
it == ASYNC_MAIN || it == ASYNC_TEST || it == ASYNC_BENCH
}
}

private fun checkFuncMustUse(function: RsFunction?): @Nls String? {
if (function == null || !function.hasMustUseAttr()) return null
return RsBundle.message("inspection.UnusedMustUse.description.function.attribute", function.name.toString())
}

private fun checkTypeMustUse(type: Ty, expr: RsExpr, fixes: MutableList<LocalQuickFix>): @Nls String? {
Expand Down
23 changes: 16 additions & 7 deletions src/main/kotlin/org/rust/lang/core/resolve/NameResolution.kt
Expand Up @@ -21,7 +21,6 @@ import com.intellij.psi.stubs.StubElement
import com.intellij.psi.util.CachedValue
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.util.ThreeState
import org.rust.cargo.project.workspace.CargoWorkspace
import org.rust.cargo.project.workspace.PackageOrigin
Expand Down Expand Up @@ -1517,12 +1516,22 @@ private fun processLexicalDeclarations(
alreadyProcessedNames.add(e.name) // Process element if it is not in the set
}

return PsiTreeUtil.findChildrenOfType(pattern, RsPatBinding::class.java).any { binding ->
val name = binding.name ?: return@any false
patternProcessor.lazy(name, VALUES) {
binding.takeIf { (it.parent is RsPatField || !it.isReferenceToConstant) && hygieneFilter(it) }
}
}
return !processElementsWithMacros(pattern) { binding ->
if (binding !is RsPatBinding) {
return@processElementsWithMacros TreeStatus.VISIT_CHILDREN
}

val name = binding.name ?: return@processElementsWithMacros TreeStatus.SKIP_CHILDREN
val result = patternProcessor.lazy(name, VALUES) {
binding.takeIf { (binding.parent is RsPatField || !binding.isReferenceToConstant) && hygieneFilter(binding) }
}

if (result) {
TreeStatus.ABORT
} else {
TreeStatus.SKIP_CHILDREN
}
}
}

fun processLetExprs(
Expand Down
Expand Up @@ -1086,4 +1086,16 @@ class RsMacroExpansionResolveTest : RsResolveTestBase() {
foo! {}
}
""")

fun `test expansion in pattern context`() = checkByCode("""
macro_rules! var {
($ i:ident) => { $ i };
}
fn foo() {
let var!(a) = 1;
//X
a;
} //^
""")
}

0 comments on commit 6a6cb28

Please sign in to comment.