Skip to content

Commit

Permalink
Make parameter types for inline classes nullable when underlying type…
Browse files Browse the repository at this point in the history
… is not primitive

Updates default parameter conversion to ensure that Kotlin doesn't generate a non-null check when underlying type is not primitive.

Test: added compiler tests
Fixes: 330655412 ( https://issuetracker.google.com/issues/330655412 )
Change-Id: Ie6bb527824c8542a0f922984f73f4af367ff21ac ( https://android-review.googlesource.com/q/Ie6bb527824c8542a0f922984f73f4af367ff21ac )

Moved from: androidx/androidx@13c32b7
  • Loading branch information
ShikaSD authored and Space Cloud committed Apr 19, 2024
1 parent bac322c commit 53f4f37
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -780,4 +780,27 @@ class ComposeBytecodeCodegenTest(useFir: Boolean) : AbstractCodegenTest(useFir)
}
"""
)

@Test
fun composeValueClassDefaultParameter() =
validateBytecode(
"""
import androidx.compose.runtime.*
@JvmInline
value class Data(val string: String)
@JvmInline
value class IntData(val value: Int)
@Composable fun Example(data: Data = Data(""), intData: IntData = IntData(0)) {}
""",
validate = {
// select Example function body
val match = Regex("public final static Example[\\s\\S]*?LOCALVARIABLE").find(it)!!
assertFalse(message = "Function body should not contain a not-null check.") {
match.value.contains("Intrinsics.checkNotNullParameter")
}
},
dumpClasses = true
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -575,4 +575,20 @@ class ComposerParamTransformTests(useFir: Boolean) : AbstractIrTransformTest(use
}
"""
)

@Test
fun composeValueClassDefaultParameter() =
verifyGoldenComposeIrTransform(
extra = """
@JvmInline
value class Data(val string: String)
@JvmInline
value class IntData(val value: Int)
""",
source = """
import androidx.compose.runtime.*
@Composable fun Example(data: Data = Data(""), intData: IntData = IntData(0)) {}
"""
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// Source
// ------------------------------------------

import androidx.compose.runtime.*

@Composable fun Example(data: Data = Data(""), intData: IntData = IntData(0)) {}

//
// Transformed IR
// ------------------------------------------

@Composable
fun Example(data: Data?, intData: IntData, %composer: Composer?, %changed: Int, %default: Int) {
%composer = %composer.startRestartGroup(<>)
sourceInformation(%composer, "C(Example)P(0:Data,1:IntData):Test.kt")
if (%changed and 0b0001 != 0 || !%composer.skipping) {
if (%default and 0b0001 != 0) {
data = Data("")
}
if (%default and 0b0010 != 0) {
intData = IntData(0)
}
if (isTraceInProgress()) {
traceEventStart(<>, %changed, -1, <>)
}
if (isTraceInProgress()) {
traceEventEnd()
}
} else {
%composer.skipToGroupEnd()
}
%composer.endRestartGroup()?.updateScope { %composer: Composer?, %force: Int ->
Example(data, intData, %composer, updateChangedFlags(%changed or 0b0001), %default)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// Source
// ------------------------------------------

import androidx.compose.runtime.*

@Composable fun Example(data: Data = Data(""), intData: IntData = IntData(0)) {}

//
// Transformed IR
// ------------------------------------------

@Composable
fun Example(data: Data?, intData: IntData, %composer: Composer?, %changed: Int, %default: Int) {
%composer = %composer.startRestartGroup(<>)
sourceInformation(%composer, "C(Example)P(0:Data,1:IntData):Test.kt")
if (%changed and 0b0001 != 0 || !%composer.skipping) {
if (%default and 0b0001 != 0) {
data = Data("")
}
if (%default and 0b0010 != 0) {
intData = IntData(0)
}
if (isTraceInProgress()) {
traceEventStart(<>, %changed, -1, <>)
}
if (isTraceInProgress()) {
traceEventEnd()
}
} else {
%composer.skipToGroupEnd()
}
%composer.endRestartGroup()?.updateScope { %composer: Composer?, %force: Int ->
Example(data, intData, %composer, updateChangedFlags(%changed or 0b0001), %default)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ class CompositionTests {
Text("1")
}
}

@Test
fun composeValueClassDefaultParameter() = compositionTest {
compose {
DefaultValueClass()
}
}
}

class CrossInlineState(content: @Composable () -> Unit = { }) {
Expand All @@ -86,3 +93,13 @@ class CrossInlineState(content: @Composable () -> Unit = { }) {
@Composable
fun place() { content() }
}

@JvmInline
value class Data(val string: String)

@Composable
fun DefaultValueClass(
data: Data = Data("Hello")
) {
println(data)
}
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,11 @@ class ComposerParamTransformer(
return when {
type.isPrimitiveType() -> type
type.isInlineClassType() -> if (context.platform.isJvm() || constructorAccessible) {
type
if (type.unboxInlineClass().isPrimitiveType()) {
type
} else {
type.makeNullable()
}
} else {
// k/js and k/native: private constructors of value classes can be not accessible.
// Therefore it won't be possible to create a "fake" default argument for calls.
Expand Down

0 comments on commit 53f4f37

Please sign in to comment.