diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ConverterUtil.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ConverterUtil.kt index b86ece21490..ee93104dd3c 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ConverterUtil.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ConverterUtil.kt @@ -112,6 +112,7 @@ fun generateDestructuringBlock( } val isVar = multiDeclaration.isVar for ((index, entry) in multiDeclaration.entries.withIndex()) { + if (entry == null) continue statements += buildProperty { this.session = session origin = FirDeclarationOrigin.Source diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt index 1482b8696ea..283b1afb22b 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt @@ -1068,7 +1068,7 @@ class DeclarationsConverter( */ private fun convertDestructingDeclaration(destructingDeclaration: LighterASTNode): DestructuringDeclaration { var isVar = false - val entries = mutableListOf>() + val entries = mutableListOf?>() val source = destructingDeclaration.toFirSourceElement() var firExpression: FirExpression = buildErrorExpression(null, ConeSimpleDiagnostic("Initializer required for destructuring declaration", DiagnosticKind.Syntax)) @@ -1087,7 +1087,7 @@ class DeclarationsConverter( /** * @see org.jetbrains.kotlin.parsing.KotlinParsing.parseMultiDeclarationName */ - private fun convertDestructingDeclarationEntry(entry: LighterASTNode): FirVariable<*> { + private fun convertDestructingDeclarationEntry(entry: LighterASTNode): FirVariable<*>? { var modifiers = Modifier() var identifier: String? = null var firType: FirTypeRef? = null @@ -1099,6 +1099,7 @@ class DeclarationsConverter( } } + if (identifier == "_") return null val name = identifier.nameAsSafeName() return buildProperty { source = entry.toFirSourceElement() diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/DestructuringDeclaration.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/DestructuringDeclaration.kt index 765246daee9..19c69a3a418 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/DestructuringDeclaration.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/DestructuringDeclaration.kt @@ -14,7 +14,7 @@ import org.jetbrains.kotlin.fir.lightTree.converter.generateDestructuringBlock data class DestructuringDeclaration( val isVar: Boolean, - val entries: List>, + val entries: List?>, val initializer: FirExpression, val source: FirSourceElement ) { diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt index 0764dad252d..289c9af8859 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt @@ -96,6 +96,7 @@ internal fun generateDestructuringBlock( } val isVar = multiDeclaration.isVar for ((index, entry) in multiDeclaration.entries.withIndex()) { + if (entry.nameIdentifier?.text == "_") continue val entrySource = entry.toFirPsiSourceElement() val name = entry.nameAsSafeName statements += buildProperty { diff --git a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/destructuring.kt b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/destructuring.kt index cbd1e4c459d..3153d704733 100644 --- a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/destructuring.kt +++ b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/destructuring.kt @@ -6,4 +6,8 @@ fun foo(some: Some) { x++ y *= 2.0 z = "" +} + +fun bar(some: Some) { + val (a, _, `_`) = some } \ No newline at end of file diff --git a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/destructuring.lazyBodies.txt b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/destructuring.lazyBodies.txt index 448ffb13fdc..be3cbea5662 100644 --- a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/destructuring.lazyBodies.txt +++ b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/destructuring.lazyBodies.txt @@ -23,3 +23,4 @@ FILE: destructuring.kt } public? final? fun foo(some: Some): R|kotlin/Unit| { LAZY_BLOCK } + public? final? fun bar(some: Some): R|kotlin/Unit| { LAZY_BLOCK } diff --git a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/destructuring.txt b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/destructuring.txt index e57b8b034fa..e912e0574ac 100644 --- a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/destructuring.txt +++ b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/destructuring.txt @@ -33,3 +33,8 @@ FILE: destructuring.kt *=(y#, Double(2.0)) z# = String() } + public? final? fun bar(some: Some): R|kotlin/Unit| { + lval : = some# + lval a: = R|/|.component1#() + lval _: = R|/|.component3#() + } diff --git a/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt b/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt index 351c4bd85bb..635204ce4c5 100644 --- a/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt +++ b/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt @@ -264,6 +264,7 @@ class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() { it.getStrictParentOfType() != null || it.getStrictParentOfType() != null || (it is KtPropertyAccessor && !it.hasBody()) || + it is KtDestructuringDeclarationEntry && it.text == "_" || it is KtConstantExpression && it.parent.let { parent -> parent is KtPrefixExpression && (parent.operationToken == KtTokens.MINUS || parent.operationToken == KtTokens.PLUS) } diff --git a/compiler/testData/codegen/box/destructuringDeclInLambdaParam/underscoreNames.kt b/compiler/testData/codegen/box/destructuringDeclInLambdaParam/underscoreNames.kt index 70e03674326..8db07f7778e 100644 --- a/compiler/testData/codegen/box/destructuringDeclInLambdaParam/underscoreNames.kt +++ b/compiler/testData/codegen/box/destructuringDeclInLambdaParam/underscoreNames.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR class A { operator fun component1() = "O" operator fun component2(): String = throw RuntimeException("fail 0") diff --git a/compiler/testData/codegen/box/multiDecl/forRange/UnderscoreNamesDontCallComponent.kt b/compiler/testData/codegen/box/multiDecl/forRange/UnderscoreNamesDontCallComponent.kt index 4495ab9f6d5..644125c9809 100644 --- a/compiler/testData/codegen/box/multiDecl/forRange/UnderscoreNamesDontCallComponent.kt +++ b/compiler/testData/codegen/box/multiDecl/forRange/UnderscoreNamesDontCallComponent.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR class A { operator fun component1() = "O" operator fun component2(): String = throw RuntimeException("fail 0") diff --git a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopMissingLoopParameter.fir.kt b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopMissingLoopParameter.fir.kt index 9bbbd640e91..0bc48dd8f5b 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopMissingLoopParameter.fir.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopMissingLoopParameter.fir.kt @@ -7,7 +7,7 @@ fun useDeclaredVariables() { } fun checkersShouldRun() { - for ((@A a, _)) { + for ((@A a, _)) { } } diff --git a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/destructuringDeclarationAssignedUnresolved.fir.kt b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/destructuringDeclarationAssignedUnresolved.fir.kt index d4235c70ed3..da599329974 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/destructuringDeclarationAssignedUnresolved.fir.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/destructuringDeclarationAssignedUnresolved.fir.kt @@ -5,7 +5,7 @@ fun useDeclaredVariables() { } fun checkersShouldRun() { - val (@A a, _) = unresolved + val (@A a, _) = unresolved } annotation class A diff --git a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/destructuringDeclarationMissingInitializer.fir.kt b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/destructuringDeclarationMissingInitializer.fir.kt index d1b014c2579..307dc46e555 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/destructuringDeclarationMissingInitializer.fir.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/destructuringDeclarationMissingInitializer.fir.kt @@ -5,7 +5,7 @@ fun useDeclaredVariables() { } fun checkersShouldRun() { - val (@A a, _) + val (@A a, _) } annotation class A diff --git a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/underscore.fir.kt b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/underscore.fir.kt index 10556a5c3dc..5760a1440ba 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/underscore.fir.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/underscore.fir.kt @@ -11,31 +11,31 @@ class C { fun test() { for ((x, _) in C()) { - foo(x, _) + foo(x, _) } for ((_, y) in C()) { - foo(_, y) + foo(_, y) } for ((_, _) in C()) { - foo(_, _) + foo(_, _) } for ((_ : Int, _ : String) in C()) { - foo(_, _) + foo(_, _) } for ((_ : String, _ : Int) in C()) { - foo(_, _) + foo(_, _) } val (x, _) = A() val (_, y) = A() foo(x, y) - foo(x, _) - foo(_, y) + foo(x, _) + foo(_, y) val (`_`, z) = A() diff --git a/compiler/testData/diagnostics/tests/functionLiterals/destructuringInLambdas/underscore.fir.kt b/compiler/testData/diagnostics/tests/functionLiterals/destructuringInLambdas/underscore.fir.kt index f08a2af15d7..0dda6673162 100644 --- a/compiler/testData/diagnostics/tests/functionLiterals/destructuringInLambdas/underscore.fir.kt +++ b/compiler/testData/diagnostics/tests/functionLiterals/destructuringInLambdas/underscore.fir.kt @@ -8,39 +8,39 @@ fun foo(block: (A) -> Unit) { } fun bar() { foo { (_, b) -> - _.hashCode() + _.hashCode() b checkType { _() } } foo { (a, _) -> a checkType { _() } - _.hashCode() + _.hashCode() } foo { (_, _) -> - _.hashCode() + _.hashCode() } foo { (_: Int, b: String) -> - _.hashCode() + _.hashCode() b checkType { _() } } foo { (a: Int, _: String) -> a checkType { _() } - _.hashCode() + _.hashCode() } foo { (_: Int, _: String) -> - _.hashCode() + _.hashCode() } foo { (_, _): A -> - _.hashCode() + _.hashCode() } foo { (`_`, _) -> - _ checkType { _() } + _ checkType { _() } } foo { (_, `_`) -> @@ -52,12 +52,12 @@ fun bar() { } foo { (_: String, b) -> - _.hashCode() + _.hashCode() b checkType { _() } } foo { (_, b): B -> - _.hashCode() + _.hashCode() b checkType { _() } } } diff --git a/compiler/testData/ir/irText/expressions/destructuringWithUnderscore.fir.kt.txt b/compiler/testData/ir/irText/expressions/destructuringWithUnderscore.fir.kt.txt index dff11a75023..ae855d61c3d 100644 --- a/compiler/testData/ir/irText/expressions/destructuringWithUnderscore.fir.kt.txt +++ b/compiler/testData/ir/irText/expressions/destructuringWithUnderscore.fir.kt.txt @@ -31,6 +31,5 @@ object B { fun B.test() { val : A = A val x: Int = (, ).component1() - val _: Int = (, ).component2() val z: Int = (, ).component3() } diff --git a/compiler/testData/ir/irText/expressions/destructuringWithUnderscore.fir.txt b/compiler/testData/ir/irText/expressions/destructuringWithUnderscore.fir.txt index d7408b4e2cc..efb3de95417 100644 --- a/compiler/testData/ir/irText/expressions/destructuringWithUnderscore.fir.txt +++ b/compiler/testData/ir/irText/expressions/destructuringWithUnderscore.fir.txt @@ -64,10 +64,6 @@ FILE fqName: fileName:/destructuringWithUnderscore.kt CALL 'public final fun component1 (): kotlin.Int [operator] declared in .B' type=kotlin.Int origin=null $this: GET_VAR ': .B declared in .test' type=.B origin=null $receiver: GET_VAR 'val tmp_0: .A [val] declared in .test' type=.A origin=null - VAR name:_ type:kotlin.Int [val] - CALL 'public final fun component2 (): kotlin.Int [operator] declared in .B' type=kotlin.Int origin=null - $this: GET_VAR ': .B declared in .test' type=.B origin=null - $receiver: GET_VAR 'val tmp_0: .A [val] declared in .test' type=.A origin=null VAR name:z type:kotlin.Int [val] CALL 'public final fun component3 (): kotlin.Int [operator] declared in .B' type=kotlin.Int origin=null $this: GET_VAR ': .B declared in .test' type=.B origin=null diff --git a/compiler/testData/ir/irText/lambdas/destructuringInLambda.fir.kt.txt b/compiler/testData/ir/irText/lambdas/destructuringInLambda.fir.kt.txt index 801757a9b58..23eb3ba3ee1 100644 --- a/compiler/testData/ir/irText/lambdas/destructuringInLambda.fir.kt.txt +++ b/compiler/testData/ir/irText/lambdas/destructuringInLambda.fir.kt.txt @@ -56,7 +56,6 @@ data class A { var fn: Function1 field = local fun (: A): Int { - val _: Int = .component1() val y: Int = .component2() return 42.plus(other = y) } diff --git a/compiler/testData/ir/irText/lambdas/destructuringInLambda.fir.txt b/compiler/testData/ir/irText/lambdas/destructuringInLambda.fir.txt index ea4206cd8b8..f47ca804e57 100644 --- a/compiler/testData/ir/irText/lambdas/destructuringInLambda.fir.txt +++ b/compiler/testData/ir/irText/lambdas/destructuringInLambda.fir.txt @@ -142,9 +142,6 @@ FILE fqName: fileName:/destructuringInLambda.kt FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (:.A) returnType:kotlin.Int VALUE_PARAMETER name: index:0 type:.A BLOCK_BODY - VAR name:_ type:kotlin.Int [val] - CALL 'public final fun component1 (): kotlin.Int declared in .A' type=kotlin.Int origin=null - $this: GET_VAR ': .A declared in .fn.' type=.A origin=null VAR name:y type:kotlin.Int [val] CALL 'public final fun component2 (): kotlin.Int declared in .A' type=kotlin.Int origin=null $this: GET_VAR ': .A declared in .fn.' type=.A origin=null