Skip to content

Commit ca9fb23

Browse files
ShikaSDSpace Cloud
authored and
Space Cloud
committed
Disallow open @composable functions with default params
Old version of Compose compiler allowed open functions with default params without a proper wrapper around it. We need to add some feature detection for precompiled artifacts to make sure we handle those functions correctly before enabling it. Fixes: 357878245 Relnote: Disallow open @composable functions with default params to fix binary compatibility issues.
1 parent 9a4c77e commit ca9fb23

18 files changed

+1179
-47
lines changed

plugins/compose/compiler-hosted/integration-tests/src/jvmTest/kotlin/androidx/compose/compiler/plugins/kotlin/ComposeBytecodeCodegenTest.kt

+30-4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package androidx.compose.compiler.plugins.kotlin
1818

1919
import org.junit.Assume.assumeFalse
2020
import org.junit.Test
21+
import kotlin.test.Ignore
2122
import kotlin.test.assertFalse
2223
import kotlin.test.assertTrue
2324

@@ -623,25 +624,50 @@ class ComposeBytecodeCodegenTest(useFir: Boolean) : AbstractCodegenTest(useFir)
623624
)
624625

625626
@Test
626-
fun testDefaultParametersInVirtualFunctions() = validateBytecode(
627+
fun testDefaultParametersInAbstractFunctions() = validateBytecode(
627628
"""
628629
import androidx.compose.runtime.*
629630
630631
interface Test {
631632
@Composable fun foo(param: Int = remember { 0 })
632-
@Composable fun bar(param: Int = remember { 0 }): Int = param
633633
}
634634
635635
class TestImpl : Test {
636636
@Composable override fun foo(param: Int) {}
637+
}
638+
639+
@Composable fun CallWithDefaults(test: Test) {
640+
test.foo()
641+
test.foo(0)
642+
}
643+
""",
644+
validate = {
645+
assertTrue(
646+
it.contains(
647+
"INVOKESTATIC test/Test%ComposeDefaultImpls.foo%default (ILtest/Test;Landroidx/compose/runtime/Composer;II)V"
648+
),
649+
"default static functions should be generated in ComposeDefaultsImpl class"
650+
)
651+
}
652+
)
653+
654+
@Ignore("b/357878245")
655+
@Test
656+
fun testDefaultParametersInOpenFunctions() = validateBytecode(
657+
"""
658+
import androidx.compose.runtime.*
659+
660+
interface Test {
661+
@Composable fun bar(param: Int = remember { 0 }): Int = param
662+
}
663+
664+
class TestImpl : Test {
637665
@Composable override fun bar(param: Int): Int {
638666
return super.bar(param)
639667
}
640668
}
641669
642670
@Composable fun CallWithDefaults(test: Test) {
643-
test.foo()
644-
test.foo(0)
645671
test.bar()
646672
test.bar(0)
647673
}

plugins/compose/compiler-hosted/integration-tests/src/jvmTest/kotlin/androidx/compose/compiler/plugins/kotlin/ComposeCrossModuleTests.kt

+3-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import org.junit.Test
2525
import org.junit.rules.TemporaryFolder
2626
import org.junit.runner.RunWith
2727
import org.junit.runners.Parameterized
28+
import kotlin.test.Ignore
2829

2930
@RunWith(Parameterized::class)
3031
class ComposeCrossModuleTests(useFir: Boolean) : AbstractCodegenTest(useFir) {
@@ -1224,8 +1225,9 @@ class ComposeCrossModuleTests(useFir: Boolean) : AbstractCodegenTest(useFir) {
12241225
)
12251226
}
12261227

1228+
@Ignore("b/357878245")
12271229
@Test
1228-
fun defaultParametersInFakeOverrideVirtualComposableFunctions() {
1230+
fun defaultParametersInFakeOverrideOpenComposableFunctions() {
12291231
compile(
12301232
mapOf(
12311233
"Base" to mapOf(

plugins/compose/compiler-hosted/integration-tests/src/jvmTest/kotlin/androidx/compose/compiler/plugins/kotlin/DefaultParamTransformTests.kt

+78-16
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package androidx.compose.compiler.plugins.kotlin
1818

1919
import org.intellij.lang.annotations.Language
20+
import org.junit.Ignore
2021
import org.junit.Test
2122

2223
class DefaultParamTransformTests(useFir: Boolean) : AbstractIrTransformTest(useFir) {
@@ -405,16 +406,49 @@ class DefaultParamTransformTests(useFir: Boolean) : AbstractIrTransformTest(useF
405406
)
406407

407408
@Test
408-
fun testDefaultParamOnInterface() = defaultParams(
409+
fun testAbstractDefaultParamOnInterface() = defaultParams(
409410
unchecked = """""",
410411
checked = """
411412
interface Test {
412413
@Composable fun foo(param: Int = remember { 0 })
413-
@Composable fun bar(param: Int = remember { 0 }): Int = param
414414
}
415415
416416
interface TestBetween : Test {
417417
@Composable fun betweenFoo(param: Int = remember { 0 })
418+
}
419+
420+
class TestImpl : TestBetween {
421+
@Composable override fun foo(param: Int) {}
422+
@Composable override fun betweenFoo(param: Int) {}
423+
}
424+
425+
@Composable fun CallWithDefaults(test: Test, testBetween: TestBetween, testImpl: TestImpl) {
426+
test.foo()
427+
test.foo(0)
428+
429+
testBetween.foo()
430+
testBetween.foo(0)
431+
testBetween.betweenFoo()
432+
testBetween.betweenFoo(0)
433+
434+
testImpl.foo()
435+
testImpl.foo(0)
436+
testImpl.betweenFoo()
437+
testImpl.betweenFoo(0)
438+
}
439+
"""
440+
)
441+
442+
@Ignore("b/357878245")
443+
@Test
444+
fun testOpenDefaultParamOnInterface() = defaultParams(
445+
unchecked = """""",
446+
checked = """
447+
interface Test {
448+
@Composable fun bar(param: Int = remember { 0 }): Int = param
449+
}
450+
451+
interface TestBetween : Test {
418452
@Composable fun betweenFooDefault(param: Int = remember { 0 }) {}
419453
@Composable fun betweenBar(param: Int = remember { 0 }): Int = param
420454
}
@@ -428,28 +462,18 @@ class DefaultParamTransformTests(useFir: Boolean) : AbstractIrTransformTest(useF
428462
}
429463
430464
@Composable fun CallWithDefaults(test: Test, testBetween: TestBetween, testImpl: TestImpl) {
431-
test.foo()
432-
test.foo(0)
433465
test.bar()
434466
test.bar(0)
435467
436-
testBetween.foo()
437-
testBetween.foo(0)
438468
testBetween.bar()
439469
testBetween.bar(0)
440-
testBetween.betweenFoo()
441-
testBetween.betweenFoo(0)
442470
testBetween.betweenFooDefault()
443471
testBetween.betweenFooDefault(0)
444472
testBetween.betweenBar()
445473
testBetween.betweenBar(0)
446474
447-
testImpl.foo()
448-
testImpl.foo(0)
449475
testImpl.bar()
450476
testImpl.bar(0)
451-
testImpl.betweenFoo()
452-
testImpl.betweenFoo(0)
453477
testImpl.betweenFooDefault()
454478
testImpl.betweenFooDefault(0)
455479
testImpl.betweenBar()
@@ -458,6 +482,7 @@ class DefaultParamTransformTests(useFir: Boolean) : AbstractIrTransformTest(useF
458482
"""
459483
)
460484

485+
@Ignore("b/357878245")
461486
@Test
462487
fun testDefaultParamOverrideOpenFunction() = defaultParams(
463488
unchecked = """""",
@@ -484,30 +509,49 @@ class DefaultParamTransformTests(useFir: Boolean) : AbstractIrTransformTest(useF
484509
)
485510

486511
@Test
487-
fun testDefaultParamOverrideExtensionReceiver() = defaultParams(
512+
fun testAbstractDefaultParamOverrideExtensionReceiver() = defaultParams(
488513
unchecked = "",
489514
checked = """
490515
interface Test {
491516
@Composable fun Int.foo(param: Int = remember { 0 })
492-
@Composable fun Int.bar(param: Int = remember { 0 }): Int = param
493517
}
494518
495519
class TestImpl : Test {
496520
@Composable override fun Int.foo(param: Int) {}
497-
@Composable override fun Int.bar(param: Int): Int = 0
498521
}
499522
500523
@Composable fun CallWithDefaults(test: Test) {
501524
with(test) {
502525
42.foo()
503526
42.foo(0)
527+
}
528+
}
529+
"""
530+
)
531+
532+
@Ignore("b/357878245")
533+
@Test
534+
fun testOpenDefaultParamOverrideExtensionReceiver() = defaultParams(
535+
unchecked = "",
536+
checked = """
537+
interface Test {
538+
@Composable fun Int.bar(param: Int = remember { 0 }): Int = param
539+
}
540+
541+
class TestImpl : Test {
542+
@Composable override fun Int.bar(param: Int): Int = 0
543+
}
544+
545+
@Composable fun CallWithDefaults(test: Test) {
546+
with(test) {
504547
42.bar()
505548
42.bar(0)
506549
}
507550
}
508551
"""
509552
)
510553

554+
@Ignore("b/357878245")
511555
@Test
512556
fun testDefaultParamFakeOverride() = defaultParams(
513557
unchecked = "",
@@ -531,12 +575,30 @@ class DefaultParamTransformTests(useFir: Boolean) : AbstractIrTransformTest(useF
531575
)
532576

533577
@Test
534-
fun testDefaultParamComposableLambda() = defaultParams(
578+
fun testAbstractDefaultParamComposableLambda() = defaultParams(
535579
unchecked = """
536580
@Composable fun Text(value: String) {}
537581
""",
538582
checked = """
539583
private interface DefaultParamInterface {
584+
@Composable fun Content(
585+
content: @Composable () -> Unit = @Composable { ComposedContent { Text("default") } }
586+
)
587+
@Composable fun ComposedContent(
588+
content: @Composable () -> Unit = @Composable { Text("default") }
589+
)
590+
}
591+
""",
592+
)
593+
594+
@Ignore("b/357878245")
595+
@Test
596+
fun testOpenDefaultParamComposableLambda() = defaultParams(
597+
unchecked = """
598+
@Composable fun Text(value: String) {}
599+
""",
600+
checked = """
601+
private interface DefaultParamInterface {
540602
@Composable fun Content(
541603
content: @Composable () -> Unit = @Composable { ComposedContent { Text("default") } }
542604
)

plugins/compose/compiler-hosted/integration-tests/src/jvmTest/kotlin/androidx/compose/compiler/plugins/kotlin/analysis/ComposableDeclarationCheckerTests.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ class ComposableDeclarationCheckerTests(useFir: Boolean) : AbstractComposeDiagno
290290
"""
291291
import androidx.compose.runtime.Composable
292292
interface A {
293-
@Composable fun foo(x: Int = 0) {}
293+
@Composable fun foo(x: Int = <!ABSTRACT_COMPOSABLE_DEFAULT_PARAMETER_VALUE!>0<!>) {}
294294
}
295295
"""
296296
)
@@ -314,7 +314,7 @@ class ComposableDeclarationCheckerTests(useFir: Boolean) : AbstractComposeDiagno
314314
"""
315315
import androidx.compose.runtime.Composable
316316
open class A {
317-
@Composable open fun foo(x: Int = 0) {}
317+
@Composable open fun foo(x: Int = <!ABSTRACT_COMPOSABLE_DEFAULT_PARAMETER_VALUE!>0<!>) {}
318318
}
319319
"""
320320
)

0 commit comments

Comments
 (0)