Mark State<T> and MutableState<T> as stable types
Theses are both implemented by an @Model object which is stable so
the interfaces should be stable.
Fixes: 146557624
Test: modified existing test
Change-Id: Ic868b7d72d89a49878d6bb7f1b07ecf8f5be2199
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsCodegenTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsCodegenTests.kt
index 69dd518..b3645e7 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsCodegenTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsCodegenTests.kt
@@ -2336,7 +2336,7 @@
var output = ArrayList<String>()
class NotStable { val value = 10 }
-
+
@Stable
class StableClass {
override fun equals(other: Any?) = true
@@ -2347,6 +2347,9 @@
Two
}
+ val mutableStateType = mutableStateOf(1)
+ val stateType: State<Int> = mutableStateType
+
@Composable
fun MemoInt(a: Int) {
output.add("MemoInt a=${'$'}a")
@@ -2382,7 +2385,7 @@
output.add("MemoEnum")
Button(text="memo ${'$'}{a}")
}
-
+
@Composable
fun MemoStable(a: StableClass) {
output.add("MemoStable")
@@ -2390,6 +2393,18 @@
}
@Composable
+ fun MemoMutableState(a: MutableState<Int>) {
+ output.add("MemoMutableState")
+ Button(text="memo ${'$'}{a.value}")
+ }
+
+ @Composable
+ fun MemoState(a: State<Int>) {
+ output.add("MemoState")
+ Button(text="memo ${'$'}{a.value}")
+ }
+
+ @Composable
fun TestSkipping(
a: Int,
b: Float,
@@ -2397,7 +2412,9 @@
d: NotStable,
e: ValueHolder,
f: EnumState,
- g: StableClass
+ g: StableClass,
+ h: MutableState<Int>,
+ i: State<Int>
) {
val am = a + m.count
output.add("TestSkipping a=${'$'}a am=${'$'}am")
@@ -2408,11 +2425,23 @@
MemoModel(a=e)
MemoEnum(a=f)
MemoStable(a=g)
+ MemoMutableState(h)
+ MemoState(i)
}
@Composable
fun Main(v: ValueHolder, n: NotStable) {
- TestSkipping(a=1, b=1f, c=2.0, d=NotStable(), e=v, f=EnumState.One, g=StableClass())
+ TestSkipping(
+ a=1,
+ b=1f,
+ c=2.0,
+ d=NotStable(),
+ e=v,
+ f=EnumState.One,
+ g=StableClass(),
+ h=mutableStateType,
+ i=stateType
+ )
}
""", {
mapOf(
@@ -2426,7 +2455,8 @@
// Expect that all the methods are called in order
assertEquals(
"TestSkipping a=1 am=1, MemoInt a=1, MemoFloat, " +
- "MemoDouble, MemoNotStable, MemoModelHolder, MemoEnum, MemoStable",
+ "MemoDouble, MemoNotStable, MemoModelHolder, MemoEnum, MemoStable, " +
+ "MemoMutableState, MemoState",
output.joinToString()
)
output.clear()
diff --git a/compose/compose-runtime/api/0.1.0-dev04.txt b/compose/compose-runtime/api/0.1.0-dev04.txt
index 1c774f4..e48b293 100644
--- a/compose/compose-runtime/api/0.1.0-dev04.txt
+++ b/compose/compose-runtime/api/0.1.0-dev04.txt
@@ -249,7 +249,7 @@
@androidx.compose.StableMarker @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.CLASS) public @interface Model {
}
- public interface MutableState<T> extends androidx.compose.State<T> {
+ @androidx.compose.Stable public interface MutableState<T> extends androidx.compose.State<T> {
method public operator T! component1();
method public operator kotlin.jvm.functions.Function1<T,kotlin.Unit> component2();
method public operator T! getValue(Object? thisObj, kotlin.reflect.KProperty<?> property);
@@ -425,7 +425,7 @@
@kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS}) public @interface StableMarker {
}
- public interface State<T> {
+ @androidx.compose.Stable public interface State<T> {
method public T! getValue();
property public abstract T! value;
}
diff --git a/compose/compose-runtime/api/current.txt b/compose/compose-runtime/api/current.txt
index 1c774f4..e48b293 100644
--- a/compose/compose-runtime/api/current.txt
+++ b/compose/compose-runtime/api/current.txt
@@ -249,7 +249,7 @@
@androidx.compose.StableMarker @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.CLASS) public @interface Model {
}
- public interface MutableState<T> extends androidx.compose.State<T> {
+ @androidx.compose.Stable public interface MutableState<T> extends androidx.compose.State<T> {
method public operator T! component1();
method public operator kotlin.jvm.functions.Function1<T,kotlin.Unit> component2();
method public operator T! getValue(Object? thisObj, kotlin.reflect.KProperty<?> property);
@@ -425,7 +425,7 @@
@kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS}) public @interface StableMarker {
}
- public interface State<T> {
+ @androidx.compose.Stable public interface State<T> {
method public T! getValue();
property public abstract T! value;
}
diff --git a/compose/compose-runtime/api/public_plus_experimental_0.1.0-dev04.txt b/compose/compose-runtime/api/public_plus_experimental_0.1.0-dev04.txt
index 1c774f4..e48b293 100644
--- a/compose/compose-runtime/api/public_plus_experimental_0.1.0-dev04.txt
+++ b/compose/compose-runtime/api/public_plus_experimental_0.1.0-dev04.txt
@@ -249,7 +249,7 @@
@androidx.compose.StableMarker @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.CLASS) public @interface Model {
}
- public interface MutableState<T> extends androidx.compose.State<T> {
+ @androidx.compose.Stable public interface MutableState<T> extends androidx.compose.State<T> {
method public operator T! component1();
method public operator kotlin.jvm.functions.Function1<T,kotlin.Unit> component2();
method public operator T! getValue(Object? thisObj, kotlin.reflect.KProperty<?> property);
@@ -425,7 +425,7 @@
@kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS}) public @interface StableMarker {
}
- public interface State<T> {
+ @androidx.compose.Stable public interface State<T> {
method public T! getValue();
property public abstract T! value;
}
diff --git a/compose/compose-runtime/api/public_plus_experimental_current.txt b/compose/compose-runtime/api/public_plus_experimental_current.txt
index 1c774f4..e48b293 100644
--- a/compose/compose-runtime/api/public_plus_experimental_current.txt
+++ b/compose/compose-runtime/api/public_plus_experimental_current.txt
@@ -249,7 +249,7 @@
@androidx.compose.StableMarker @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.CLASS) public @interface Model {
}
- public interface MutableState<T> extends androidx.compose.State<T> {
+ @androidx.compose.Stable public interface MutableState<T> extends androidx.compose.State<T> {
method public operator T! component1();
method public operator kotlin.jvm.functions.Function1<T,kotlin.Unit> component2();
method public operator T! getValue(Object? thisObj, kotlin.reflect.KProperty<?> property);
@@ -425,7 +425,7 @@
@kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS}) public @interface StableMarker {
}
- public interface State<T> {
+ @androidx.compose.Stable public interface State<T> {
method public T! getValue();
property public abstract T! value;
}
diff --git a/compose/compose-runtime/api/restricted_0.1.0-dev04.txt b/compose/compose-runtime/api/restricted_0.1.0-dev04.txt
index 1c774f4..e48b293 100644
--- a/compose/compose-runtime/api/restricted_0.1.0-dev04.txt
+++ b/compose/compose-runtime/api/restricted_0.1.0-dev04.txt
@@ -249,7 +249,7 @@
@androidx.compose.StableMarker @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.CLASS) public @interface Model {
}
- public interface MutableState<T> extends androidx.compose.State<T> {
+ @androidx.compose.Stable public interface MutableState<T> extends androidx.compose.State<T> {
method public operator T! component1();
method public operator kotlin.jvm.functions.Function1<T,kotlin.Unit> component2();
method public operator T! getValue(Object? thisObj, kotlin.reflect.KProperty<?> property);
@@ -425,7 +425,7 @@
@kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS}) public @interface StableMarker {
}
- public interface State<T> {
+ @androidx.compose.Stable public interface State<T> {
method public T! getValue();
property public abstract T! value;
}
diff --git a/compose/compose-runtime/api/restricted_current.txt b/compose/compose-runtime/api/restricted_current.txt
index 1c774f4..e48b293 100644
--- a/compose/compose-runtime/api/restricted_current.txt
+++ b/compose/compose-runtime/api/restricted_current.txt
@@ -249,7 +249,7 @@
@androidx.compose.StableMarker @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.CLASS) public @interface Model {
}
- public interface MutableState<T> extends androidx.compose.State<T> {
+ @androidx.compose.Stable public interface MutableState<T> extends androidx.compose.State<T> {
method public operator T! component1();
method public operator kotlin.jvm.functions.Function1<T,kotlin.Unit> component2();
method public operator T! getValue(Object? thisObj, kotlin.reflect.KProperty<?> property);
@@ -425,7 +425,7 @@
@kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS}) public @interface StableMarker {
}
- public interface State<T> {
+ @androidx.compose.Stable public interface State<T> {
method public T! getValue();
property public abstract T! value;
}
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/MutableState.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/MutableState.kt
index 2c9c078..081d83e 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/MutableState.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/MutableState.kt
@@ -16,7 +16,6 @@
package androidx.compose
-import androidx.compose.annotations.Hide
import androidx.compose.frames.AbstractRecord
import androidx.compose.frames.Framed
import androidx.compose.frames.Record
@@ -132,6 +131,7 @@
* @see [MutableState]
* @see [mutableStateOf]
*/
+@Stable
interface State<T> {
val value: T
}
@@ -146,6 +146,7 @@
* @see [State]
* @see [mutableStateOf]
*/
+@Stable
interface MutableState<T> : State<T> {
override var value: T
operator fun component1(): T