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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//! Thread-local counters that make an invisible optimization testable.
//!
//! Several 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 gated. 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.
//!
//! # Two crates, one macro
//!
//! `big-code-analysis` declares counters of its own (in its `ops`,
//! `wire` and `spaces` walks) with the same macro, which is why it is
//! `#[macro_export]`ed. The accessor's gate is a parameter because the
//! two crates need different ones: a counter declared *here* must also be
//! readable by the root crate's tests, which see this crate as an
//! ordinary dependency (no `cfg(test)`), so it opens under the
//! `test-support` feature as well.
/// Declares a thread-local observation counter as a module: a private
/// `Cell`, an unconditional `record()`, and a gated `observed()`.
///
/// Takes the module's name and, optionally, the `cfg` predicate that
/// gates the accessor (`cfg(test)` when omitted). 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 observation_counter as counter;