Merge "Fix and re-enable providers optimization" into androidx-main
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 31650af..5427f4e 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
@@ -2006,18 +2006,14 @@
         if (inserting) {
             providers = parentScope.putValue(local, state)
             invalid = false
+            writerHasAProvider = true
         } else {
             val oldScope = reader.groupAux(reader.currentGroup) as PersistentCompositionLocalMap
             providers =
                 if ((!skipping || change) && (value.canOverride || !parentScope.contains(local)))
                     parentScope.putValue(local, state)
                 else oldScope
-            if (oldScope !== providers) {
-                invalid = true
-                writerHasAProvider = true
-            } else {
-                invalid = false
-            }
+            invalid = reusing || oldScope !== providers
         }
         if (invalid && !inserting) {
             providerUpdates[reader.currentGroup] = providers
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/CompositionLocal.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/CompositionLocal.kt
index cde9d7c..1073e39 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/CompositionLocal.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/CompositionLocal.kt
@@ -244,10 +244,9 @@
 @Composable
 @OptIn(InternalComposeApi::class)
 fun CompositionLocalProvider(value: ProvidedValue<*>, content: @Composable () -> Unit) {
-    // TODO(b/292224893): Switch this to the higher-performance startProvider()
-    currentComposer.startProviders(arrayOf(value))
+    currentComposer.startProvider(value)
     content()
-    currentComposer.endProviders()
+    currentComposer.endProvider()
 }
 
 /**
diff --git a/compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/CompositionLocalTests.kt b/compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/CompositionLocalTests.kt
index 1289e49..4144ccd 100644
--- a/compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/CompositionLocalTests.kt
+++ b/compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/CompositionLocalTests.kt
@@ -568,6 +568,44 @@
         }
     }
 
+    @Suppress("UNUSED_EXPRESSION")
+    @Test // Regression for b/292224893
+    fun testSingleInvalidatedProvider() = compositionTest {
+        val local1 = compositionLocalOf { 10 }
+        val local2 = compositionLocalOf { 20 }
+        val local3 = compositionLocalOf { 30 }
+        var state by mutableStateOf(0)
+
+        compose {
+            state
+            CompositionLocalProvider(local1 provides 11) {
+                state
+                CompositionLocalProvider(local2 provides 22) {
+                    state
+                    CompositionLocalProvider(local3 provides 33) {
+                        state
+                        assertEquals(11, local1.current)
+                        assertEquals(22, local2.current)
+                        assertEquals(33, local3.current)
+                    }
+                    assertEquals(11, local1.current)
+                    assertEquals(22, local2.current)
+                    assertEquals(30, local3.current)
+                }
+                assertEquals(11, local1.current)
+                assertEquals(20, local2.current)
+                assertEquals(30, local3.current)
+            }
+            assertEquals(10, local1.current)
+            assertEquals(20, local2.current)
+            assertEquals(30, local3.current)
+        }
+
+        state++
+
+        advance()
+    }
+
     @OptIn(ExperimentalCoroutinesApi::class)
     @Test
     fun testProvideAllLocals() = compositionTest {