Method Resolution failing across modules when @Composable fun has a @Composable lambda and called within launchMolecule
- Dominant language
- Kotlin
- Stars
- 2.2k
- Forks
- 116
- Avg merge
- 1h 36m
- Merged PRs (30d)
- 8
Description
Reproducing project is here: https://github.com/steve-the-edwards/reproductions/tree/main/overridetest
```
abstract class AndroidLibAbstractClass {
@Composable
abstract fun AComposableWithLambda(
input1: I1,
input2: I2,
hoistState: @Composable (T) -> Unit
): Unit
@Composable
abstract fun AComposableWithoutLambda(
input1: I1,
input2: I2,
): Unit
}
@Composable fun AndroidLibComposableWithLambda(
i1: I1,
i2: I2,
objectWithComposables: AndroidLibAbstractClass
): T? {
val payload: MutableState = remember { mutableStateOf(null) }
objectWithComposables.AComposableWithLambda(i1, i2) @Composable {
payload.value = it
}
return payload.value
}
@Composable fun AndroidLibComposableWithoutLambda(
i1: I1,
i2: I2,
objectWithComposables: AndroidLibAbstractClass
): Unit {
objectWithComposables.AComposableWithoutLambda(i1, i2)
}
```
Are defined in android-lib-module.
In the app module, a concrete child class of `AndroidLibAbstractClass` _can be used successfully_ in a Compose UI composition.
However, in the `launchMolecule` composition (see `MethodResolutionTest`) this fails on `AndroidLibComposableWithLambda`:
```
private class AndroidAppConcreteTestClass(
private val payload: String
) : AndroidLibAbstractClass() {
@Composable
public override fun AComposableWithLambda(
input1: Unit,
input2: String,
hoistState: @Composable (s: String) -> Unit
) {
println("Can you hear me now? $payload")
hoistState(payload + input2)
}
@Composable
override fun AComposableWithoutLambda(
input1: Unit,
input2: String
) {
}
}
@Test fun testMethodResolution() {
val objectUnderTest = AndroidAppConcreteTestClass("a test")
val broadcastFrameClock = BroadcastFrameClock {}
val testScope = CoroutineScope(broadcastFrameClock)
val testFlow = testScope.launchMolecule {
AndroidLibComposableWithoutLambda(Unit, " again", objectUnderTest)
AndroidLibComposableWithLambda(Unit, " again", objectUnderTest)
}
assert(testFlow.value.contentEquals("a test again"))
}
```
because it gets an AbstractMethodError as it cannot resolve the concrete class's override at runtime?
Originally I thought it might be because I was using the 0.3.0-SNAPSHOT and the common KMP artifacts so I include a module with that example as well, but I was able to reproduce it with just 0.2.0 while all in Android/JVM.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the reproducing project in steve-the-edwards/reproductions/overridetest and the MethodResolutionTest described in the issue. Run the launchMolecule test and compare method resolution for the composable with a lambda against the version without one. Done means the concrete override resolves without AbstractMethodError and the assertion passes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, kotlin
- Domain
- mobile-dev, testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100