Repository: cashapp/redwood
Pull request #597 (2022-12-06 17:47:15)

Migrate children tag to value class with signed storage
Refs #418 


Patch:
diff --git a/redwood-cli/src/main/kotlin/app/cash/redwood/generator/diffConsumingGeneration.kt b/redwood-cli/src/main/kotlin/app/cash/redwood/generator/diffConsumingGeneration.kt
index 7345461e2..f5607f8f4 100644
--- a/redwood-cli/src/main/kotlin/app/cash/redwood/generator/diffConsumingGeneration.kt
+++ b/redwood-cli/src/main/kotlin/app/cash/redwood/generator/diffConsumingGeneration.kt
@@ -34,7 +34,6 @@ import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
 import com.squareup.kotlinpoet.PropertySpec
 import com.squareup.kotlinpoet.TypeName
 import com.squareup.kotlinpoet.TypeSpec
-import com.squareup.kotlinpoet.U_INT
 import com.squareup.kotlinpoet.asTypeName
 
 /*
@@ -337,13 +336,13 @@ internal fun generateDiffConsumingWidget(schema: Schema, widget: Widget, host: S
           addFunction(
             FunSpec.builder("children")
               .addModifiers(OVERRIDE)
-              .addParameter("tag", U_INT)
+              .addParameter("tag", Protocol.ChildrenTag)
               .returns(RedwoodWidget.WidgetChildrenOfW.copy(nullable = true))
               .apply {
                 if (childrens.isNotEmpty()) {
-                  beginControlFlow("return when (tag)")
+                  beginControlFlow("return when (tag.value)")
                   for (children in childrens) {
-                    addStatement("%LU -> widget.%N", children.tag, children.name)
+                    addStatement("%L -> widget.%N", children.tag, children.name)
                   }
                   beginControlFlow("else ->")
                   addStatement("mismatchHandler.onUnknownChildren(%L, tag)", widget.tag)
diff --git a/redwood-cli/src/main/kotlin/app/cash/redwood/generator/diffProducingGeneration.kt b/redwood-cli/src/main/kotlin/app/cash/redwood/generator/diffProducingGeneration.kt
index 156e24d42..45c6ad859 100644
--- a/redwood-cli/src/main/kotlin/app/cash/redwood/generator/diffProducingGeneration.kt
+++ b/redwood-cli/src/main/kotlin/app/cash/redwood/generator/diffProducingGeneration.kt
@@ -264,7 +264,11 @@ internal fun generateDiffProducingWidget(schema: Schema, widget: Widget, host: S
                     .addModifiers(OVERRIDE)
                     .getter(
                       FunSpec.getterBuilder()
-                        .addStatement("return bridge.widgetChildren(id, %LU)", trait.tag)
+                        .addStatement(
+                          "return bridge.widgetChildren(id, %T(%L))",
+                          Protocol.ChildrenTag,
+                          trait.tag,
+                        )
                         .build(),
                     )
                     .build(),
diff --git a/redwood-cli/src/main/kotlin/app/cash/redwood/generator/types.kt b/redwood-cli/src/main/kotlin/app/cash/redwood/generator/types.kt
index a737fb440..9e72b33d6 100644
--- a/redwood-cli/src/main/kotlin/app/cash/redwood/generator/types.kt
+++ b/redwood-cli/src/main/kotlin/app/cash/redwood/generator/types.kt
@@ -26,6 +26,7 @@ import com.squareup.kotlinpoet.TypeVariableName
 import com.squareup.kotlinpoet.UNIT
 
 internal object Protocol {
+  val ChildrenTag = ClassName("app.cash.redwood.protocol", "ChildrenTag")
   val Event = ClassName("app.cash.redwood.protocol", "Event")
   val EventTag = ClassName("app.cash.redwood.protocol", "EventTag")
   val EventSink = ClassName("app.cash.redwood.protocol", "EventSink")
diff --git a/redwood-protocol-compose/src/commonMain/kotlin/app/cash/redwood/protocol/compose/DiffProducingWidgetChildren.kt b/redwood-protocol-compose/src/commonMain/kotlin/app/cash/redwood/protocol/compose/DiffProducingWidgetChildren.kt
index 41454c6c9..9f91cbb25 100644
--- a/redwood-protocol-compose/src/commonMain/kotlin/app/cash/redwood/protocol/compose/DiffProducingWidgetChildren.kt
+++ b/redwood-protocol-compose/src/commonMain/kotlin/app/cash/redwood/protocol/compose/DiffProducingWidgetChildren.kt
@@ -16,12 +16,13 @@
 package app.cash.redwood.protocol.compose
 
 import app.cash.redwood.protocol.ChildrenDiff
+import app.cash.redwood.protocol.ChildrenTag
 import app.cash.redwood.protocol.Id
 import app.cash.redwood.widget.Widget
 
 internal class DiffProducingWidgetChildren(
   private val id: Id,
-  private val tag: UInt,
+  private val tag: ChildrenTag,
   private val bridge: ProtocolBridge,
 ) : Widget.Children<Nothing> {
   private val ids = mutableListOf<Id>()
diff --git a/redwood-protocol-compose/src/commonMain/kotlin/app/cash/redwood/protocol/compose/ProtocolBridge.kt b/redwood-protocol-compose/src/commonMain/kotlin/app/cash/redwood/protocol/compose/ProtocolBridge.kt
index 2681439d8..37b1a1ad6 100644
--- a/redwood-protocol-compose/src/commonMain/kotlin/app/cash/redwood/protocol/compose/ProtocolBridge.kt
+++ b/redwood-protocol-compose/src/commonMain/kotlin/app/cash/redwood/protocol/compose/ProtocolBridge.kt
@@ -16,6 +16,7 @@
 package app.cash.redwood.protocol.compose
 
 import app.cash.redwood.protocol.ChildrenDiff
+import app.cash.redwood.protocol.ChildrenTag
 import app.cash.redwood.protocol.Diff
 import app.cash.redwood.protocol.Event
 import app.cash.redwood.protocol.EventSink
@@ -83,7 +84,7 @@ public class ProtocolBridge : EventSink {
     nodes.remove(id)
   }
 
-  public fun widgetChildren(id: Id, tag: UInt): Widget.Children<Nothing> {
+  public fun widgetChildren(id: Id, tag: ChildrenTag): Widget.Children<Nothing> {
     return DiffProducingWidgetChildren(id, tag, this)
   }
 
diff --git a/redwood-protocol-compose/src/commonMain/kotlin/app/cash/redwood/protocol/compose/ProtocolRedwoodComposition.kt b/redwood-protocol-compose/src/commonMain/kotlin/app/cash/redwood/protocol/compose/ProtocolRedwoodComposition.kt
index ddc929901..12eaa3340 100644
--- a/redwood-protocol-compose/src/commonMain/kotlin/app/cash/redwood/protocol/compose/ProtocolRedwoodComposition.kt
+++ b/redwood-protocol-compose/src/commonMain/kotlin/app/cash/redwood/protocol/compose/ProtocolRedwoodComposition.kt
@@ -22,7 +22,7 @@ import androidx.compose.runtime.currentComposer
 import app.cash.redwood.compose.LocalWidgetVersion
 import app.cash.redwood.compose.RedwoodComposition
 import app.cash.redwood.compose.WidgetApplier
-import app.cash.redwood.protocol.ChildrenDiff
+import app.cash.redwood.protocol.ChildrenTag
 import app.cash.redwood.protocol.DiffSink
 import app.cash.redwood.protocol.Id
 import kotlinx.coroutines.CoroutineScope
@@ -38,7 +38,7 @@ public fun ProtocolRedwoodComposition(
   widgetVersion: UInt,
 ): RedwoodComposition {
   val bridge = factory.bridge
-  val root = DiffProducingWidgetChildren(Id.Root, ChildrenDiff.RootChildrenTag, bridge)
+  val root = DiffProducingWidgetChildren(Id.Root, ChildrenTag.Root, bridge)
   val applier = WidgetApplier(factory, root) {
     bridge.createDiffOrNull()?.let(diffSink::sendDiff)
   }
diff --git a/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/DiffConsumingNode.kt b/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/DiffConsumingNode.kt
index f66389e56..48c8f0e82 100644
--- a/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/DiffConsumingNode.kt
+++ b/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/DiffConsumingNode.kt
@@ -15,6 +15,7 @@
  */
 package app.cash.redwood.protocol.widget
 
+import app.cash.redwood.protocol.ChildrenTag
 import app.cash.redwood.protocol.EventSink
 import app.cash.redwood.protocol.Id
 import app.cash.redwood.protocol.PropertyDiff
@@ -47,7 +48,7 @@ public abstract class DiffConsumingNode<W : Any>(
    * If `null` is returned, the caller should make every effort to ignore these children and
    * continue executing.
    */
-  public abstract fun children(tag: UInt): Widget.Children<W>?
+  public abstract fun children(tag: ChildrenTag): Widget.Children<W>?
 
   public interface Factory<W : Any> {
     /**
diff --git a/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolBridge.kt b/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolBridge.kt
index 810d7eb6c..b4ca388a8 100644
--- a/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolBridge.kt
+++ b/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolBridge.kt
@@ -16,7 +16,7 @@
 package app.cash.redwood.protocol.widget
 
 import app.cash.redwood.protocol.ChildrenDiff
-import app.cash.redwood.protocol.ChildrenDiff.Companion.RootChildrenTag
+import app.cash.redwood.protocol.ChildrenTag
 import app.cash.redwood.protocol.Diff
 import app.cash.redwood.protocol.DiffSink
 import app.cash.redwood.protocol.EventSink
@@ -103,8 +103,8 @@ private class DiffConsumingProtocolRoot<W : Any>(
     throw AssertionError("unexpected: $diff")
   }
 
-  override fun children(tag: UInt) = when (tag) {
-    RootChildrenTag -> children
+  override fun children(tag: ChildrenTag) = when (tag) {
+    ChildrenTag.Root -> children
     else -> throw AssertionError("unexpected: $tag")
   }
 
diff --git a/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolMismatchHandler.kt b/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolMismatchHandler.kt
index 680413870..28a98e948 100644
--- a/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolMismatchHandler.kt
+++ b/redwood-protocol-widget/src/commonMain/kotlin/app/cash/redwood/protocol/widget/ProtocolMismatchHandler.kt
@@ -15,6 +15,7 @@
  */
 package app.cash.redwood.protocol.widget
 
+import app.cash.redwood.protocol.ChildrenTag
 import app.cash.redwood.protocol.PropertyTag
 import kotlin.jvm.JvmField
 
@@ -31,7 +32,7 @@ public interface ProtocolMismatchHandler {
   public fun onUnknownLayoutModifier(tag: Int)
 
   /** Handle a request to manipulate unknown children [tag] for the specified widget [kind]. */
-  public fun onUnknownChildren(kind: Int, tag: UInt)
+  public fun onUnknownChildren(kind: Int, tag: ChildrenTag)
 
   /** Handle a request to set an unknown property [tag] for the specified widget [kind]. */
   public fun onUnknownProperty(kind: Int, tag: PropertyTag)
@@ -48,8 +49,8 @@ public interface ProtocolMismatchHandler {
         throw IllegalArgumentException("Unknown layout modifier tag $tag")
       }
 
-      override fun onUnknownChildren(kind: Int, tag: UInt) {
-        throw IllegalArgumentException("Unknown children tag $tag for widget kind $kind")
+      override fun onUnknownChildren(kind: Int, tag: ChildrenTag) {
+        throw IllegalArgumentException("Unknown children tag ${tag.value} for widget kind $kind")
       }
 
       override fun onUnknownProperty(kind: Int, tag: PropertyTag) {
diff --git a/redwood-protocol/src/commonMain/kotlin/app/cash/redwood/protocol/protocol.kt b/redwood-protocol/src/commonMain/kotlin/app/cash/redwood/protocol/protocol.kt
index 3545e184e..3506d5485 100644
--- a/redwood-protocol/src/commonMain/kotlin/app/cash/redwood/protocol/protocol.kt
+++ b/redwood-protocol/src/commonMain/kotlin/app/cash/redwood/protocol/protocol.kt
@@ -63,13 +63,13 @@ public sealed class ChildrenDiff {
   public abstract val id: Id
 
   /** Identifies which group of children changed on the widget with [id]. */
-  public abstract val tag: UInt
+  public abstract val tag: ChildrenTag
 
   @Serializable
   @SerialName("insert")
   public data class Insert(
     override val id: Id,
-    override val tag: UInt,
+    override val tag: ChildrenTag,
     val childId: Id,
     val kind: Int,
     val index: Int,
@@ -79,7 +79,7 @@ public sealed class ChildrenDiff {
   @SerialName("move")
   public data class Move(
     override val id: Id,
-    override val tag: UInt,
+    override val tag: ChildrenTag,
     val fromIndex: Int,
     val toIndex: Int,
     val count: Int,
@@ -89,12 +89,8 @@ public sealed class ChildrenDiff {
   @SerialName("remove")
   public data class Remove(
     override val id: Id,
-    override val tag: UInt,
+    override val tag: ChildrenTag,
     val index: Int,
     val count: Int,
   ) : ChildrenDiff()
-
-  public companion object {
-    public const val RootChildrenTag: UInt = 1U
-  }
 }
diff --git a/redwood-protocol/src/commonMain/kotlin/app/cash/redwood/protocol/values.kt b/redwood-protocol/src/commonMain/kotlin/app/cash/redwood/protocol/values.kt
index ed63b7687..302b08859 100644
--- a/redwood-protocol/src/commonMain/kotlin/app/cash/redwood/protocol/values.kt
+++ b/redwood-protocol/src/commonMain/kotlin/app/cash/redwood/protocol/values.kt
@@ -34,3 +34,11 @@ public value class EventTag(public val value: Int)
 @JvmInline
 @Serializable
 public value class PropertyTag(public val value: Int)
+
+@JvmInline
+@Serializable
+public value class ChildrenTag(public val value: Int) {
+  public companion object {
+    public val Root: ChildrenTag = ChildrenTag(0)
+  }
+}
diff --git a/redwood-treehouse/src/hostMain/kotlin/app/cash/redwood/treehouse/EventListener.kt b/redwood-treehouse/src/hostMain/kotlin/app/cash/redwood/treehouse/EventListener.kt
index 636f9713e..58596387b 100644
--- a/redwood-treehouse/src/hostMain/kotlin/app/cash/redwood/treehouse/EventListener.kt
+++ b/redwood-treehouse/src/hostMain/kotlin/app/cash/redwood/treehouse/EventListener.kt
@@ -15,6 +15,7 @@
  */
 package app.cash.redwood.treehouse
 
+import app.cash.redwood.protocol.ChildrenTag
 import app.cash.redwood.protocol.PropertyTag
 import app.cash.zipline.Call
 import app.cash.zipline.CallResult
@@ -73,7 +74,7 @@ public abstract class EventListener {
   public open fun onUnknownChildren(
     app: TreehouseApp<*>,
     kind: Int,
-    tag: UInt,
+    tag: ChildrenTag,
   ) {
   }
 
diff --git a/redwood-treehouse/src/hostMain/kotlin/app/cash/redwood/treehouse/EventPublisher.kt b/redwood-treehouse/src/hostMain/kotlin/app/cash/redwood/treehouse/EventPublisher.kt
index 905fd06a7..8787dab25 100644
--- a/redwood-treehouse/src/hostMain/kotlin/app/cash/redwood/treehouse/EventPublisher.kt
+++ b/redwood-treehouse/src/hostMain/kotlin/app/cash/redwood/treehouse/EventPublisher.kt
@@ -15,6 +15,7 @@
  */
 package app.cash.redwood.treehouse
 
+import app.cash.redwood.protocol.ChildrenTag
 import app.cash.redwood.protocol.PropertyTag
 import app.cash.redwood.protocol.widget.ProtocolMismatchHandler
 import app.cash.zipline.Call
@@ -128,7 +129,7 @@ internal class EventPublisher(
       listener.onUnknownLayoutModifier(app, tag)
     }
 
-    override fun onUnknownChildren(kind: Int, tag: UInt) {
+    override fun onUnknownChildren(kind: Int, tag: ChildrenTag) {
       listener.onUnknownChildren(app, kind, tag)
     }
 


Test patch:
diff --git a/redwood-protocol-compose/src/commonTest/kotlin/app/cash/redwood/protocol/compose/ProtocolTest.kt b/redwood-protocol-compose/src/commonTest/kotlin/app/cash/redwood/protocol/compose/ProtocolTest.kt
index 610ccc11f..87e796ce4 100644
--- a/redwood-protocol-compose/src/commonTest/kotlin/app/cash/redwood/protocol/compose/ProtocolTest.kt
+++ b/redwood-protocol-compose/src/commonTest/kotlin/app/cash/redwood/protocol/compose/ProtocolTest.kt
@@ -21,7 +21,7 @@ import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.setValue
 import app.cash.redwood.compose.WidgetVersion
 import app.cash.redwood.protocol.ChildrenDiff
-import app.cash.redwood.protocol.ChildrenDiff.Companion.RootChildrenTag
+import app.cash.redwood.protocol.ChildrenTag
 import app.cash.redwood.protocol.Diff
 import app.cash.redwood.protocol.Event
 import app.cash.redwood.protocol.EventTag
@@ -86,10 +86,10 @@ class ProtocolTest {
     assertEquals(
       Diff(
         childrenDiffs = listOf(
-          ChildrenDiff.Insert(Id.Root, RootChildrenTag, Id(1), 1 /* row */, 0),
-          ChildrenDiff.Insert(Id(1), 1U, Id(2), 3 /* text */, 0),
-          ChildrenDiff.Insert(Id(1), 1U, Id(3), 1 /* row */, 1),
-          ChildrenDiff.Insert(Id(3), 1U, Id(4), 3 /* text */, 0),
+          ChildrenDiff.Insert(Id.Root, ChildrenTag.Root, Id(1), 1 /* row */, 0),
+          ChildrenDiff.Insert(Id(1), ChildrenTag(1), Id(2), 3 /* text */, 0),
+          ChildrenDiff.Insert(Id(1), ChildrenTag(1), Id(3), 1 /* row */, 1),
+          ChildrenDiff.Insert(Id(3), ChildrenTag(1), Id(4), 3 /* text */, 0),
         ),
         layoutModifiers = listOf(
           LayoutModifiers(Id(1), JsonArray(listOf())),
@@ -137,7 +137,7 @@ class ProtocolTest {
     assertEquals(
       Diff(
         childrenDiffs = listOf(
-          ChildrenDiff.Insert(Id.Root, RootChildrenTag, Id(1), 4 /* button */, 0),
+          ChildrenDiff.Insert(Id.Root, ChildrenTag.Root, Id(1), 4 /* button */, 0),
         ),
         layoutModifiers = listOf(
           LayoutModifiers(Id(1), JsonArray(listOf())),
diff --git a/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/DiffConsumingWidgetFactoryTest.kt b/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/DiffConsumingWidgetFactoryTest.kt
index 8cb6c8e65..a4340f503 100644
--- a/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/DiffConsumingWidgetFactoryTest.kt
+++ b/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/DiffConsumingWidgetFactoryTest.kt
@@ -16,6 +16,7 @@
 package app.cash.redwood.protocol.widget
 
 import app.cash.redwood.LayoutModifier
+import app.cash.redwood.protocol.ChildrenTag
 import app.cash.redwood.protocol.Event
 import app.cash.redwood.protocol.EventSink
 import app.cash.redwood.protocol.EventTag
@@ -197,7 +198,7 @@ class DiffConsumingWidgetFactoryTest {
     val button = factory.create(Id.Root, ThrowingWidgetChildren(), 4)!!
 
     val t = assertFailsWith<IllegalArgumentException> {
-      button.children(345432U)
+      button.children(ChildrenTag(345432))
     }
     assertEquals("Unknown children tag 345432 for widget kind 4", t.message)
   }
@@ -210,7 +211,7 @@ class DiffConsumingWidgetFactoryTest {
     )
 
     val button = factory.create(Id.Root, ThrowingWidgetChildren(), 4)!!
-    assertNull(button.children(345432U))
+    assertNull(button.children(ChildrenTag(345432)))
 
     assertEquals("Unknown children 345432 for 4", handler.events.single())
   }
diff --git a/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/ProtocolBridgeTest.kt b/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/ProtocolBridgeTest.kt
index 852cd5f85..ec634940f 100644
--- a/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/ProtocolBridgeTest.kt
+++ b/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/ProtocolBridgeTest.kt
@@ -16,7 +16,7 @@
 package app.cash.redwood.protocol.widget
 
 import app.cash.redwood.protocol.ChildrenDiff
-import app.cash.redwood.protocol.ChildrenDiff.Companion.RootChildrenTag
+import app.cash.redwood.protocol.ChildrenTag
 import app.cash.redwood.protocol.Diff
 import app.cash.redwood.protocol.Id
 import app.cash.redwood.widget.MutableListChildren
@@ -36,7 +36,7 @@ class ProtocolBridgeTest {
       childrenDiffs = listOf(
         ChildrenDiff.Insert(
           id = Id.Root,
-          tag = RootChildrenTag,
+          tag = ChildrenTag.Root,
           childId = Id.Root,
           kind = 4 /* button */,
           index = 0,
@@ -59,7 +59,7 @@ class ProtocolBridgeTest {
       childrenDiffs = listOf(
         ChildrenDiff.Insert(
           id = Id.Root,
-          tag = RootChildrenTag,
+          tag = ChildrenTag.Root,
           childId = Id(1),
           kind = 4 /* button */,
           index = 0,
diff --git a/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/ProtocolMismatchHandlerTest.kt b/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/ProtocolMismatchHandlerTest.kt
index faa52b1b2..0b8dff49e 100644
--- a/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/ProtocolMismatchHandlerTest.kt
+++ b/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/ProtocolMismatchHandlerTest.kt
@@ -15,6 +15,7 @@
  */
 package app.cash.redwood.protocol.widget
 
+import app.cash.redwood.protocol.ChildrenTag
 import app.cash.redwood.protocol.PropertyTag
 import kotlin.test.Test
 import kotlin.test.assertEquals
@@ -37,7 +38,7 @@ class ProtocolMismatchHandlerTest {
 
   @Test fun throwingUnknownChildren() {
     val t = assertFailsWith<IllegalArgumentException> {
-      ProtocolMismatchHandler.Throwing.onUnknownChildren(1, 2U)
+      ProtocolMismatchHandler.Throwing.onUnknownChildren(1, ChildrenTag(2))
     }
     assertEquals("Unknown children tag 2 for widget kind 1", t.message)
   }
diff --git a/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/RecordingProtocolMismatchHandler.kt b/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/RecordingProtocolMismatchHandler.kt
index e7e177c18..3e2d6c1a0 100644
--- a/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/RecordingProtocolMismatchHandler.kt
+++ b/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/RecordingProtocolMismatchHandler.kt
@@ -15,6 +15,7 @@
  */
 package app.cash.redwood.protocol.widget
 
+import app.cash.redwood.protocol.ChildrenTag
 import app.cash.redwood.protocol.PropertyTag
 
 class RecordingProtocolMismatchHandler : ProtocolMismatchHandler {
@@ -28,8 +29,8 @@ class RecordingProtocolMismatchHandler : ProtocolMismatchHandler {
     events += "Unknown layout modifier $tag"
   }
 
-  override fun onUnknownChildren(kind: Int, tag: UInt) {
-    events += "Unknown children $tag for $kind"
+  override fun onUnknownChildren(kind: Int, tag: ChildrenTag) {
+    events += "Unknown children ${tag.value} for $kind"
   }
 
   override fun onUnknownProperty(kind: Int, tag: PropertyTag) {
diff --git a/redwood-protocol/src/commonTest/kotlin/app/cash/redwood/protocol/ProtocolTest.kt b/redwood-protocol/src/commonTest/kotlin/app/cash/redwood/protocol/ProtocolTest.kt
index 7bcf7e3b9..3eedbcc42 100644
--- a/redwood-protocol/src/commonTest/kotlin/app/cash/redwood/protocol/ProtocolTest.kt
+++ b/redwood-protocol/src/commonTest/kotlin/app/cash/redwood/protocol/ProtocolTest.kt
@@ -44,9 +44,9 @@ class ProtocolTest {
   @Test fun diff() {
     val model = Diff(
       childrenDiffs = listOf(
-        ChildrenDiff.Insert(Id(1), 2U, Id(3), 4, 5),
-        ChildrenDiff.Move(Id(1), 2U, 3, 4, 5),
-        ChildrenDiff.Remove(Id(1), 2U, 3, 4),
+        ChildrenDiff.Insert(Id(1), ChildrenTag(2), Id(3), 4, 5),
+        ChildrenDiff.Move(Id(1), ChildrenTag(2), 3, 4, 5),
+        ChildrenDiff.Remove(Id(1), ChildrenTag(2), 3, 4),
       ),
       layoutModifiers = listOf(
         LayoutModifiers(