pub fn choose_indent_source(fresh: bool) -> IndentSourceExpand description
The staleness decision (design §5), as a pure function so the policy is testable without racing the reparse worker.
§Why there is no synchronous-reparse branch
The design specified three branches, the middle one being “stale but under a byte budget ⇒ re-parse synchronously, then query”. It was built, benched, and deleted on the evidence:
-
It is far too slow to sit on the keystroke path. The
indent_reparsesweep measured 1.9 ms at 16 KB, 7.6 ms at 64 KB and 15.4 ms at 129 KB — on an Apple-silicon dev box, wherebenchmarks.mdwarns typical user hardware runs 2–5× slower. A budget generous enough to be useful is a budget that misses frames; one tight enough to be safe covers only files small enough for the question not to matter. -
It buys almost nothing even when affordable. The snapshot is stale precisely just after an edit — which is exactly when the code is half-typed, and a fresh parse of half-typed code yields an
ERRORnode with no block structure, so the engine declines and the lexical bridge answers anyway. The expensive branch would usually spend milliseconds to returnNone.
Human typing is ~100 ms between keystrokes and the off-thread
reparse lands in single-digit milliseconds for ordinary files, so
the stale window is narrow to begin with. Falling straight to the
lexical bridge costs a wrong-by-one indent in a rare window,
recoverable with the next keystroke or =; the reparse cost a
dropped frame. Paramount #1 decides it.
§2026-08-16: that argument only became true today
The paragraph above rests on the stale window being RARE. It wasn’t.
tree_levels_for_new_line’s freshness check asked
reparsed_from_version() == text_version(), and an incremental
reparse can never satisfy that — so the window was not narrow, it was
permanent: every keystroke after the first edit took the Lexical
branch, for the rest of the session. The engine benched in IN.2 was
running approximately never.
The check now asks lattice_syntax::SyntaxSnapshot::tree_reflects,
which puts the reasoning above on the footing it always claimed to
have. The conclusion is unchanged and the sync-reparse branch stays
deleted — but it is worth recording that the evidence for deleting it
was gathered against a gate that was sending everything to the
fallback anyway.