Merge "Change how function instances are compared for skipping" into androidx-main
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ComposerParamTransformTests.kt b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ComposerParamTransformTests.kt
index 897c193..905e566 100644
--- a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ComposerParamTransformTests.kt
+++ b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ComposerParamTransformTests.kt
@@ -501,7 +501,7 @@
sourceInformation(%composer, "C(Wrapper)<block(...>:Test.kt#2487m")
val %dirty = %changed
if (%changed and 0b1110 === 0) {
- %dirty = %dirty or if (%composer.changed(block)) 0b0100 else 0b0010
+ %dirty = %dirty or if (%composer.changedInstance(block)) 0b0100 else 0b0010
}
if (%dirty and 0b1011 !== 0b0010 || !%composer.skipping) {
if (isTraceInProgress()) {
@@ -648,7 +648,7 @@
sourceInformation(%composer, "C(composeVector)<emit>:Test.kt#2487m")
val %dirty = %changed
if (%changed and 0b1110 === 0) {
- %dirty = %dirty or if (%composer.changed(composable)) 0b0100 else 0b0010
+ %dirty = %dirty or if (%composer.changedInstance(composable)) 0b0100 else 0b0010
}
if (%dirty and 0b1011 !== 0b0010 || !%composer.skipping) {
if (isTraceInProgress()) {
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ContextReceiversTransformTests.kt b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ContextReceiversTransformTests.kt
index 7d0cee9..9edb6f7 100644
--- a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ContextReceiversTransformTests.kt
+++ b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ContextReceiversTransformTests.kt
@@ -544,7 +544,7 @@
sourceInformation(%composer, "C(Test)<b("yay...>:Test.kt")
val %dirty = %changed
if (%changed and 0b001110000000 === 0) {
- %dirty = %dirty or if (%composer.changed(b)) 0b000100000000 else 0b10000000
+ %dirty = %dirty or if (%composer.changedInstance(b)) 0b000100000000 else 0b10000000
}
if (%dirty and 0b001010000001 !== 0b10000000 || !%composer.skipping) {
if (isTraceInProgress()) {
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/FunctionBodySkippingTransformTests.kt b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/FunctionBodySkippingTransformTests.kt
index c53597f..e569c06 100644
--- a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/FunctionBodySkippingTransformTests.kt
+++ b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/FunctionBodySkippingTransformTests.kt
@@ -167,7 +167,7 @@
if (%default and 0b0010 !== 0) {
%dirty = %dirty or 0b00110000
} else if (%changed and 0b01110000 === 0) {
- %dirty = %dirty or if (%composer.changed(onTextLayout)) 0b00100000 else 0b00010000
+ %dirty = %dirty or if (%composer.changedInstance(onTextLayout)) 0b00100000 else 0b00010000
}
if (%default and 0b0100 !== 0) {
%dirty = %dirty or 0b000110000000
@@ -273,7 +273,7 @@
if (%default and 0b0001 !== 0) {
%dirty = %dirty or 0b0110
} else if (%changed and 0b1110 === 0) {
- %dirty = %dirty or if (%composer.changed(content)) 0b0100 else 0b0010
+ %dirty = %dirty or if (%composer.changedInstance(content)) 0b0100 else 0b0010
}
if (%dirty and 0b1011 !== 0b0010 || !%composer.skipping) {
if (%default and 0b0001 !== 0) {
@@ -565,7 +565,7 @@
if (%default and 0b00100000 !== 0) {
%dirty = %dirty or 0b00110000000000000000
} else if (%changed and 0b01110000000000000000 === 0) {
- %dirty = %dirty or if (%composer.changed(content)) 0b00100000000000000000 else 0b00010000000000000000
+ %dirty = %dirty or if (%composer.changedInstance(content)) 0b00100000000000000000 else 0b00010000000000000000
}
if (%dirty and 0b01011011011011011011 !== 0b00010010010010010010 || !%composer.skipping) {
if (%default and 0b0010 !== 0) {
@@ -623,7 +623,7 @@
if (%default and 0b1000 !== 0) {
%dirty = %dirty or 0b110000000000
} else if (%changed and 0b0001110000000000 === 0) {
- %dirty = %dirty or if (%composer.changed(content)) 0b100000000000 else 0b010000000000
+ %dirty = %dirty or if (%composer.changedInstance(content)) 0b100000000000 else 0b010000000000
}
if (%dirty and 0b0001011011011011 !== 0b010010010010 || !%composer.skipping) {
if (%default and 0b0001 !== 0) {
@@ -960,7 +960,7 @@
if (%default and 0b0010 !== 0) {
%dirty = %dirty or 0b00110000
} else if (%changed and 0b01110000 === 0) {
- %dirty = %dirty or if (%composer.changed(content)) 0b00100000 else 0b00010000
+ %dirty = %dirty or if (%composer.changedInstance(content)) 0b00100000 else 0b00010000
}
if (%dirty and 0b01011011 !== 0b00010010 || !%composer.skipping) {
if (%default and 0b0001 !== 0) {
@@ -1100,7 +1100,7 @@
sourceInformation(%composer, "C(SomeThing)<conten...>:Test.kt")
val %dirty = %changed
if (%changed and 0b1110 === 0) {
- %dirty = %dirty or if (%composer.changed(content)) 0b0100 else 0b0010
+ %dirty = %dirty or if (%composer.changedInstance(content)) 0b0100 else 0b0010
}
if (%dirty and 0b1011 !== 0b0010 || !%composer.skipping) {
if (isTraceInProgress()) {
@@ -1435,7 +1435,7 @@
%dirty = %dirty or if (%composer.changed(y)) 0b0100 else 0b0010
}
if (%changed and 0b01110000 === 0) {
- %dirty = %dirty or if (%composer.changed(content)) 0b00100000 else 0b00010000
+ %dirty = %dirty or if (%composer.changedInstance(content)) 0b00100000 else 0b00010000
}
if (%dirty and 0b01011011 !== 0b00010010 || !%composer.skipping) {
if (isTraceInProgress()) {
@@ -3454,7 +3454,7 @@
sourceInformation(%composer, "C(Example)<invoke...>:Test.kt")
val %dirty = %changed
if (%changed and 0b1110 === 0) {
- %dirty = %dirty or if (%composer.changed(content)) 0b0100 else 0b0010
+ %dirty = %dirty or if (%composer.changedInstance(content)) 0b0100 else 0b0010
}
if (%dirty and 0b1011 !== 0b0010 || !%composer.skipping) {
if (isTraceInProgress()) {
@@ -3540,7 +3540,7 @@
if (%default and 0b0100 !== 0) {
%dirty = %dirty or 0b000110000000
} else if (%changed and 0b001110000000 === 0) {
- %dirty = %dirty or if (%composer.changed(content)) 0b000100000000 else 0b10000000
+ %dirty = %dirty or if (%composer.changedInstance(content)) 0b000100000000 else 0b10000000
}
if (%dirty and 0b001011011011 !== 0b10010010 || !%composer.skipping) {
if (%default and 0b0001 !== 0) {
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/LambdaMemoizationTransformTests.kt b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/LambdaMemoizationTransformTests.kt
index b9a59ea..803e2de 100644
--- a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/LambdaMemoizationTransformTests.kt
+++ b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/LambdaMemoizationTransformTests.kt
@@ -678,7 +678,7 @@
if (%default and 0b0010 !== 0) {
%dirty = %dirty or 0b00110000
} else if (%changed and 0b01110000 === 0) {
- %dirty = %dirty or if (%composer.changed(content)) 0b00100000 else 0b00010000
+ %dirty = %dirty or if (%composer.changedInstance(content)) 0b00100000 else 0b00010000
}
if (%dirty and 0b01011011 !== 0b00010010 || !%composer.skipping) {
if (%default and 0b0010 !== 0) {
@@ -805,7 +805,7 @@
sourceInformation(%composer, "C(TestLambda):Test.kt")
val %dirty = %changed
if (%changed and 0b1110 === 0) {
- %dirty = %dirty or if (%composer.changed(content)) 0b0100 else 0b0010
+ %dirty = %dirty or if (%composer.changedInstance(content)) 0b0100 else 0b0010
}
if (%dirty and 0b1011 !== 0b0010 || !%composer.skipping) {
if (isTraceInProgress()) {
@@ -871,7 +871,7 @@
sourceInformation(%composer, "C(TestLambda):Test.kt")
val %dirty = %changed
if (%changed and 0b1110 === 0) {
- %dirty = %dirty or if (%composer.changed(content)) 0b0100 else 0b0010
+ %dirty = %dirty or if (%composer.changedInstance(content)) 0b0100 else 0b0010
}
if (%dirty and 0b1011 !== 0b0010 || !%composer.skipping) {
if (isTraceInProgress()) {
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/TargetAnnotationsTransformTests.kt b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/TargetAnnotationsTransformTests.kt
index 0153148..e438684 100644
--- a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/TargetAnnotationsTransformTests.kt
+++ b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/TargetAnnotationsTransformTests.kt
@@ -137,7 +137,7 @@
sourceInformation(%composer, "C(Test)<conten...>:Test.kt")
val %dirty = %changed
if (%changed and 0b1110 === 0) {
- %dirty = %dirty or if (%composer.changed(content)) 0b0100 else 0b0010
+ %dirty = %dirty or if (%composer.changedInstance(content)) 0b0100 else 0b0010
}
if (%dirty and 0b1011 !== 0b0010 || !%composer.skipping) {
if (isTraceInProgress()) {
@@ -535,7 +535,7 @@
sourceInformation(%composer, "C(Test)*<it()>:Test.kt")
val %dirty = %changed
if (%changed and 0b1110 === 0) {
- %dirty = %dirty or if (%composer.changed(content)) 0b0100 else 0b0010
+ %dirty = %dirty or if (%composer.changedInstance(content)) 0b0100 else 0b0010
}
if (%dirty and 0b1011 !== 0b0010 || !%composer.skipping) {
if (isTraceInProgress()) {
@@ -645,7 +645,7 @@
sourceInformation(%composer, "C(Wrapper)<conten...>:Test.kt")
val %dirty = %changed
if (%changed and 0b1110 === 0) {
- %dirty = %dirty or if (%composer.changed(content)) 0b0100 else 0b0010
+ %dirty = %dirty or if (%composer.changedInstance(content)) 0b0100 else 0b0010
}
if (%dirty and 0b1011 !== 0b0010 || !%composer.skipping) {
if (isTraceInProgress()) {
@@ -671,37 +671,37 @@
if (%default and 0b0001 !== 0) {
%dirty = %dirty or 0b0110
} else if (%changed and 0b1110 === 0) {
- %dirty = %dirty or if (%composer.changed(one)) 0b0100 else 0b0010
+ %dirty = %dirty or if (%composer.changedInstance(one)) 0b0100 else 0b0010
}
if (%default and 0b0010 !== 0) {
%dirty = %dirty or 0b00110000
} else if (%changed and 0b01110000 === 0) {
- %dirty = %dirty or if (%composer.changed(two)) 0b00100000 else 0b00010000
+ %dirty = %dirty or if (%composer.changedInstance(two)) 0b00100000 else 0b00010000
}
if (%default and 0b0100 !== 0) {
%dirty = %dirty or 0b000110000000
} else if (%changed and 0b001110000000 === 0) {
- %dirty = %dirty or if (%composer.changed(three)) 0b000100000000 else 0b10000000
+ %dirty = %dirty or if (%composer.changedInstance(three)) 0b000100000000 else 0b10000000
}
if (%default and 0b1000 !== 0) {
%dirty = %dirty or 0b110000000000
} else if (%changed and 0b0001110000000000 === 0) {
- %dirty = %dirty or if (%composer.changed(four)) 0b100000000000 else 0b010000000000
+ %dirty = %dirty or if (%composer.changedInstance(four)) 0b100000000000 else 0b010000000000
}
if (%default and 0b00010000 !== 0) {
%dirty = %dirty or 0b0110000000000000
} else if (%changed and 0b1110000000000000 === 0) {
- %dirty = %dirty or if (%composer.changed(five)) 0b0100000000000000 else 0b0010000000000000
+ %dirty = %dirty or if (%composer.changedInstance(five)) 0b0100000000000000 else 0b0010000000000000
}
if (%default and 0b00100000 !== 0) {
%dirty = %dirty or 0b00110000000000000000
} else if (%changed and 0b01110000000000000000 === 0) {
- %dirty = %dirty or if (%composer.changed(six)) 0b00100000000000000000 else 0b00010000000000000000
+ %dirty = %dirty or if (%composer.changedInstance(six)) 0b00100000000000000000 else 0b00010000000000000000
}
if (%default and 0b01000000 !== 0) {
%dirty = %dirty or 0b000110000000000000000000
} else if (%changed and 0b001110000000000000000000 === 0) {
- %dirty = %dirty or if (%composer.changed(content)) 0b000100000000000000000000 else 0b10000000000000000000
+ %dirty = %dirty or if (%composer.changedInstance(content)) 0b000100000000000000000000 else 0b10000000000000000000
}
if (%dirty and 0b001011011011011011011011 !== 0b10010010010010010010 || !%composer.skipping) {
if (%default and 0b0001 !== 0) {
@@ -1020,7 +1020,7 @@
sourceInformation(%composer, "C(Test2)<Layout...>:Test.kt")
val %dirty = %changed
if (%changed and 0b1110 === 0) {
- %dirty = %dirty or if (%composer.changed(content)) 0b0100 else 0b0010
+ %dirty = %dirty or if (%composer.changedInstance(content)) 0b0100 else 0b0010
}
if (%dirty and 0b1011 !== 0b0010 || !%composer.skipping) {
if (isTraceInProgress()) {
@@ -1094,7 +1094,7 @@
sourceInformation(%composer, "C(Test5)<Compos...>:Test.kt")
val %dirty = %changed
if (%changed and 0b1110 === 0) {
- %dirty = %dirty or if (%composer.changed(content)) 0b0100 else 0b0010
+ %dirty = %dirty or if (%composer.changedInstance(content)) 0b0100 else 0b0010
}
if (%dirty and 0b1011 !== 0b0010 || !%composer.skipping) {
if (isTraceInProgress()) {
@@ -1272,7 +1272,7 @@
sourceInformation(%composer, "C(Test)<rememb...>:Test.kt")
val %dirty = %changed
if (%changed and 0b1110 === 0) {
- %dirty = %dirty or if (%composer.changed(content)) 0b0100 else 0b0010
+ %dirty = %dirty or if (%composer.changedInstance(content)) 0b0100 else 0b0010
}
if (%dirty and 0b1011 !== 0b0010 || !%composer.skipping) {
if (isTraceInProgress()) {
@@ -1426,7 +1426,7 @@
sourceInformation(%composer, "C(Test)<decora...>:Test.kt")
val %dirty = %changed
if (%changed and 0b1110 === 0) {
- %dirty = %dirty or if (%composer.changed(decorator)) 0b0100 else 0b0010
+ %dirty = %dirty or if (%composer.changedInstance(decorator)) 0b0100 else 0b0010
}
if (%dirty and 0b1011 !== 0b0010 || !%composer.skipping) {
if (isTraceInProgress()) {
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableFunctionBodyTransformer.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableFunctionBodyTransformer.kt
index 85953db..134e3f3 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableFunctionBodyTransformer.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableFunctionBodyTransformer.kt
@@ -152,6 +152,7 @@
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.getPropertyGetter
+import org.jetbrains.kotlin.ir.util.isFunction
import org.jetbrains.kotlin.ir.util.isLocal
import org.jetbrains.kotlin.ir.util.isVararg
import org.jetbrains.kotlin.ir.util.kotlinFqName
@@ -503,6 +504,12 @@
it.name.identifier == "changed" && it.valueParameters.first().type.isNullableAny()
}
+ private val changedInstanceFunction = composerIrClass.functions
+ .firstOrNull() {
+ it.name.identifier == "changedInstance" &&
+ it.valueParameters.first().type.isNullableAny()
+ } ?: changedFunction
+
private fun IrType.toPrimitiveType(): PrimitiveType? = when {
isInt() -> PrimitiveType.INT
isBoolean() -> PrimitiveType.BOOLEAN
@@ -2150,7 +2157,8 @@
val expr = value.unboxValueIfInline()
val descriptor = type
.toPrimitiveType()
- .let { changedPrimitiveFunctions[it] } ?: changedFunction
+ .let { changedPrimitiveFunctions[it] }
+ ?: if (type.isFunction()) changedInstanceFunction else changedFunction
return irMethodCall(irCurrentComposer(), descriptor).also {
it.putValueArgument(0, expr)
}
diff --git a/compose/runtime/runtime/api/current.txt b/compose/runtime/runtime/api/current.txt
index 2c2e001..8b0cc2a 100644
--- a/compose/runtime/runtime/api/current.txt
+++ b/compose/runtime/runtime/api/current.txt
@@ -108,6 +108,7 @@
method @androidx.compose.runtime.ComposeCompilerApi public default boolean changed(float value);
method @androidx.compose.runtime.ComposeCompilerApi public default boolean changed(long value);
method @androidx.compose.runtime.ComposeCompilerApi public default boolean changed(double value);
+ method @androidx.compose.runtime.ComposeCompilerApi public default boolean changedInstance(Object? value);
method public void collectParameterInformation();
method @androidx.compose.runtime.ComposeCompilerApi public <T> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
method @androidx.compose.runtime.ComposeCompilerApi public void deactivateToEndGroup(boolean changed);
diff --git a/compose/runtime/runtime/api/public_plus_experimental_current.txt b/compose/runtime/runtime/api/public_plus_experimental_current.txt
index 0801888..c69dd48 100644
--- a/compose/runtime/runtime/api/public_plus_experimental_current.txt
+++ b/compose/runtime/runtime/api/public_plus_experimental_current.txt
@@ -114,6 +114,7 @@
method @androidx.compose.runtime.ComposeCompilerApi public default boolean changed(float value);
method @androidx.compose.runtime.ComposeCompilerApi public default boolean changed(long value);
method @androidx.compose.runtime.ComposeCompilerApi public default boolean changed(double value);
+ method @androidx.compose.runtime.ComposeCompilerApi public default boolean changedInstance(Object? value);
method public void collectParameterInformation();
method @androidx.compose.runtime.InternalComposeApi public <T> T! consume(androidx.compose.runtime.CompositionLocal<T> key);
method @androidx.compose.runtime.ComposeCompilerApi public <T> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
diff --git a/compose/runtime/runtime/api/restricted_current.txt b/compose/runtime/runtime/api/restricted_current.txt
index b50e6f8..684ac84 100644
--- a/compose/runtime/runtime/api/restricted_current.txt
+++ b/compose/runtime/runtime/api/restricted_current.txt
@@ -110,6 +110,7 @@
method @androidx.compose.runtime.ComposeCompilerApi public default boolean changed(float value);
method @androidx.compose.runtime.ComposeCompilerApi public default boolean changed(long value);
method @androidx.compose.runtime.ComposeCompilerApi public default boolean changed(double value);
+ method @androidx.compose.runtime.ComposeCompilerApi public default boolean changedInstance(Object? value);
method public void collectParameterInformation();
method @androidx.compose.runtime.ComposeCompilerApi public <T> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
method @androidx.compose.runtime.ComposeCompilerApi public void deactivateToEndGroup(boolean changed);
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
index 44515859..318a06f 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
@@ -19,6 +19,7 @@
)
package androidx.compose.runtime
+import androidx.compose.runtime.Composer.Companion.equals
import androidx.compose.runtime.collection.IdentityArrayMap
import androidx.compose.runtime.collection.IdentityArraySet
import androidx.compose.runtime.external.kotlinx.collections.immutable.PersistentMap
@@ -916,6 +917,21 @@
@ComposeCompilerApi
fun changed(value: Double): Boolean = changed(value)
+ /**
+ * A Compose compiler plugin API. DO NOT call directly.
+ *
+ * Check [value] is different than the value used in the previous composition using `===`
+ * instead of `==` equality. This is used, for example, to check parameter values to determine
+ * if they have changed for values that use value equality but, for correct behavior, the
+ * composer needs reference equality.
+ *
+ * @param value the value to check
+ * @return `true` if the value is === equal to the previous value and returns `false` when
+ * [value] is different.
+ */
+ @ComposeCompilerApi
+ fun changedInstance(value: Any?): Boolean = changed(value)
+
// Scopes
/**
@@ -1662,6 +1678,16 @@
}
@ComposeCompilerApi
+ override fun changedInstance(value: Any?): Boolean {
+ return if (nextSlot() !== value) {
+ updateValue(value)
+ true
+ } else {
+ false
+ }
+ }
+
+ @ComposeCompilerApi
override fun changed(value: Char): Boolean {
val next = nextSlot()
if (next is Char) {
diff --git a/compose/runtime/runtime/src/commonTest/kotlin/androidx/compose/runtime/CompositionTests.kt b/compose/runtime/runtime/src/commonTest/kotlin/androidx/compose/runtime/CompositionTests.kt
index a20604d..82ba839 100644
--- a/compose/runtime/runtime/src/commonTest/kotlin/androidx/compose/runtime/CompositionTests.kt
+++ b/compose/runtime/runtime/src/commonTest/kotlin/androidx/compose/runtime/CompositionTests.kt
@@ -3214,6 +3214,31 @@
Text("Hello!")
}
}
+
+ @Test // Regression test for b/249050560
+ fun testFunctionInstances() = compositionTest {
+ var state by mutableStateOf(0)
+ functionInstance = { -1 }
+
+ compose {
+ val localStateCopy = state
+ fun localStateReader() = localStateCopy
+ updateInstance(::localStateReader)
+ }
+
+ assertEquals(state, functionInstance())
+
+ state = 10
+ advance()
+ assertEquals(state, functionInstance())
+ }
+}
+
+var functionInstance: () -> Int = { 0 }
+
+@Composable
+fun updateInstance(newInstance: () -> Int) {
+ functionInstance = newInstance
}
var stateA by mutableStateOf(1000)