Lesson 2
Reading Compose source as evidence
Use declarations, producers, consumers, tests, and history to bound an internals claim.
Status: The reading method is Durable . Conclusions about the pinned files are Version-specific . A test proves its inputs, source set, target, and assertions. It does not prove every private detail forever.
Outcome
When you investigate one Compose mechanism, you should be able to say:
- where the protocol is declared;
- which compiler code produces it;
- which runtime code consumes it;
- which test observes it; and
- what history says about its scope.
This prevents a plausible explanation from becoming an unearned guarantee.
Start with a claim, not a class name
Searches for startRestartGroup often produce this sentence:
Compose creates a restart group around every composable.
That sentence hides several questions. Is the name a public contract? Who emits the call? Do all consumers implement it the same way? Which test covers it? Is the behavior current or transitional?
Use a source walk to answer them in order.
Build an evidence graph
flowchart TD
Interface[Protocol declaration] --> Producer[Compiler producer]
Producer --> Consumer[Runtime consumer]
Consumer --> Tests[Runtime tests]
Interface --> History[Pinned history]
Tests --> Conclusion[Bounded conclusion]
History --> ConclusionRead the arrows as questions: what does the runtime ask for, who emits it, how do consumers interpret it, what do tests observe, what changed, and what bounded conclusion follows?
Know what each source set can prove
| Source set | Strong use | Boundary |
|---|---|---|
commonMain | Shared protocol and implementation | Not every platform integration or public API status |
nonEmulatorCommonTest | Runtime behavior and edge cases | Not every workload or platform |
androidInstrumentedTest | Android/device integration | Not common-runtime behavior everywhere |
Compiler lower | How source becomes runtime calls | Not runtime behavior by itself |
| Compiler test data | Golden output and compiler checks | Not a universal rule beyond its inputs |
runtime/design | Intent and historical vocabulary | Not current behavior when code differs |
| Benchmarks | Maintainer-selected measurements | Not application-wide causality |
The pinned runtime source tree and Compose compiler tree are maps, not conclusions.
A four-stop source walk
Use startRestartGroup as a small exercise.
1. Read the protocol
Open Composer.kt. startRestartGroup(key) is a compiler-facing protocol method. Its KDoc describes a source-keyed group that can be recomposed on demand. This establishes the contract and intended role.
It does not prove that every composable gets one, that keys are globally unique, or that every compiler version emits the same shape.
2. Find the producer
Open the pinned ComposableFunctionBodyTransformer.kt. Search for the generated start and end group calls. This ties the runtime protocol to compiler lowering.
It does not prove an exact dirty-mask layout or that every body is restartable. Those need transformer conditions and compiler test data.
3. Compare consumers
The pinned runtime has separate implementations in GapComposer.kt and LinkComposer.kt. The protocol can stay common while storage differs. The link-buffer flag is disabled by default at this revision, so teach that path as Experimental
, not as the universal implementation.
4. Narrow with tests and history
Read runtime restart tests for the behavior they actually assert. Then inspect pinned file history to learn whether a method or implementation is new, renamed, or transitional. History explains evolution; current code and tests decide the current claim.
A repeatable command set
From clean, pinned checkouts:
ANDROIDX=5e647f344a6a600b7342f43f2203d22bb82ca48a
KOTLIN=a1ab72da08c7cc2acca226db6193ea38d988e253
git -C /tmp/support grep -n "startRestartGroup" -- \
compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime
git -C /tmp/kotlin grep -n "startRestartGroup" -- \
plugins/compose/compiler-hosted
git -C /tmp/support grep -n "skip" -- \
compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/RestartTests.kt
The commands establish provenance; read the surrounding code and test assertions too.
Check yourself
Rewrite this claim so it matches the evidence:
Compose creates a restart group around every composable.
A good answer names the protocol, pins the compiler/runtime observation, and avoids universal language.
Source notes
| Claim | Direct evidence | Status |
|---|---|---|
Composer exposes a restart-group protocol | Composer.kt | Durable
Version-specific |
| The compiler plugin emits the protocol at the pinned revision | ComposableFunctionBodyTransformer.kt | Version-specific |
| Gap and link composers are distinct consumers | GapComposer.kt and LinkComposer.kt | Version-specific
Experimental |
| Tests bound restart and skip claims | RestartTests.kt | Version-specific |
| History is context, not a replacement for current code | Pinned Gitiles Composer history | Durable |
Freshness
Refresh this lesson when lowering moves, the Composer protocol changes, a consumer is added or removed, the link-buffer flag changes default, or restart tests are renamed. Re-pin both repositories before updating a conclusion.
Finished this lesson?
Your progress stays only in this browser.