The globals registry (global_names) was last-wins across modules with no
per-importer gate: any module's bare K could read/write/type against an
unrelated module's same-named global (hash.sx's K table hijacked every
user K once std's namespace tail pulled hash into the program), and an
own const of an unsupported shape borrowed another module's const and
panicked at the unresolved-type tripwire.
- var_decl joins RawDeclRef: module globals are selectable raw authors.
- selectGlobalAuthor (the globals analogue of F2's selectModuleConst):
own author wins, one flat-visible author resolves, >=2 distinct flat
authors diagnose loudly, authored-but-not-visible diagnoses, and a
compiler-synthesized global (no raw author) emits untracked. A var_decl
author whose per-source registration was deduped at flat-merge (two
modules declaring the same extern symbol) serves the symbol's
registration.
- All bare-identifier global sites route through it: value read, addr-of,
assignment (store + compound), lvalue address, fn-ptr call, call param
typing, and expression type inference.
- selectModuleConst gains .own_opaque: an own const author with no
materialized per-source value (e.g. an array '::' const) blocks
borrowing another module's same-named const — the read diagnoses
cleanly instead of panicking.
- The fn-as-VALUE arm admits raw-facts-only authors: an own fn whose name
a flat-merge collision dropped from the global decl list (first-wins)
now resolves via author selection for func_ref/closure/Any shapes too.
Regressions: examples 0835 (own const vs flat array global), 0836 (main
const vs namespaced array global, incl. inference), 0837 (own array
const never borrows cross-module — clean unresolved).
globalInitValue had no unary_op arm, so g : s64 = -1; fell into the
catch-all 'must be initialized by a compile-time constant' even though
constExprValue already folds negate(literal) for the module-const
identifier route. The new arm routes through constExprValue and applies
the direct-literal rules to the folded value: checkIntLiteralFits on
ints (g : s8 = -300 gets the range diagnostic), and a negated float at
an integer global narrows only when integral (-4.0 folds to -4, -4.5
errors). Binary-op initializers keep the specific non-constant
diagnostic.
Regression: examples/0175-types-negative-literal-global.sx.
checkIntLiteralFits range-checks a literal against its integer target
(builtins + custom widths via intLiteralRange; width-64 types skip —
every representable literal is a legal bit pattern there) and diagnoses
with the type's range and an xx/cast hint. Wired into the .int_literal
arm (covers decls, assignments, call args, struct-literal fields),
lowerStructConstant, and globalInitValue.
A negated literal now folds to a single constant so -128 range-checks
as -128 rather than as an out-of-range +128 intermediate. An explicit
xx operand skips the check — truncation stays available on request
(cast(T) was already exempt: its value arg lowers without the target).
examples/0300-closures-lambda.sx pinned 133 wrapping to -3 through an
s3 param — the exact class this outlaws; updated to a fitting value.
Found during the fix and filed separately: issue 0113 (negated-literal
global initializers rejected as non-constant; pre-existing).
Regressions: examples/1156-diagnostics-int-literal-out-of-range.sx,
examples/0174-types-int-literal-boundaries.sx.
Sweep all src/**.zig comments that cite resolved issues (issue NNNN /
fix-NNNN / KB-N): the invariant or mechanism each comment states is
kept; the historical citation is dropped, per the no-conclusion-comments
rule. Pure-history parentheticals are removed outright. References to
the 16 still-open issues (0030, 0041-0056) are untouched, as are test
NAMES carrying regression provenance (matching the sanctioned
"Regression (issue NNNN)" example-header convention).
Also removes the issues/0019-import-non-transitive-c-scope/ fixture dir
— the issue is superseded and its behavior is covered by
examples/0706-modules-import-non-transitive.sx (the .md writeup stays).
issues/0030's repro .sx stays: that issue is an open feature request.
Gate: zig build OK; zig build test 426/426; run_examples 541/0; zero
expected/ snapshot churn.
Review follow-up to the ARCH-B split (comment/import hygiene only, no
code changes):
- Section banners that travelled to the wrong file with the B1-B8 cuts
are reworded to describe the section that actually follows (e.g.
stmt.zig's trailing "Expression lowering", expr.zig's "Control flow"
before lowerChainedComparison) or deleted where nothing follows
(4 trailing-at-EOF banners). ffi.zig's facade note no longer claims
the IMP builders "stay here" (they live in lower/objc_class.zig);
protocol.zig's namespace-lookup banner now points at
pack.zig:resolvePackProjection for the orchestrator.
- lower.zig's two lower/expr.zig alias blocks (B8.1 + B8.2 appends)
merged into one.
- 448 unused header decls pruned from the 15 lower/*.zig files (each
had inherited lower.zig's full import block; pruned to fixpoint so
cascading type-extraction consts went too).
Gate: zig build OK; zig build test 426/426; run_examples 541/0; zero
expected/ snapshot churn.