1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
//! Thread-local counters that make an invisible optimization testable.
//!
//! Several of this crate's optimizations change no output at all:
//! reusing one `tree_sitter::Parser` per thread (#1118), skipping a
//! space-kind lookup on a node that opens no space (#1110), serializing
//! `Ops` through a borrowed projection rather than an owned clone
//! (#1110), deferring the modeline scan behind a resolving extension
//! (#1111). Every assertion on the *result* of those paths holds just as
//! well once the optimization is reverted, so a revert is silent unless
//! something counts the work.
//!
//! # The invariant
//!
//! The counter and the function that bumps it are **unconditional**;
//! only the accessor is `#[cfg(test)]`. Gating the counter itself would
//! leave the test observing a build production never ships — the counted
//! branch compiled under `cfg(test)` and the shipped one under nothing —
//! which is the exact failure these counters exist to catch. Four sites
//! grew that rule independently and each stated it in prose; [`counter`]
//! makes it structural instead, emitting the three items together so the
//! wrong one cannot be gated.
//!
//! The cost is one `Cell` increment on a path that already does far more
//! (building a parser, classifying a node, projecting a whole tree),
//! which is why it is affordable to leave in the shipped build.
/// Declares a thread-local observation counter as a module: a private
/// `Cell`, an unconditional `record()`, and a `#[cfg(test)] observed()`.
///
/// Takes the module's name and nothing else. It deliberately carries no
/// narrative — *which* optimization a counter observes, and why no
/// assertion on the output can distinguish it, belongs in a comment
/// above each invocation.
///
/// A module rather than three free items so a call site names the
/// counter once (`parsers_built::record()`), which keeps the invocation
/// to one line and leaves no room for the recorder and the accessor to
/// drift apart.
pub use counter;