Skip to main content

choose_indent_source

Function choose_indent_source 

Source
pub fn choose_indent_source(fresh: bool) -> IndentSource
Expand 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:

  1. It is far too slow to sit on the keystroke path. The indent_reparse sweep 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, where benchmarks.md warns 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.

  2. 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 ERROR node with no block structure, so the engine declines and the lexical bridge answers anyway. The expensive branch would usually spend milliseconds to return None.

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.