Two coupled capabilities on the road to the std restructure
(current/PLAN-STDLIB.md, issue 0114):
1. alias.Type.method() / alias.Type as a call head, alias.CONST, and
alias.Enum.variant now resolve — previously only alias.fn() and
type-position alias.Type worked. objectIsValue treats an
alias-rooted field_access as a type head; the call path strips the
alias to the existing Type.method machinery; lowerFieldAccess
resolves alias.CONST pinned to the target module and alias.Enum.x
as a typed enum literal; resolveTypeWithBindings resolves qualified
type_exprs pinned to the target.
2. The carry rule: namespaceAliasTarget resolves an alias from the
file's own edges first, then from DIRECT flat imports (one level),
diagnosing two distinct carried targets as ambiguous. All qualified
shapes work through a carried alias — the std.sx namespace tail
(mem.GPA.init() etc.) is now expressible.
Regression: examples/0831-modules-namespace-alias-carry.sx (direct +
carried, all seven shapes).
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.
xs[1..=3] (end inclusive), xs[0<..<4] (both exclusive), xs[..=2]
(prefix form with markers, implicit 0 start), xs[2<..] (open end,
exclusive start), and xs[..] (whole collection) — lowered as lo+1 /
hi+1 on the existing subslice op. Strings slice through the same path.
An explicit end marker requires an end expression, matching the
for-header rule.
Regression: examples/0052-basic-slice-range-bounds.sx.
lowerBreak/lowerContinue emitted a bare br, and the enclosing block's
emitBlockDefers — seeing the terminator — discarded the pending entries
on the assumption a return had already drained them. The breaking
iteration's defers were silently skipped, leaking whatever the cleanup
released.
Lowering.loop_defer_base records the defer-stack height at each loop's
body start (while / for / range-for, saved and restored alongside
break_target); break/continue drain non-onfail entries down to it in
LIFO order via the non-truncating emitLoopExitDefers before branching.
Truncation stays with the lexical block exits — the same entries still
belong to the fall-through path after the branch containing the break.
break/continue outside a loop now diagnose instead of no-op'ing.
Regression: examples/0049-basic-defer-break-continue.sx (for and while,
break and continue, nested-block LIFO drain).
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.
Verbatim relocation of the 30-method expression cluster (struct/array/
tuple/enum/tagged-enum literals, init blocks, field access on values and
types, optional chains, numeric limits, indexing, slicing, deref, force
unwrap, null coalesce) into src/ir/lower/expr.zig — one contiguous
1,372-line cut. 30 aliases on Lowering keep all call sites unchanged.
Nested StructConstInfo stays on Lowering (field type of
struct_const_map), flipped pub and reached via an alias const, alongside
headNameOfCallee.
Gate: zig build OK; zig build test 426/426; run_examples 541/0; zero
expected/ snapshot churn.