Fix logic for identifying legacy functions with default parameters.
It was not checking for presence of default parameters on declaration side.
Fixes: CMP-8741
Test: Compiler tests
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ComposeIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ComposeIT.kt
index aac1347..3ba03c3 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ComposeIT.kt
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ComposeIT.kt
@@ -443,6 +443,14 @@
| return value
| }
|}
+ |
+ |interface TestInterface {
+ | @Composable fun Content()
+ |}
+ |
+ |class OtherModuleImpl : TestInterface {
+ | @Composable override fun Content() {}
+ |}
""".trimMargin()
)
build("publishToMavenLocal") {
@@ -485,11 +493,13 @@
| @Test
| fun test() = compositionTest {
| val testImpl = TestImpl()
+ | val otherModuleImpl = OtherModuleImpl()
| compose {
| testImpl.UnitFun(1)
| testImpl.UnitFun()
| Text("${'$'}{testImpl.openFun(1)}")
| Text("${'$'}{testImpl.openFun()}")
+ | otherModuleImpl.Content() // Just executing this successfully is enough
| }
|
| validate {
diff --git a/plugins/compose/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposerParamTransformer.kt b/plugins/compose/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposerParamTransformer.kt
index 69112ba..fde1274 100644
--- a/plugins/compose/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposerParamTransformer.kt
+++ b/plugins/compose/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposerParamTransformer.kt
@@ -579,6 +579,7 @@
private fun IrSimpleFunction.isLegacyOpenFunctionWithDefault(): Boolean =
modality == Modality.OPEN && (
origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB &&
+ parameters.any { it.hasDefaultValue() } &&
composeMetadata?.supportsOpenFunctionsWithDefaultParams() != true
) || overriddenSymbols.any { it.owner.isLegacyOpenFunctionWithDefault() }
diff --git a/plugins/compose/compiler-hosted/testData/codegen/testOverrideLambda.ir.txt b/plugins/compose/compiler-hosted/testData/codegen/testOverrideLambda.ir.txt
new file mode 100644
index 0000000..ed1902a
--- /dev/null
+++ b/plugins/compose/compiler-hosted/testData/codegen/testOverrideLambda.ir.txt
@@ -0,0 +1,98 @@
+MODULE_FRAGMENT
+ FILE fqName:<root> fileName:module_main_testOverrideLambda.kt
+ FUN name:Content visibility:public modality:FINAL returnType:kotlin.Unit
+ VALUE_PARAMETER kind:Regular name:$composer index:0 type:androidx.compose.runtime.Composer? [assignable]
+ VALUE_PARAMETER kind:Regular name:$changed index:1 type:kotlin.Int
+ annotations:
+ Composable
+ FunctionKeyMeta(key = -519357155, startOffset = 94, endOffset = 130)
+ BLOCK_BODY
+ BLOCK type=kotlin.Unit origin=null
+ SET_VAR '$composer: androidx.compose.runtime.Composer? [assignable] declared in <root>.Content' type=kotlin.Unit origin=null
+ CALL 'public abstract fun startRestartGroup (key: kotlin.Int): androidx.compose.runtime.Composer declared in androidx.compose.runtime.Composer' type=androidx.compose.runtime.Composer origin=null
+ ARG <this>: GET_VAR '$composer: androidx.compose.runtime.Composer? [assignable] declared in <root>.Content' type=androidx.compose.runtime.Composer? origin=null
+ ARG key: CONST Int type=kotlin.Int value=-519357155
+ CALL 'public final fun sourceInformation (composer: androidx.compose.runtime.Composer, sourceInformation: kotlin.String): kotlin.Unit declared in androidx.compose.runtime' type=kotlin.Unit origin=null
+ ARG composer: GET_VAR '$composer: androidx.compose.runtime.Composer? [assignable] declared in <root>.Content' type=androidx.compose.runtime.Composer? origin=null
+ ARG sourceInformation: CONST String type=kotlin.String value="C(Content)22@126L2,22@121L7:module_main_testOverrideLambda.kt"
+ WHEN type=kotlin.Unit origin=IF
+ BRANCH
+ if: CALL 'public abstract fun shouldExecute (parametersChanged: kotlin.Boolean, flags: kotlin.Int): kotlin.Boolean declared in androidx.compose.runtime.Composer' type=kotlin.Boolean origin=null
+ ARG <this>: GET_VAR '$composer: androidx.compose.runtime.Composer? [assignable] declared in <root>.Content' type=androidx.compose.runtime.Composer? origin=null
+ ARG parametersChanged: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=null
+ ARG <this>: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=null
+ ARG arg0: GET_VAR '$changed: kotlin.Int declared in <root>.Content' type=kotlin.Int origin=null
+ ARG arg1: CONST Int type=kotlin.Int value=0
+ ARG flags: CALL 'public final fun and (other: kotlin.Int): kotlin.Int [infix] declared in kotlin.Int' type=kotlin.Int origin=null
+ ARG <this>: GET_VAR '$changed: kotlin.Int declared in <root>.Content' type=kotlin.Int origin=null
+ ARG other: CONST Int type=kotlin.Int value=1
+ then: BLOCK type=kotlin.Unit origin=null
+ WHEN type=kotlin.Unit origin=IF
+ BRANCH
+ if: CALL 'public final fun isTraceInProgress (): kotlin.Boolean declared in androidx.compose.runtime' type=kotlin.Boolean origin=null
+ then: CALL 'public final fun traceEventStart (key: kotlin.Int, dirty1: kotlin.Int, dirty2: kotlin.Int, info: kotlin.String): kotlin.Unit declared in androidx.compose.runtime' type=kotlin.Unit origin=null
+ ARG key: CONST Int type=kotlin.Int value=-519357155
+ ARG dirty1: GET_VAR '$changed: kotlin.Int declared in <root>.Content' type=kotlin.Int origin=null
+ ARG dirty2: CONST Int type=kotlin.Int value=-1
+ ARG info: CONST String type=kotlin.String value="Content (module_main_testOverrideLambda.kt:21)"
+ CALL 'public open fun test (lambda: kotlin.Function0<kotlin.Unit>, $composer: androidx.compose.runtime.Composer?, $changed: kotlin.Int): kotlin.Unit declared in <root>.Test' type=kotlin.Unit origin=null
+ ARG <this>: CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in <root>.Test' type=<root>.Test origin=null
+ ARG lambda: BLOCK type=kotlin.Function0<kotlin.Unit> origin=null
+ CALL 'public final fun sourceInformationMarkerStart (composer: androidx.compose.runtime.Composer, key: kotlin.Int, sourceInformation: kotlin.String): kotlin.Unit declared in androidx.compose.runtime' type=kotlin.Unit origin=null
+ ARG composer: GET_VAR '$composer: androidx.compose.runtime.Composer? [assignable] declared in <root>.Content' type=androidx.compose.runtime.Composer? origin=null
+ ARG key: CONST Int type=kotlin.Int value=-886018593
+ ARG sourceInformation: CONST String type=kotlin.String value="CC(remember):module_main_testOverrideLambda.kt#9igjgp"
+ VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Function0<kotlin.Unit> [val]
+ CALL 'public final fun cache <T> (<this>: androidx.compose.runtime.Composer, invalid: kotlin.Boolean, block: @[DisallowComposableCalls] kotlin.Function0<T of androidx.compose.runtime.cache>): T of androidx.compose.runtime.cache [inline] declared in androidx.compose.runtime' type=kotlin.Function0<kotlin.Unit> origin=null
+ TYPE_ARG T: kotlin.Function0<kotlin.Unit>
+ ARG <this>: GET_VAR '$composer: androidx.compose.runtime.Composer? [assignable] declared in <root>.Content' type=androidx.compose.runtime.Composer? origin=null
+ ARG invalid: CONST Boolean type=kotlin.Boolean value=false
+ ARG block: FUN_EXPR type=kotlin.Function0<kotlin.Function0<kotlin.Unit>> origin=LAMBDA
+ FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL returnType:kotlin.Function0<kotlin.Unit>
+ BLOCK_BODY
+ RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.Function0<kotlin.Unit> declared in <root>.Content'
+ FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
+ FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL returnType:kotlin.Unit
+ BLOCK_BODY
+ RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.Unit declared in <root>.Content.<anonymous>'
+ GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
+ CALL 'public final fun sourceInformationMarkerEnd (composer: androidx.compose.runtime.Composer): kotlin.Unit declared in androidx.compose.runtime' type=kotlin.Unit origin=null
+ ARG composer: GET_VAR '$composer: androidx.compose.runtime.Composer? [assignable] declared in <root>.Content' type=androidx.compose.runtime.Composer? origin=null
+ GET_VAR 'val tmp_0: kotlin.Function0<kotlin.Unit> [val] declared in <root>.Content' type=kotlin.Function0<kotlin.Unit> origin=null
+ ARG $composer: GET_VAR '$composer: androidx.compose.runtime.Composer? [assignable] declared in <root>.Content' type=androidx.compose.runtime.Composer? origin=null
+ ARG $changed: CONST Int type=kotlin.Int value=6
+ WHEN type=kotlin.Unit origin=IF
+ BRANCH
+ if: CALL 'public final fun isTraceInProgress (): kotlin.Boolean declared in androidx.compose.runtime' type=kotlin.Boolean origin=null
+ then: CALL 'public final fun traceEventEnd (): kotlin.Unit declared in androidx.compose.runtime' type=kotlin.Unit origin=null
+ BRANCH
+ if: CONST Boolean type=kotlin.Boolean value=true
+ then: CALL 'public abstract fun skipToGroupEnd (): kotlin.Unit declared in androidx.compose.runtime.Composer' type=kotlin.Unit origin=null
+ ARG <this>: GET_VAR '$composer: androidx.compose.runtime.Composer? [assignable] declared in <root>.Content' type=androidx.compose.runtime.Composer? origin=null
+ BLOCK type=kotlin.Unit origin=null
+ BLOCK type=kotlin.Unit origin=SAFE_CALL
+ VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:androidx.compose.runtime.ScopeUpdateScope? [val]
+ CALL 'public abstract fun endRestartGroup (): androidx.compose.runtime.ScopeUpdateScope? declared in androidx.compose.runtime.Composer' type=androidx.compose.runtime.ScopeUpdateScope? origin=null
+ ARG <this>: GET_VAR '$composer: androidx.compose.runtime.Composer? [assignable] declared in <root>.Content' type=androidx.compose.runtime.Composer? origin=null
+ WHEN type=kotlin.Unit origin=IF
+ BRANCH
+ if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=null
+ ARG arg0: GET_VAR 'val tmp_1: androidx.compose.runtime.ScopeUpdateScope? [val] declared in <root>.Content' type=androidx.compose.runtime.ScopeUpdateScope? origin=null
+ ARG arg1: CONST Null type=kotlin.Any? value=null
+ then: CONST Null type=kotlin.Any? value=null
+ BRANCH
+ if: CONST Boolean type=kotlin.Boolean value=true
+ then: CALL 'public abstract fun updateScope (block: kotlin.Function2<androidx.compose.runtime.Composer, kotlin.Int, kotlin.Unit>): kotlin.Unit declared in androidx.compose.runtime.ScopeUpdateScope' type=kotlin.Unit origin=null
+ ARG <this>: GET_VAR 'val tmp_1: androidx.compose.runtime.ScopeUpdateScope? [val] declared in <root>.Content' type=androidx.compose.runtime.ScopeUpdateScope? origin=null
+ ARG block: FUN_EXPR type=kotlin.Function2<androidx.compose.runtime.Composer?, kotlin.Int, kotlin.Unit> origin=LAMBDA
+ FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL returnType:kotlin.Unit
+ VALUE_PARAMETER kind:Regular name:$composer index:0 type:androidx.compose.runtime.Composer?
+ VALUE_PARAMETER kind:Regular name:$force index:1 type:kotlin.Int
+ BLOCK_BODY
+ RETURN type=kotlin.Nothing from='local final fun <anonymous> ($composer: androidx.compose.runtime.Composer?, $force: kotlin.Int): kotlin.Unit declared in <root>.Content'
+ CALL 'public final fun Content ($composer: androidx.compose.runtime.Composer?, $changed: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
+ ARG $composer: GET_VAR '$composer: androidx.compose.runtime.Composer? declared in <root>.Content.<anonymous>' type=androidx.compose.runtime.Composer? origin=null
+ ARG $changed: CALL 'internal final fun updateChangedFlags (flags: kotlin.Int): kotlin.Int declared in androidx.compose.runtime' type=kotlin.Int origin=null
+ ARG flags: CALL 'public final fun or (other: kotlin.Int): kotlin.Int [infix] declared in kotlin.Int' type=kotlin.Int origin=null
+ ARG <this>: GET_VAR '$changed: kotlin.Int declared in <root>.Content' type=kotlin.Int origin=null
+ ARG other: CONST Int type=kotlin.Int value=1
diff --git a/plugins/compose/compiler-hosted/testData/codegen/testOverrideLambda.kt b/plugins/compose/compiler-hosted/testData/codegen/testOverrideLambda.kt
new file mode 100644
index 0000000..046beef
--- /dev/null
+++ b/plugins/compose/compiler-hosted/testData/codegen/testOverrideLambda.kt
@@ -0,0 +1,24 @@
+// DUMP_IR
+
+// MODULE: lib
+import androidx.compose.runtime.Composable
+
+interface ITest {
+ @Composable
+ fun test(lambda: () -> Unit)
+}
+
+class Test : ITest {
+ @Composable
+ override fun test(lambda: () -> Unit) {
+ println("in test")
+ }
+}
+
+// MODULE: main(lib)
+import androidx.compose.runtime.Composable
+
+@Composable
+fun Content() {
+ Test().test {}
+}
\ No newline at end of file
diff --git a/plugins/compose/compiler-hosted/testData/codegen/testOverrideLambda.txt b/plugins/compose/compiler-hosted/testData/codegen/testOverrideLambda.txt
new file mode 100644
index 0000000..8086a35
--- /dev/null
+++ b/plugins/compose/compiler-hosted/testData/codegen/testOverrideLambda.txt
@@ -0,0 +1,6 @@
+public final class Module_main_testOverrideLambdaKt {
+ // source: 'module_main_testOverrideLambda.kt'
+ private final static method Content$lambda$0$0(): kotlin.Unit
+ private final static method Content$lambda$1(p0: int, p1: androidx.compose.runtime.Composer, p2: int): kotlin.Unit
+ public final static method Content(p0: androidx.compose.runtime.Composer, p1: int): void
+}
\ No newline at end of file
diff --git a/plugins/compose/compiler-hosted/tests-gen/androidx/compose/compiler/plugins/kotlin/CompilerFacilityTestForComposeCompilerPluginGenerated.java b/plugins/compose/compiler-hosted/tests-gen/androidx/compose/compiler/plugins/kotlin/CompilerFacilityTestForComposeCompilerPluginGenerated.java
index f92a991..72e60ff 100644
--- a/plugins/compose/compiler-hosted/tests-gen/androidx/compose/compiler/plugins/kotlin/CompilerFacilityTestForComposeCompilerPluginGenerated.java
+++ b/plugins/compose/compiler-hosted/tests-gen/androidx/compose/compiler/plugins/kotlin/CompilerFacilityTestForComposeCompilerPluginGenerated.java
@@ -186,6 +186,12 @@
}
@Test
+ @TestMetadata("testOverrideLambda.kt")
+ public void testTestOverrideLambda() {
+ runTest("plugins/compose/compiler-hosted/testData/codegen/testOverrideLambda.kt");
+ }
+
+ @Test
@TestMetadata("valueArgumentForLibraryConstructor.kt")
public void testValueArgumentForLibraryConstructor() {
runTest("plugins/compose/compiler-hosted/testData/codegen/valueArgumentForLibraryConstructor.kt");