Repository navigation
fix(hy-check): reject untyped nil local declarations (fixes #672) - #691
dezzy-music wants to merge 1 commit into
Conversation
234c6d9 to
7273bde
Compare
…l declarations (N1 untyped leg) Merge pr-673 (milkingndb-oss, fixes #672): reject untyped nil local declarations — HYB-E4003, the N1 untyped leg (var x = nil / x := nil / let x = nil / a, b := nil, 1 / var _ = nil, incl. closure/loop/match-arm bodies) Live on main (probed 0ca08c2, go1.26.9 twin): all ten spellings hyb-check ACCEPT with 0 diagnostics, then go build fails 'use of untyped nil in variable declaration'. The N1 ascribed-nil check was gated on 'if let Some(t) = &l.ty' at both local-decl sites (loans.rs process_local + closures.rs check_stmt_boundaries); untyped decls fell through uninspected. Fix (PR verbatim): untyped-nil else-leg at both sites emitting registered HYB-E4003 (nil-safety, rule N, tier0 N1); local const c = nil stays E6003's locus (#640), no double-fire. Verified on merge c5126b0+pr-673: unit suite untyped_nil_decl.rs 13/13 (4 spellings, closure/loop/match-arm bodies, blank ident; controls: ascribed error-nil, bare nil as call arg/compare, zero-value decls, const-nil non-double-fire) — all ten probe spellings REJECT HYB-E4003; controls keep verdicts (var e error = nil ACCEPT, zero-value decls ACCEPT, f(nil)/ch==nil ACCEPT, var s []int = nil still E4001); corpus 80/80 (new fixture untyped-nil-decl-reject.hy, VERDICTS.md entry, parse_all 79->80); differential FULL 23 accept + 57 reject; cargo --workspace 1168/0; #524 Go-twin float matrix re-verified intact (const 1.0/0.0 REJECT E6001 x2, _ = 1.0/0.0 REJECT, runtime x/0.0 ACCEPT x3); CI green on head 17ff816 (quick+compiler). Credit: milkingndb-oss (this take: corpus fixture + registry date bump + E6003-scope control). Dezzy-music's parallel take #691 (same fix, emit helper emit_untyped_nil_error) — its two extra shapes (if-body and if-init untyped nil) land in the follow-up integration commit; credit to both authors per duplicate-family rule.
|
Landed — thank you @dezzy-music. Your take is correct and its two unique shapes are carried; the duplicate-family rule kept one landing (same defect, same fix, same three check-site hunks as #673). Landed fix: #673 (milkingndb-oss) merged server-side as 7aaf193 — registered Per-take verification on main after the landing (live-bypass probe, was LIVE before — all ten accepted with 0 diagnostics then failed
False-positive guards hold: Credit: dezzy-music (this take + the two carried shapes) and milkingndb-oss (landed take #673, corpus registration). Closing as duplicate-fixed; issue #672 tracks the defect. |
Fixes #672
Problem
Declaring a variable initialized to bare
nilwithout a declared type (var x = nil,x := nil,let x = nil,a, b := nil, 1,var _ = nil, or inside closure/loop/if bodies) passedhyb checkwith 0 diagnostics and emitted Go that failedgo build:This violates the accepted-implies-buildable contract (C5a, rule
BUILDABLE/N1).The gap was that the N1 nil check at both local-declaration check sites (
hy-check/src/loans.rsprocess_localandhy-check/src/closures.rscheck_stmt_boundaries) was gated behindif let Some(t) = &l.ty. Whenl.ty.is_none(), barenilpassed through uninspected.Solution
HYB-E4003):HYB-E4003(untyped-nil-declaration) under categorynil-safety, severityerror, ruleN, tier0_rule_idN1incompiler/crates/hy-diag/data/diagnostics.json.sendability.rs,loans.rs,closures.rs):emit_untyped_nil_errorhelper inChecker(sendability.rs).loans.rs(process_local) andclosures.rs(check_stmt_boundaries), added anelse if l.kind != LocalKind::Const && Checker::is_nil_literal(value)branch whenl.ty.is_none().const c = nilto the E6003 constant-expression guard (issue Soundness & buildability gaps inmake/newshape resolution, closure builtin validation, barechan Texpressions, and file-levelconstforward references #640) as Go reportsnil is not constantthere.var e error = nil(ascribederror) continues to accept.var ch chan int/var s []int(zero-value declarations without initializer) continue to accept.ch == nil/f(nil)(comparisons and call arguments) continue to accept.var s []int = nil) continues to reject withHYB-E4001.compiler/crates/hy-check/tests/untyped_nil_decl.rscovering all 14 test cases (all declaration spellings, closure bodies, loop bodies, if-inits, match arms, blank identifiers, and controls).tests/checker-corpus/untyped-nil-decl-reject.hypinningREJECT N1 [HYB-E4003].Verification
cargo test --manifest-path compiler/Cargo.toml --test untyped_nil_decl: 14 passed, 0 failed.cargo test --manifest-path compiler/Cargo.toml -p hy-check: all passed, 0 failed.cargo test --manifest-path compiler/Cargo.toml -p hy-diag: 8 passed, 0 failed.python tools/corpus_harness.py: 80/80 verdict agreement, tripwire not fired.python tools/check_conflict_markers.py: conflict markers: none.