FIR: generate destructurings for more than one parameter
This commit is contained in:
+5
@@ -521,6 +521,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/definetelyNotNullForTypeParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("destructuring.kt")
|
||||
public void testDestructuring() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/destructuring.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("extensionLambdaInDefaultArgument.kt")
|
||||
public void testExtensionLambdaInDefaultArgument() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/extensionLambdaInDefaultArgument.kt");
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
FILE: destructuring.kt
|
||||
public final data class C : R|kotlin/Any| {
|
||||
public constructor(x: R|kotlin/Int|, y: R|kotlin/String|): R|C| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val x: R|kotlin/Int| = R|<local>/x|
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
public final val y: R|kotlin/String| = R|<local>/y|
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
public final operator fun component1(): R|kotlin/Int|
|
||||
|
||||
public final operator fun component2(): R|kotlin/String|
|
||||
|
||||
public final fun copy(x: R|kotlin/Int| = this@R|/C|.R|/C.x|, y: R|kotlin/String| = this@R|/C|.R|/C.y|): R|C|
|
||||
|
||||
}
|
||||
public final fun foo1(block: R|(C) -> kotlin/Unit|): R|kotlin/Unit| {
|
||||
^foo1 R|<local>/block|.R|SubstitutionOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(R|/C.C|(Int(0), String()))
|
||||
}
|
||||
public final fun foo2(block: R|(C, C) -> kotlin/Unit|): R|kotlin/Unit| {
|
||||
^foo2 R|<local>/block|.R|SubstitutionOverride<kotlin/Function2.invoke: R|kotlin/Unit|>|(R|/C.C|(Int(0), String()), R|/C.C|(Int(0), String()))
|
||||
}
|
||||
public final fun test(): R|kotlin/Unit| {
|
||||
R|/foo1|(<L> = foo1@fun <anonymous>(<destruct>: R|C|): R|kotlin/Unit| <inline=NoInline> {
|
||||
lval x: R|kotlin/Int| = R|<local>/<destruct>|.R|/C.component1|()
|
||||
lval y: R|kotlin/String| = R|<local>/<destruct>|.R|/C.component2|()
|
||||
R|/C.C|(R|<local>/x|, R|<local>/y|)
|
||||
}
|
||||
)
|
||||
R|/foo1|(<L> = foo1@fun <anonymous>(<destruct>: R|C|): R|kotlin/Unit| <inline=NoInline> {
|
||||
lval x: R|kotlin/Int| = R|<local>/<destruct>|.R|/C.component1|()
|
||||
lval y: R|kotlin/String| = R|<local>/<destruct>|.R|/C.component2|()
|
||||
R|/C.C|(R|<local>/x|, R|<local>/y|)
|
||||
}
|
||||
)
|
||||
R|/foo1|(<L> = foo1@fun <anonymous>(<destruct>: R|C|): R|kotlin/Unit| <inline=NoInline> {
|
||||
lval x: R|kotlin/String| = R|<local>/<destruct>|.R|/C.component1|()
|
||||
lval y: R|kotlin/Int| = R|<local>/<destruct>|.R|/C.component2|()
|
||||
<Inapplicable(INAPPLICABLE): /C.C>#(R|<local>/x|, R|<local>/y|)
|
||||
}
|
||||
)
|
||||
R|/foo2|(<L> = foo2@fun <anonymous>(<destruct>: R|C|, <destruct>: R|C|): R|kotlin/Unit| <inline=NoInline> {
|
||||
lval x: R|kotlin/Int| = R|<local>/<destruct>|.R|/C.component1|()
|
||||
lval y: R|kotlin/String| = R|<local>/<destruct>|.R|/C.component2|()
|
||||
lval z: R|kotlin/Int| = R|<local>/<destruct>|.R|/C.component1|()
|
||||
lval w: R|kotlin/String| = R|<local>/<destruct>|.R|/C.component2|()
|
||||
R|/C.C|(R|<local>/x|.R|kotlin/Int.plus|(R|<local>/z|), R|<local>/y|.R|kotlin/String.plus|(R|<local>/w|))
|
||||
}
|
||||
)
|
||||
R|/foo2|(<L> = foo2@fun <anonymous>(<destruct>: R|C|, <destruct>: R|C|): R|kotlin/Unit| <inline=NoInline> {
|
||||
lval x: R|kotlin/Int| = R|<local>/<destruct>|.R|/C.component1|()
|
||||
lval y: R|kotlin/String| = R|<local>/<destruct>|.R|/C.component2|()
|
||||
lval z: R|kotlin/Int| = R|<local>/<destruct>|.R|/C.component1|()
|
||||
lval w: R|kotlin/String| = R|<local>/<destruct>|.R|/C.component2|()
|
||||
R|/C.C|(R|<local>/x|.R|kotlin/Int.plus|(R|<local>/z|), R|<local>/y|.R|kotlin/String.plus|(R|<local>/w|))
|
||||
}
|
||||
)
|
||||
R|/foo2|(<L> = foo2@fun <anonymous>(<destruct>: R|C|, <destruct>: R|C|): R|kotlin/Unit| <inline=NoInline> {
|
||||
lval x: R|kotlin/String| = R|<local>/<destruct>|.R|/C.component1|()
|
||||
lval y: R|kotlin/Int| = R|<local>/<destruct>|.R|/C.component2|()
|
||||
lval z: R|kotlin/String| = R|<local>/<destruct>|.R|/C.component1|()
|
||||
lval w: R|kotlin/Int| = R|<local>/<destruct>|.R|/C.component2|()
|
||||
<Inapplicable(INAPPLICABLE): /C.C>#(R|<local>/x|.R|kotlin/String.plus|(R|<local>/z|), R|<local>/y|.R|kotlin/Int.plus|(R|<local>/w|))
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
data class C(val x: Int, val y: String)
|
||||
|
||||
fun foo1(block: (C) -> Unit) = block(C(0, ""))
|
||||
fun foo2(block: (C, C) -> Unit) = block(C(0, ""), C(0, ""))
|
||||
|
||||
fun test() {
|
||||
foo1 { (x, y) -> C(x, y) }
|
||||
foo1 { (x: Int, y: String) -> C(x, y) }
|
||||
foo1 { (x: String, y: Int) -> <!INAPPLICABLE_CANDIDATE!>C<!>(x, y) }
|
||||
foo2 { (x, y), (z, w) -> C(x + z, y + w) }
|
||||
foo2 { (x: Int, y: String), (z: Int, w: String) -> C(x + z, y + w) }
|
||||
foo2 { (x: String, y: Int), (z: String, w: Int) -> <!INAPPLICABLE_CANDIDATE!>C<!>(x + z, y + w) }
|
||||
}
|
||||
+6
@@ -611,6 +611,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/definetelyNotNullForTypeParameter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("destructuring.kt")
|
||||
public void testDestructuring() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/destructuring.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("extensionLambdaInDefaultArgument.kt")
|
||||
public void testExtensionLambdaInDefaultArgument() throws Exception {
|
||||
|
||||
+6
@@ -615,6 +615,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/definetelyNotNullForTypeParameter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("destructuring.kt")
|
||||
public void testDestructuring() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/arguments/destructuring.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("extensionLambdaInDefaultArgument.kt")
|
||||
public void testExtensionLambdaInDefaultArgument() throws Exception {
|
||||
|
||||
+2
-1
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||
import org.jetbrains.kotlin.fir.declarations.FirVariable
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.*
|
||||
import org.jetbrains.kotlin.fir.lightTree.fir.DestructuringDeclaration
|
||||
@@ -106,7 +107,7 @@ fun generateDestructuringBlock(
|
||||
multiDeclaration: DestructuringDeclaration,
|
||||
container: FirVariable<*>,
|
||||
tmpVariable: Boolean
|
||||
): FirExpression {
|
||||
): FirBlock {
|
||||
return buildBlock {
|
||||
if (tmpVariable) {
|
||||
statements += container
|
||||
|
||||
+5
-13
@@ -147,7 +147,7 @@ class ExpressionsConverter(
|
||||
}
|
||||
target = FirFunctionTarget(labelName = label?.name, isLambda = true)
|
||||
context.firFunctionTargets += target
|
||||
var destructuringBlock: FirExpression? = null
|
||||
val destructuringStatements = mutableListOf<FirStatement>()
|
||||
for (valueParameter in valueParameterList) {
|
||||
val multiDeclaration = valueParameter.destructuringDeclaration
|
||||
valueParameters += if (multiDeclaration != null) {
|
||||
@@ -163,12 +163,12 @@ class ExpressionsConverter(
|
||||
isNoinline = false
|
||||
isVararg = false
|
||||
}
|
||||
destructuringBlock = generateDestructuringBlock(
|
||||
destructuringStatements += generateDestructuringBlock(
|
||||
this@ExpressionsConverter.baseSession,
|
||||
multiDeclaration,
|
||||
multiParameter,
|
||||
tmpVariable = false
|
||||
)
|
||||
).statements
|
||||
multiParameter
|
||||
} else {
|
||||
valueParameter.firValueParameter
|
||||
@@ -187,11 +187,7 @@ class ExpressionsConverter(
|
||||
}
|
||||
)
|
||||
}
|
||||
if (destructuringBlock is FirBlock) {
|
||||
for ((index, statement) in destructuringBlock.statements.withIndex()) {
|
||||
statements.add(index, statement)
|
||||
}
|
||||
}
|
||||
statements.addAll(0, destructuringStatements)
|
||||
}.build()
|
||||
}
|
||||
} else {
|
||||
@@ -989,11 +985,7 @@ class ExpressionsConverter(
|
||||
firLoopParameter,
|
||||
tmpVariable = true
|
||||
)
|
||||
if (destructuringBlock is FirBlock) {
|
||||
for ((index, statement) in destructuringBlock.statements.withIndex()) {
|
||||
statements.add(index, statement)
|
||||
}
|
||||
}
|
||||
statements.addAll(0, destructuringBlock.statements)
|
||||
} else {
|
||||
statements.add(0, firLoopParameter)
|
||||
}
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ internal fun generateDestructuringBlock(
|
||||
tmpVariable: Boolean,
|
||||
extractAnnotationsTo: KtAnnotated.(FirAnnotationContainerBuilder) -> Unit,
|
||||
toFirOrImplicitTypeRef: KtTypeReference?.() -> FirTypeRef,
|
||||
): FirExpression {
|
||||
): FirBlock {
|
||||
return buildBlock {
|
||||
source = multiDeclaration.toFirPsiSourceElement()
|
||||
if (tmpVariable) {
|
||||
|
||||
@@ -1069,7 +1069,7 @@ open class RawFirBuilder(
|
||||
symbol = FirAnonymousFunctionSymbol()
|
||||
isLambda = true
|
||||
|
||||
var destructuringBlock: FirExpression? = null
|
||||
val destructuringStatements = mutableListOf<FirStatement>()
|
||||
for (valueParameter in literal.valueParameters) {
|
||||
val multiDeclaration = valueParameter.destructuringDeclaration
|
||||
valueParameters += if (multiDeclaration != null) {
|
||||
@@ -1087,13 +1087,13 @@ open class RawFirBuilder(
|
||||
isNoinline = false
|
||||
isVararg = false
|
||||
}
|
||||
destructuringBlock = generateDestructuringBlock(
|
||||
destructuringStatements += generateDestructuringBlock(
|
||||
baseSession,
|
||||
multiDeclaration,
|
||||
multiParameter,
|
||||
tmpVariable = false,
|
||||
extractAnnotationsTo = { extractAnnotationsTo(it) },
|
||||
) { toFirOrImplicitType() }
|
||||
) { toFirOrImplicitType() }.statements
|
||||
multiParameter
|
||||
} else {
|
||||
val typeRef = valueParameter.typeReference?.convertSafe() ?: buildImplicitTypeRef {
|
||||
@@ -1129,11 +1129,7 @@ open class RawFirBuilder(
|
||||
}
|
||||
)
|
||||
}
|
||||
if (destructuringBlock is FirBlock) {
|
||||
for ((index, statement) in destructuringBlock.statements.withIndex()) {
|
||||
statements.add(index, statement)
|
||||
}
|
||||
}
|
||||
statements.addAll(0, destructuringStatements)
|
||||
}.build()
|
||||
}
|
||||
context.firFunctionTargets.removeLast()
|
||||
@@ -1742,11 +1738,7 @@ open class RawFirBuilder(
|
||||
tmpVariable = true,
|
||||
extractAnnotationsTo = { extractAnnotationsTo(it) },
|
||||
) { toFirOrImplicitType() }
|
||||
if (destructuringBlock is FirBlock) {
|
||||
for ((index, statement) in destructuringBlock.statements.withIndex()) {
|
||||
blockBuilder.statements.add(index, statement)
|
||||
}
|
||||
}
|
||||
blockBuilder.statements.addAll(0, destructuringBlock.statements)
|
||||
} else {
|
||||
blockBuilder.statements.add(0, firLoopParameter)
|
||||
}
|
||||
|
||||
Vendored
+7
-7
@@ -24,24 +24,24 @@ fun bar(aInstance: A, bInstance: B) {
|
||||
|
||||
foo(bInstance) {
|
||||
(a, b): A, (c, d) ->
|
||||
<!UNRESOLVED_REFERENCE!>a<!> checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
|
||||
<!UNRESOLVED_REFERENCE!>b<!> checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
|
||||
a checkType { _<Int>() }
|
||||
b checkType { _<String>() }
|
||||
c checkType { _<Double>() }
|
||||
d checkType { _<Short>() }
|
||||
}
|
||||
|
||||
foo(bInstance) {
|
||||
(a, b), (c, d) ->
|
||||
<!UNRESOLVED_REFERENCE!>a<!> checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
|
||||
<!UNRESOLVED_REFERENCE!>b<!> checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
|
||||
<!COMPONENT_FUNCTION_MISSING, COMPONENT_FUNCTION_MISSING!>(a, b)<!>, (c, d) ->
|
||||
a <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
|
||||
b <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
|
||||
c checkType { _<Double>() }
|
||||
d checkType { _<Short>() }
|
||||
}
|
||||
|
||||
foo<A, B>(bInstance) {
|
||||
(a, b), (c, d) ->
|
||||
<!UNRESOLVED_REFERENCE!>a<!> checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
|
||||
<!UNRESOLVED_REFERENCE!>b<!> checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
|
||||
a checkType { _<Int>() }
|
||||
b checkType { _<String>() }
|
||||
c checkType { _<Double>() }
|
||||
d checkType { _<Short>() }
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -23,7 +23,7 @@ fun bar() {
|
||||
}
|
||||
|
||||
foo { (a, b), (c, b) ->
|
||||
<!UNRESOLVED_REFERENCE!>a<!> checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
|
||||
a checkType { _<Int>() }
|
||||
b checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
|
||||
c checkType { <!INAPPLICABLE_CANDIDATE!>_<!><B>() }
|
||||
}
|
||||
|
||||
+2
-2
@@ -36,8 +36,8 @@ fun bar() {
|
||||
}
|
||||
|
||||
foobar { (a, b), (c, d) ->
|
||||
<!UNRESOLVED_REFERENCE!>a<!> checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
|
||||
<!UNRESOLVED_REFERENCE!>b<!> checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
|
||||
a checkType { _<Int>() }
|
||||
b checkType { _<String>() }
|
||||
c checkType { _<Double>() }
|
||||
d checkType { _<Short>() }
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -32,12 +32,12 @@ fun bar() {
|
||||
}
|
||||
|
||||
foobar { (a, b), (c, d) ->
|
||||
<!UNRESOLVED_REFERENCE!>a<!> checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
|
||||
a checkType { _<Int>() }
|
||||
d checkType { _<Short>() }
|
||||
}
|
||||
|
||||
foobar { (a, b), (c, d) ->
|
||||
<!UNRESOLVED_REFERENCE!>b<!> checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
|
||||
b checkType { _<String>() }
|
||||
c checkType { _<Double>() }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user