Berkeli Alashov
05/27/2022, 4:35 AM@Composable operator fun invoke with interfaces - default arguments doesn't work. Is this a bug? Example in threadBerkeli Alashov
05/27/2022, 4:35 AMinterface A {
object B : A
operator fun invoke(truth: Boolean = true, data: String = "Data") {
assert(truth)
assert(data == "Data")
}
}
interface C {
object D : C
@Composable
operator fun invoke(truth: Boolean = true, data: String = "Data") {
assert(truth)
assert(data == "Data")
}
}
@Preview
@Composable
fun Test() {
// doesn't crash
A.B.invoke()
// doesn't crash
A.B()
// doesn't crash
C.D.invoke()
// crashes with assertion error
C.D()
}Zach Klippenstein (he/him) [MOD]
05/27/2022, 4:38 AMBerkeli Alashov
05/27/2022, 4:39 AMtruth is false, data is nullZach Klippenstein (he/him) [MOD]
05/27/2022, 4:43 AMBerkeli Alashov
05/27/2022, 4:44 AMZach Klippenstein (he/him) [MOD]
05/27/2022, 4:45 AMBerkeli Alashov
05/27/2022, 4:46 AM@ComposableZach Klippenstein (he/him) [MOD]
05/27/2022, 4:46 AMZach Klippenstein (he/him) [MOD]
05/27/2022, 4:47 AMZoltan Demant
05/27/2022, 5:10 AMBerkeli Alashov
05/27/2022, 5:12 AMLINENUMBER 382 L0
GETSTATIC app/A$B.INSTANCE : Lapp/A$B;
CHECKCAST app/A
ICONST_0
ACONST_NULL
ICONST_3
ACONST_NULL
INVOKESTATIC app/A$DefaultImpls.invoke$default (Lapp/A;ZLjava/lang/String;ILjava/lang/Object;)V
L1
LINENUMBER 384 L1
GETSTATIC app/A$B.INSTANCE : Lapp/A$B;
CHECKCAST app/A
ICONST_0
ACONST_NULL
ICONST_3
ACONST_NULL
INVOKESTATIC app/A$DefaultImpls.invoke$default (Lapp/A;ZLjava/lang/String;ILjava/lang/Object;)V
L2
LINENUMBER 387 L2
GETSTATIC app/C$D.INSTANCE : Lapp/C$D;
CHECKCAST app/C
ICONST_0
ACONST_NULL
ICONST_3
ACONST_NULL
INVOKESTATIC app/C$DefaultImpls.invoke$default (Lapp/C;ZLjava/lang/String;ILjava/lang/Object;)V
L3
LINENUMBER 389 L3
GETSTATIC app/C$D.INSTANCE : Lapp/C$D;
CHECKCAST app/C
ICONST_0
ACONST_NULL
ICONST_3
ACONST_NULL
INVOKESTATIC app/C$DefaultImpls.invoke$default (Lapp/C;ZLjava/lang/String;ILjava/lang/Object;)V
L4
Body of TestZach Klippenstein (he/him) [MOD]
05/27/2022, 5:16 AMBerkeli Alashov
05/27/2022, 5:23 AMBerkeli Alashov
05/27/2022, 5:26 AMste
05/27/2022, 8:17 AMLeland Richardson [G]
05/27/2022, 3:46 PMBerkeli Alashov
05/27/2022, 6:39 PMfun invoke to fun C.invoke and adding more arguments that are @Composable lambdas also seems to work somehow..
While only adding @Composable lambdas result in runtime error (non-nullable param is null)Leland Richardson [G]
05/27/2022, 7:12 PMC.invoke(…) the compiler looks at it like a normal function call. The C() pathway is an “operator call” and the code in the compose compiler was incorrectly assuming that in the latter pathway it would never have any default paramsBerkeli Alashov
05/27/2022, 8:34 PMC. to @Composable operator fun invoke to make it @Composable operator fun C.invoke , and call it like C.D() (which seems to be still an "operator call"?), it feels like it shouldn't be different calls?Leland Richardson [G]
05/27/2022, 8:45 PMBen Trengrove [G]
05/27/2022, 11:42 PMBerkeli Alashov
05/28/2022, 12:44 AMsealed interface A {
object B : A
sealed interface E : A {
object F : E
}
@Composable
operator fun invoke(truth: Boolean = true, data: String = "Data") {
assert(truth)
assert(data == "Data")
}
}
@Preview
@Composable
fun Test() {
// doesn't crash
A.B.invoke()
// crashes with: checkNotNullParameter, parameter data
A.E.F.invoke()
A.E.F()
// Crashes with already fixed assertion error (wrong defaults)
A.B()
}Berkeli Alashov
05/28/2022, 1:58 AMminSize: Dp = Defaults.minSize() field to invoke with totally different stacktrace:
java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object kotlin.jvm.functions.Function3.invoke(java.lang.Object, java.lang.Object, java.lang.Object)' on a null object reference
Class structure is same as above but invoke has a receiver : @Composable operator invoke A.invokeBen Trengrove [G]
05/31/2022, 12:34 AMBen Trengrove [G]
05/31/2022, 12:34 AMBerkeli Alashov
05/31/2022, 12:37 AMBerkeli Alashov
07/02/2022, 1:17 AMLeland Richardson [G]
07/02/2022, 2:22 AMBerkeli Alashov
07/02/2022, 2:50 AMsealed interface Button {
object Primary : Button
object Secondary : Button
sealed interface Outlined : Button {
object Primary : Outlined
object Secondary : Outlined
}
@Composable
operator fun invoke(
onClick: () -> Unit,
text: String,
modifier: Modifier = Modifier,
) {
androidx.compose.material3.Button(
onClick = onClick,
modifier = modifier,
) {
Text(text = text)
}
}
}
@Composable
@Preview
fun ButtonsPreview() {
Column {
// doesn't crash
Button.Primary(text = "Primary", onClick = {})
Button.Secondary(text = "Secondary", onClick = {})
// crashes
Button.Outlined.Primary(text = "Outlined Primary", onClick = {})
Button.Outlined.Secondary(text = "Outlined Secondary", onClick = {})
}
}Berkeli Alashov
07/02/2022, 2:52 AMinterface Outlined : Button, but not object Primary: ButtonBen Trengrove [G]
07/03/2022, 10:18 PMBerkeli Alashov
07/03/2022, 10:19 PMBen Trengrove [G]
07/03/2022, 10:40 PMLeland Richardson [G]
07/03/2022, 10:41 PMBen Trengrove [G]
07/03/2022, 10:42 PMBerkeli Alashov
07/03/2022, 10:44 PMBerkeli Alashov
07/03/2022, 10:46 PMinterface too and doesn't with object, abstract/sealed classBen Trengrove [G]
07/03/2022, 11:02 PMBen Trengrove [G]
07/03/2022, 11:02 PMLeland Richardson [G]
07/03/2022, 11:14 PM