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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//! Module-namespace **root identity** (docs/decision-log.md 2026-08-04
//! "`std::` and libraries are PEER ROOTS of `story::`, not children of it";
//! docs/modules-spec.md §4; issue #2245, generalized to a set by #2251).
//!
//! `story::*` is the universe of what the project *author* provided.
//! `std::*` — and every future mounted library — is a top-level **peer**
//! of `story`, never a child of it: the module forest has several roots,
//! and a project's own tree is exactly one of them
//! (`brink_db::modules::native_module_path` mints `story::…` for an
//! ordinary project file and bare `std::…` for a file mounted under the
//! reserved `std/` key prefix — see that function's own doc).
//!
//! Once "which root is this?" is a structural fact about the module
//! *path itself* rather than a policy decided independently at each
//! reference site, "is this a reserved peer root?" collapses to one check:
//! does the module's leading segment appear in [`RESERVED_ROOTS`]? Before
//! this module existed, that check was reinvented identically in two
//! places — `brink-analyzer::resolve` and `brink-ir::lir::lower::decls` —
//! because `brink-ir` cannot depend on `brink-analyzer` (the reverse edge
//! is the real one: `brink-analyzer` already depends on `brink-ir`, per
//! this crate's own `symbols` module doc — "so that `brink-ir::lir` can
//! consume the resolved index without depending on `brink-analyzer`").
//! Defining the check here, in the substrate both already share, removes
//! the duplication rather than merely keeping it in sync by hand.
//!
//! # A set, not a single constant (#2251)
//!
//! #2245's fix (PR #2250) hardcoded exactly one peer root as a single
//! `&str` constant, even though the ruling above was stated generally
//! ("`std::` — and every future mounted library"). A single constant
//! cannot answer a question about a second peer without either
//! re-deriving the "which branch does this root take" logic by hand at
//! every call site (recreating the duplication #2245 deleted) or silently
//! falling through to the `story` branch — the original #2245 defect,
//! recurring. [`RESERVED_ROOTS`] is the set every such call site now
//! consults, so a second mounted library is a one-line data change here,
//! not a re-derivation anywhere else.
//!
//! This intentionally does **not** add a per-root visibility *policy* type
//! (an enum, a trait, a `ReservedRoot { name, policy }` struct) — that half
//! of #2251's ask is deliberately deferred, not delivered here. Note that
//! the membership check below is not policy-neutral: every consumer that
//! calls [`is_reserved_root_module`] now applies std's bare-name-fallback
//! exclusion to *any* member of [`RESERVED_ROOTS`], with no per-root
//! opt-out. That is a real decision, baked in by generalizing a single
//! `std`-specific check into a set-membership test — it is just not a
//! *differing* policy per root, because there is only one data point
//! (`std`) to generalize a difference from. A future root that needs
//! different visibility behavior than `std` still needs the policy type;
//! this module only gives it a name to add to the set.
/// The project's own root — the universe of what the story *author*
/// provided, as opposed to a mounted library (issue #2274, closing the
/// naming gap #2245/#2251 left on this side: every reserved peer root has
/// a named constant in [`RESERVED_ROOTS`], but the root the *rest* of a
/// project's files fall back to — `brink_db::modules::native_module_path`'s
/// default branch — stayed a bare `"story"` literal). Deliberately **not**
/// a member of [`RESERVED_ROOTS`]: that set answers "is this a mounted
/// library, not project-owned", and `story` is the opposite answer to that
/// question, not another entry in it.
pub const STORY_ROOT: &str = "story";
/// The standard library's reserved peer-root name — the one entry in
/// [`RESERVED_ROOTS`] that exists today (`brink_environment::mount_stdlib`'s
/// `std/…` source-key convention, turned into a module path by
/// `brink_db::modules::native_module_path`). Kept as its own public
/// constant rather than folded away into an unlabeled `RESERVED_ROOTS[0]`
/// index: today the only consumer that means "the std root" specifically,
/// not "any reserved root", is this module's own tests
/// (`reserved_roots_contains_exactly_std_today`), but that distinction —
/// naming one particular root versus testing set membership — is real even
/// with a single entry, and a public name is cheaper to keep than to add
/// back once a second root exists and something legitimately needs to
/// single `std` out from its peers.
pub const STD_ROOT: &str = "std";
/// The full set of reserved peer-root names (#2251, generalizing #2245's
/// single [`STD_ROOT`] constant). A structural constant, not a
/// project-config lookup — only `std` exists today; a future library
/// mount (any new `brink_environment::mount_*` producer) adds its own
/// entry here, so every consumer below (`native_module_path`,
/// [`is_reserved_root_module`], and the `Candidacy::Other` exclusion
/// sites in `brink-analyzer::resolve` / `brink-ir::lir::lower::decls`)
/// picks it up as data rather than needing a new hardcoded branch.
pub const RESERVED_ROOTS: & = &;
/// True when `module`'s leading `::`-segment names any reserved peer root
/// in [`RESERVED_ROOTS`] — `std` itself/its submodules today
/// (`std::conventions::screenplay`, …), and every future mounted library
/// once its root joins the set.
///
/// Generalizes the single-root `is_std_module` check #2245 shipped: every
/// caller of that function actually meant "is this a mounted-library
/// candidate, not project-owned" (the bare-name-fallback exclusion policy
/// applies identically to any reserved root, not specifically to `std`),
/// so the check generalizes along with the constant it was built on.
/// Pure root-identity check for one candidate root: `module`'s leading
/// `::`-segment is exactly `root` (not merely a textual prefix — see the
/// `stdlib`-vs-`std` test below).