Skip to content

check: literal-defaulting cleanup follow-ups (post #9605)#9673

Open
jaredramirez wants to merge 16 commits into
mainfrom
jared/literal-defaulting-cleanup
Open

check: literal-defaulting cleanup follow-ups (post #9605)#9673
jaredramirez wants to merge 16 commits into
mainfrom
jared/literal-defaulting-cleanup

Conversation

@jaredramirez

@jaredramirez jaredramirez commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

Follow-up cleanup to #9605 ("check: lots of literal things"), driven by a multi-pass review (correctness, duplication, and a local-optimum/architecture audit). Sixteen well-scoped commits, each behavior-preserving except the first (a latent bug fix). No snapshots were harmed in the making of this PR

Correctness

  • fix(emit): parenthesize negative typed numerals under unary operatorsunaryReceiverNeedsParens only guarded e_num_from_numeral, so a unary op over a negative e_typed_num_from_numeral re-emitted as --5.U8 (re-tokenizes as binary minus). Merged the two from-numeral arms; added a round-trip unit test.

Duplication squashes (Check.zig)

  • extract collectConstraintSignatureReachable — the signature-footprint walk was copy-pasted in boundaryDefaultLeaksIntoSignature and runLiteralDefaultingRounds; these must agree or a literal could be partitioned non-interfering yet warned.
  • share numeral-probe digit-fit and verify loopstryCommitNumeralCandidate and commitLiteralGroupDefault now call shared rangeNumeralDigitsFit / candidateSatisfiesRangeConstraints instead of hand-synced copies.
  • centralize boundary-leak warning bracketing — new commitGatheredGroup, symmetric to commitGatheredLiteral, collapses the inlined before/commit/after warning dance.

Consolidation

  • derive CheckedStaticDispatchConstraint flat fields via accessors — drop the redundant binop_negated/num_literal (re-derived from origin at 5 sites) in favor of binopNegated()/numeralInfo(), finishing the consolidation the PR began on the type-store side.

Architecture audit findings

  • single source of truth for binding powers — RocEmitter kept a hand-synced parallel copy of the parser's binding-power table (its comment falsely claimed it "mirrored exactly"; the numbers were actually off-by-2). A parser precedence change could have silently made re-emitted operator expressions reparse to a different tree. The emitter now maps Binop.Op → Token.Tag and looks up the parser's one table, and a comptime assertion enforces that every Binop.Op resolves to a token with a defined binding power (so the lookup's .? can never panic — a bad future mapping becomes a compile error).
  • centralize the literal-kind tie-breaknumeral > quote > interpolation was replicated at three sites synced only by a doc comment; now one StaticDispatchConstraint.dominantLiteralKind kernel.
  • buffer .eql edges in the generalization-boundary scandefaultLiteralsAtGeneralizationBoundary re-scanned the whole module constraint list each fixpoint round; now collects the .eql edges into a front-loaded reusable buffer once per call.

Tidy-ups

  • probe bench counters → per-instance + debug-only — moved off process-global pub vars onto Check fields, gated every increment behind comptime std.debug.runtime_safety so release builds compile them out to a true no-op.
  • SurfaceOrigin encode/decode comptime guard + round-trip test; TestEnv.initReportBuilder helper (collapsing 6 sites, hoisting one out of a loop); stale doc-comment fixes.
  • Lifts all inline allocations to the root struct in Check for predictable memory use

Verification

Every commit was implemented and independently reviewed (spec + code-quality) per task, then a final holistic review of the whole stack. Each behavior-preserving change asserts zero test/snapshots drift after regeneration. Full stack: 2608 Zig unit tests pass, multi-backend eval passes, zero snapshot drift. (The binding-power comptime guard is compile-time-checked and adds no runtime behavior.)

Note: local zig build minici fails only in build-coverage-tools (the vendored kcov tool can't find system libs z/curl in this environment) — unrelated to these changes and identical on main.

🤖 Generated with Claude Code

@jaredramirez jaredramirez self-assigned this Jun 16, 2026
@jaredramirez jaredramirez force-pushed the jared/literal-defaulting-cleanup branch 5 times, most recently from 7ce0317 to e4eb79e Compare June 17, 2026 12:38
@jaredramirez jaredramirez marked this pull request as ready for review June 17, 2026 13:48
@jaredramirez jaredramirez enabled auto-merge June 17, 2026 13:48
@Anton-4

Anton-4 commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

No snapshots were harmed in the making of this PR

😄

@Anton-4 Anton-4 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice and clean :)

@jaredramirez jaredramirez force-pushed the jared/literal-defaulting-cleanup branch 8 times, most recently from 70d9be1 to 1a06357 Compare June 18, 2026 18:20
jaredramirez and others added 9 commits June 18, 2026 14:20
unaryReceiverNeedsParens only guarded e_num_from_numeral; a unary
operator over a negative e_typed_num_from_numeral re-emitted as --5.U8,
which re-tokenizes as binary minus. Merge the two from-numeral arms.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ia accessors

Drop the redundant binop_negated/num_literal fields (re-derived from
origin at 5 clone sites) in favor of binopNegated()/numeralInfo()
accessors, matching types.Origin.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The signature-footprint walk was copy-pasted in
boundaryDefaultLeaksIntoSignature and runLiteralDefaultingRounds; these
must agree or a literal could be partitioned non-interfering yet warned.
One helper, one source of truth.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extract rangeNumeralDigitsFit and candidateSatisfiesRangeConstraints so
the single-literal and group defaulting probes call one implementation
of the precheck and phase-2 verify instead of hand-synced copies.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…p default

The multi-driver else-arm of runLiteralDefaultingRounds re-implemented the
before/commit/after warning bracketing that commitGatheredLiteral owns for
the single case. Introduce commitGatheredGroup, symmetric to
commitGatheredLiteral, so the else-arm shrinks to one call.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remove the dangling doc comment for a deleted interpolation predicate and
update from_numeral/from_quote references to the from_literal + LiteralKind
representation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collapse six identical 9-arg ReportBuilder.init call sites into a helper
and stop rebuilding the report builder per problem in assertTypeErrorMsgs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a comptime assertion pinning surface_origin_binop_offset to the unit
tag count and a round-trip test over all SurfaceOrigin forms, so a future
unit variant can't silently collide with the binop range.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move bench_probe_attempts/bench_probe_refuted from process-global pub vars
to Check fields, and gate increments + their assertion test behind
comptime std.debug.runtime_safety so release builds compile them out to a
true no-op. Removes global mutable state and the hot-path cost in release.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jaredramirez and others added 7 commits June 18, 2026 14:20
…Kind

The numeral>quote>interpolation precedence was replicated in
varLiteralKind, flexLiteralDefaultKind, and numericDefaultPhaseForConstraints,
synced only by a doc comment. One kernel on StaticDispatchConstraint; each
site keeps its own surrounding logic.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
RocEmitter kept a hand-synced parallel binding-power table (comment falsely
claimed it mirrored the parser 'exactly'); a parser precedence change could
silently make re-emitted operator expressions reparse to a different tree.
Make the parser the single owner and map Binop.Op to its token to look up
the one table.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
defaultLiteralsAtGeneralizationBoundary re-scanned the whole module
constraint list on every fixpoint round. Collect the .eql edges into a
front-loaded reusable buffer once per call and iterate that instead, so
the fixpoint costs rounds*eql_edges rather than rounds*all_constraints.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Promote the 8 runLiteralDefaultingRounds buffers and 3
commitLiteralGroupDefault buffers to reused Check fields, matching the
existing boundary_* front-loaded scratch. Each is cleared at the start of
its step/use; the step-4 cascade (which can re-enter the function) reads
none of them, so a shared field is safe under that reentrancy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Promote the unifyMatchAltPatternBindings and payload-emptiness scratch
buffers to reused Check fields. Each buffer is filled then consumed by a
pure exhaustive.* call or non-recursive helper, so the owning function is
never re-entered while the buffer is live.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
validateRecordRow/validateTagUnionRow recurse through nested record/tag
types while their duplicate-name set is live, so a shared field would
clobber the outer frame. Use a per-frame stackFallback (stack-backed,
heap fallback on overflow), matching the arg_vars_sfa pattern.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Promote the external_pinnable AutoHashMap to a reused Check field,
matching its already-front-loaded siblings (pinnable_vars,
reported_dispatch_vars, pinnable_spine_visited) in the same one-shot
ambiguity sweep. The platform-hosted-section maps stay local: that
section only runs for platform modules (genuinely may-not-run) and its
two maps own their keys.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jaredramirez jaredramirez force-pushed the jared/literal-defaulting-cleanup branch from 1a06357 to 53f6b1c Compare June 18, 2026 18:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants