Make `snapshotFlow` no longer experimental

Also removes experimental from `withMutableSnapshot` and
moves it to as a companion method of Snapshot.

Fixes: 178392296, 178490402
Test: ./gradlew :compose:r:r:tDUT
Relnote: """`snapshotFlow` and `withMutableSnapshot` are no longer
experimental"""

Change-Id: I6a45fac62267a318481e9a3ba8a3acf3162219f6
diff --git a/compose/runtime/runtime/api/current.txt b/compose/runtime/runtime/api/current.txt
index 833d1e5..dbb5c5b 100644
--- a/compose/runtime/runtime/api/current.txt
+++ b/compose/runtime/runtime/api/current.txt
@@ -692,6 +692,7 @@
     method public kotlin.jvm.functions.Function0<kotlin.Unit> registerApplyObserver(kotlin.jvm.functions.Function2<? super java.util.Set<?>,? super androidx.compose.runtime.snapshots.Snapshot,kotlin.Unit> observer);
     method public kotlin.jvm.functions.Function0<kotlin.Unit> registerGlobalWriteObserver(kotlin.jvm.functions.Function1<java.lang.Object,kotlin.Unit> observer);
     method public void sendApplyNotifications();
+    method public inline <R> R! withMutableSnapshot(kotlin.jvm.functions.Function0<? extends R> block);
     property public final androidx.compose.runtime.snapshots.Snapshot! current;
   }
 
@@ -724,8 +725,8 @@
   }
 
   public final class SnapshotFlowKt {
-    method @androidx.compose.runtime.ExperimentalComposeApi public static <T> kotlinx.coroutines.flow.Flow<T> snapshotFlow(kotlin.jvm.functions.Function0<? extends T> block);
-    method @androidx.compose.runtime.ExperimentalComposeApi public static inline <R> R! withMutableSnapshot(kotlin.jvm.functions.Function0<? extends R> block);
+    method public static <T> kotlinx.coroutines.flow.Flow<T> snapshotFlow(kotlin.jvm.functions.Function0<? extends T> block);
+    method @Deprecated @androidx.compose.runtime.ExperimentalComposeApi public static inline <R> R! withMutableSnapshot(kotlin.jvm.functions.Function0<? extends R> block);
   }
 
   public final class SnapshotIdSetKt {
diff --git a/compose/runtime/runtime/api/public_plus_experimental_current.txt b/compose/runtime/runtime/api/public_plus_experimental_current.txt
index 833d1e5..dbb5c5b 100644
--- a/compose/runtime/runtime/api/public_plus_experimental_current.txt
+++ b/compose/runtime/runtime/api/public_plus_experimental_current.txt
@@ -692,6 +692,7 @@
     method public kotlin.jvm.functions.Function0<kotlin.Unit> registerApplyObserver(kotlin.jvm.functions.Function2<? super java.util.Set<?>,? super androidx.compose.runtime.snapshots.Snapshot,kotlin.Unit> observer);
     method public kotlin.jvm.functions.Function0<kotlin.Unit> registerGlobalWriteObserver(kotlin.jvm.functions.Function1<java.lang.Object,kotlin.Unit> observer);
     method public void sendApplyNotifications();
+    method public inline <R> R! withMutableSnapshot(kotlin.jvm.functions.Function0<? extends R> block);
     property public final androidx.compose.runtime.snapshots.Snapshot! current;
   }
 
@@ -724,8 +725,8 @@
   }
 
   public final class SnapshotFlowKt {
-    method @androidx.compose.runtime.ExperimentalComposeApi public static <T> kotlinx.coroutines.flow.Flow<T> snapshotFlow(kotlin.jvm.functions.Function0<? extends T> block);
-    method @androidx.compose.runtime.ExperimentalComposeApi public static inline <R> R! withMutableSnapshot(kotlin.jvm.functions.Function0<? extends R> block);
+    method public static <T> kotlinx.coroutines.flow.Flow<T> snapshotFlow(kotlin.jvm.functions.Function0<? extends T> block);
+    method @Deprecated @androidx.compose.runtime.ExperimentalComposeApi public static inline <R> R! withMutableSnapshot(kotlin.jvm.functions.Function0<? extends R> block);
   }
 
   public final class SnapshotIdSetKt {
diff --git a/compose/runtime/runtime/api/restricted_current.txt b/compose/runtime/runtime/api/restricted_current.txt
index 07e1499..9e431c7 100644
--- a/compose/runtime/runtime/api/restricted_current.txt
+++ b/compose/runtime/runtime/api/restricted_current.txt
@@ -723,6 +723,7 @@
     method @kotlin.PublishedApi internal androidx.compose.runtime.snapshots.Snapshot? removeCurrent();
     method @kotlin.PublishedApi internal void restoreCurrent(androidx.compose.runtime.snapshots.Snapshot? previous);
     method public void sendApplyNotifications();
+    method public inline <R> R! withMutableSnapshot(kotlin.jvm.functions.Function0<? extends R> block);
     property public final androidx.compose.runtime.snapshots.Snapshot! current;
   }
 
@@ -755,8 +756,8 @@
   }
 
   public final class SnapshotFlowKt {
-    method @androidx.compose.runtime.ExperimentalComposeApi public static <T> kotlinx.coroutines.flow.Flow<T> snapshotFlow(kotlin.jvm.functions.Function0<? extends T> block);
-    method @androidx.compose.runtime.ExperimentalComposeApi public static inline <R> R! withMutableSnapshot(kotlin.jvm.functions.Function0<? extends R> block);
+    method public static <T> kotlinx.coroutines.flow.Flow<T> snapshotFlow(kotlin.jvm.functions.Function0<? extends T> block);
+    method @Deprecated @androidx.compose.runtime.ExperimentalComposeApi public static inline <R> R! withMutableSnapshot(kotlin.jvm.functions.Function0<? extends R> block);
   }
 
   public final class SnapshotIdSetKt {
diff --git a/compose/runtime/runtime/samples/src/main/java/androidx/compose/runtime/samples/SnapshotSamples.kt b/compose/runtime/runtime/samples/src/main/java/androidx/compose/runtime/samples/SnapshotSamples.kt
index 1e62c6d..2bf9ecf 100644
--- a/compose/runtime/runtime/samples/src/main/java/androidx/compose/runtime/samples/SnapshotSamples.kt
+++ b/compose/runtime/runtime/samples/src/main/java/androidx/compose/runtime/samples/SnapshotSamples.kt
@@ -21,8 +21,8 @@
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshots.Snapshot
 import androidx.compose.runtime.snapshots.snapshotFlow
-import androidx.compose.runtime.snapshots.withMutableSnapshot
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.launch
@@ -54,7 +54,7 @@
     // ...
 
     // Change snapshot state; greetPersonFlow will emit a new greeting
-    withMutableSnapshot {
+    Snapshot.withMutableSnapshot {
         greeting = "Ahoy"
         person = "Sean"
     }
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt
index 8deda49..0e904d0 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt
@@ -317,6 +317,31 @@
         }
 
         /**
+         * Take a [MutableSnapshot] and run [block] within it. When [block] returns successfully,
+         * attempt to [MutableSnapshot.apply] the snapshot. Returns the result of [block] or throws
+         * [SnapshotApplyConflictException] if snapshot changes attempted by [block] could not be
+         * applied.
+         *
+         * Prior to returning, any changes made to snapshot state (e.g. state holders returned by
+         * [androidx.compose.runtime.mutableStateOf] are not visible to other threads. When
+         * [withMutableSnapshot] returns successfully those changes will be made visible to other
+         * threads  and any snapshot observers (e.g. [snapshotFlow]) will be notified of changes.
+         *
+         * [block] must not suspend if [withMutableSnapshot] is called from a suspend function.
+         */
+        // TODO: determine a good way to prevent/discourage suspending in an inlined [block]
+        inline fun <R> withMutableSnapshot(
+            block: () -> R
+        ): R = takeMutableSnapshot().run {
+            try {
+                enter(block).also { apply().check() }
+            } catch (t: Throwable) {
+                dispose()
+                throw t
+            }
+        }
+
+        /**
          * Observe reads and or write of state objects in the current thread.
          *
          * This only affects the current snapshot (if any) and any new snapshots create from
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotFlow.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotFlow.kt
index 3ecb3ee..e2a2a8cd 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotFlow.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotFlow.kt
@@ -60,7 +60,6 @@
  * intermediate states as well as run multiple times for the same state and the result should
  * be the same.
  */
-@ExperimentalComposeApi
 fun <T> snapshotFlow(
     block: () -> T
 ): Flow<T> = flow {
@@ -140,6 +139,12 @@
  */
 // TODO: determine a good way to prevent/discourage suspending in an inlined [block]
 @ExperimentalComposeApi
+@Deprecated(
+    "Use Snapshot.withMutableSnapshot() instead",
+    ReplaceWith(
+        "Snapshot.withMutableSnapshot(block)"
+    )
+)
 inline fun <R> withMutableSnapshot(
     block: () -> R
 ): R = takeMutableSnapshot().run {
@@ -149,4 +154,4 @@
         dispose()
         throw t
     }
-}
+}
\ No newline at end of file
diff --git a/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/snapshots/SnapshotFlowTests.kt b/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/snapshots/SnapshotFlowTests.kt
index 2bd56c8..5c9a611 100644
--- a/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/snapshots/SnapshotFlowTests.kt
+++ b/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/snapshots/SnapshotFlowTests.kt
@@ -45,7 +45,7 @@
 
         assertEquals(2, result, "value after initial run")
 
-        withMutableSnapshot {
+        Snapshot.withMutableSnapshot {
             state = 5
         }
 
@@ -69,13 +69,13 @@
         yield()
         assertEquals(1, runCount, "snapshot collector initial run")
 
-        withMutableSnapshot { state++ }
+        Snapshot.withMutableSnapshot { state++ }
         yield()
 
         assertEquals(2, runCount, "made one change")
 
-        withMutableSnapshot { state++ }
-        withMutableSnapshot { state++ }
+        Snapshot.withMutableSnapshot { state++ }
+        Snapshot.withMutableSnapshot { state++ }
         yield()
 
         assertEquals(3, runCount, "coalesced two changes")
@@ -98,7 +98,7 @@
 
         assertEquals(1, runCount, "initial run")
 
-        withMutableSnapshot { unrelatedState++ }
+        Snapshot.withMutableSnapshot { unrelatedState++ }
         yield()
 
         assertEquals(1, runCount, "after changing unrelated state")
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt
index eaeebde..d2fed78 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt
@@ -21,7 +21,7 @@
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.setValue
-import androidx.compose.runtime.snapshots.withMutableSnapshot
+import androidx.compose.runtime.snapshots.Snapshot
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.platform.InspectableValue
@@ -264,7 +264,7 @@
                 }
             }
             scenario.moveToState(Lifecycle.State.STARTED)
-            withMutableSnapshot {
+            Snapshot.withMutableSnapshot {
                 toAdd = "secondary"
             }
             assertTrue("waiting for relaunch timed out", latch.await(1, TimeUnit.SECONDS))