Repository navigation
Fixes #1112: typed int values no longer satisfy float64 targets (untyped-constant clause across all 20 value positions) - #1447
Conversation
…64 targets — value positions route through an untyped-constant clause kinds_conflict's `(Float, Int) => false` arm exists solely for Go's untyped-constant conversion (`var f float64 = 1` builds), but the kind model cannot tell an untyped constant from an `int` variable, so `var y int = 3; var f float64 = y` (go build: `cannot use y ... value in ...`) passed every value position — the issue's 10 faces plus more call sites verified accept. Collector::value_conflicts(want, got, value) = kinds_conflict || (want Float && got Int && !is_untyped_constant(value)) now guards all 20 sites: typed init (1/2-value), struct literal field, fn args incl. the pointer-inner auto-& arm (2x2), method args (2x2), report_return_conflict (value expr threaded through its 4 callers), append, assign single/parallel, compound `+=` and `-=`/`*=`/`/=`, map index key, array/slice literal, map literal key/value (the dead const_int_value guards subsumed — this also fixes the pre-existing false reject of an untyped file const in an array literal), copy element kinds, plus a new narrow Stmt::Send check (`chan float64 <- typed int`; deliberately narrow so HYB-E3011's shape rules keep owning the other send pairs). is_untyped_constant: int/rune literals, `-x`, `a op b` over constants, and untyped const refs (file-level only when `ty` is absent; fn-local consts fail open as untyped). equality_kinds_conflict and conversion_kinds_conflict untouched — `1 == 1.0` and `float64(y)` stay legal. Validation: hy-check/tests/typed_int_float_coercion_issue_1112.rs (29 tests: 20 reject faces + 7 accept-control groups covering every classic untyped-constant shape); the issue's 10 repros plus make-chan/array probes all flip accept -> reject with HYB-E1002; corpus pin typed-int-into-float64-reject.hy, census 126 -> 127 across all 8 surfaces; corpus harness 127/127 (negative flip: exit 2 flipped / exit 0 restored); differential loop 40/40 accept + 87/87 reject; cargo test --workspace green except the pre-existing spec_t3_strings failure (reproduced on clean HEAD, reads SPEC-LANGUAGE.md's T3 fence — unrelated). Fixes limitlessprojects#1112. Credit: wminno's surface checklist in the issue; stale companions zidirahim617-del's PR limitlessprojects#1130 (partial: 3 sites + tests) and mhatipog's PR limitlessprojects#1117 — this PR supersedes both with full-site coverage.
…ssion-35: limitlessprojects#1419/limitlessprojects#1432/limitlessprojects#1439/limitlessprojects#1441 — disjoint files, census still 126)
|
Post-merge validation on Census coordination: #1428 and #1430 also bump 126 → 127 with their own pins — whichever lands last should rebase the count to 128/129 on all 8 surfaces (same pattern as the #906/#905 sibling take). |
…nd comparisons (fixes limitlessprojects#922) Root cause: check_binary_operands compared numeric FAMILIES, not concrete kinds — for `< <= > >=` and `+` the mismatch term was `lk.is_numeric() != rk.is_numeric()` (int and float64 are both numeric, so never mismatched), and `- * /` only checked kind membership. `x + f`, `x - f`, `x * f`, `x / f`, `x < f`, `f <= x` checked clean while go build refused each with `mismatched types int and float64` (GUARANTEES Row 13). Fix: a new Collector::numeric_adapt_conflict routes cross-kind operand pairs through Go's only implicit numeric conversion — untyped-constant adaptation — and emits HYB-E1002 when it cannot bridge them: - `1 + 2.5` (both untyped) and `f + 1` / `1 + f` (int const -> float64) keep building, including untyped `const` identifiers (`f + k`); - `x + f`, `f + x`, `x - f`, `x < f`, `f <= x`, and the untyped float const against a typed int (`x + 2.5`) are rejected; - `Define.untyped_const` (from LocalDecl.ty) distinguishes `const k = 1` (untyped) from `const k int = 1` (typed like a variable) for fn-local consts — the annotation was recorded but never consulted. Validation: new hy-check/tests/binop_operand_types_issue_922.rs 24/24 (15 reject faces + 9 accept controls); corpus pin binop-mismatched-numeric-reject.hy (REJECT BUILDABLE + HYB-E1002), census 126 -> 127 on all 7 surfaces; harness 127/127, tripwire not fired; negative flip: baseline upstream accepts the pin (126/127, pin FAILs) and restores to 127/127; differential 40/40 accept + 87/87 reject; cargo test --workspace green except the pre-existing local-CRLF spec_t3_strings failure (reproduces on clean HEAD). Harvest credit: stale companion rickymulya PR limitlessprojects#923 (bot:stale-base + bot:conflict) proposed the same family of rules with literal-only helpers; this take supersedes it with const-ident support and the untyped_const annotation check. Coordination: limitlessprojects#1428, limitlessprojects#1430 and limitlessprojects#1447 also bump census 126 -> 127 — the PR that lands last rebases the count to 128+. The numeric_adapt_conflict doc carries a dedupe NOTE against limitlessprojects#1447's is_untyped_constant (the kinds_conflict / PR limitlessprojects#620 duplicate-helper precedent) for whoever lands second.
…n — post-session-36 landings (limitlessprojects#1410/limitlessprojects#1411/limitlessprojects#1416/limitlessprojects#1418/limitlessprojects#1429/limitlessprojects#1440): corpus gains select-two-recv-define-arms-accept.hy (union 128 = 39/2/87), census reconciled to 128 on all 7 surfaces, buildable.rs auto-merged (1112 value-conflict points disjoint from E2005/main-init changes)
|
Queue-reset sweep: this repo now runs a rolling conveyor, and open PRs This is not a verdict on the work. If this change still matters:
Wildcard holds (verdict window 2026-11-01) and Pareto land candidates are |
…nd comparisons (fixes limitlessprojects#922) Root cause: check_binary_operands compared numeric FAMILIES, not concrete kinds — for `< <= > >=` and `+` the mismatch term was `lk.is_numeric() != rk.is_numeric()` (int and float64 are both numeric, so never mismatched), and `- * /` only checked kind membership. `x + f`, `x - f`, `x * f`, `x / f`, `x < f`, `f <= x` checked clean while go build refused each with `mismatched types int and float64` (GUARANTEES Row 13). Fix: a new Collector::numeric_adapt_conflict routes cross-kind operand pairs through Go's only implicit numeric conversion — untyped-constant adaptation — and emits HYB-E1002 when it cannot bridge them: - `1 + 2.5` (both untyped) and `f + 1` / `1 + f` (int const -> float64) keep building, including untyped `const` identifiers (`f + k`); - `x + f`, `f + x`, `x - f`, `x < f`, `f <= x`, and the untyped float const against a typed int (`x + 2.5`) are rejected; - `Define.untyped_const` (from LocalDecl.ty) distinguishes `const k = 1` (untyped) from `const k int = 1` (typed like a variable) for fn-local consts — the annotation was recorded but never consulted. Validation: new hy-check/tests/binop_operand_types_issue_922.rs 24/24 (15 reject faces + 9 accept controls); corpus pin binop-mismatched-numeric-reject.hy (REJECT BUILDABLE + HYB-E1002), census 126 -> 127 on all 7 surfaces; harness 127/127, tripwire not fired; negative flip: baseline upstream accepts the pin (126/127, pin FAILs) and restores to 127/127; differential 40/40 accept + 87/87 reject; cargo test --workspace green except the pre-existing local-CRLF spec_t3_strings failure (reproduces on clean HEAD). Harvest credit: stale companion rickymulya PR limitlessprojects#923 (bot:stale-base + bot:conflict) proposed the same family of rules with literal-only helpers; this take supersedes it with const-ident support and the untyped_const annotation check. Coordination: limitlessprojects#1428, limitlessprojects#1430 and limitlessprojects#1447 also bump census 126 -> 127 — the PR that lands last rebases the count to 128+. The numeric_adapt_conflict doc carries a dedupe NOTE against limitlessprojects#1447's is_untyped_constant (the kinds_conflict / PR limitlessprojects#620 duplicate-helper precedent) for whoever lands second.
Fixes #1112
Root cause
buildable.rs'skinds_conflictopens with a(Float, Int) => falsearm that exists solely for Go's untyped-constant conversion (var f float64 = 1builds) — its own comment concedes "the kind model cannot tell an untyped constant from anintvariable". So every value position that compares kinds let a typedintvariable through:var y int = 3; var x float64 = ychecks clean (0 diagnostics) and then failsgo buildwithcannot use y (value of type int) as float64 value in .... Issue #1112 enumerates the surfaces; all 10 were reproduced accept-then-go build-fail before this change.Fix
New
Collector::value_conflicts(want, got, value)=kinds_conflict(want, got) || (want == Float && got == Int && !self.is_untyped_constant(value)), guarding all 20 value positions:var f float64 = ypoint{f: y}g(y)/take(y)on*float64pt.scale(y)report_return_conflict(4 callers, value expr threaded through)return y/return g()append(s, y)x = y/pf, xi = y, y+=and-=/*=//=x += ym[y]onmap[float64]T[2]float64{y}/[]float64{y}map[float64]string{y: ..}/map[string]float64{..: y}copy(fs, is)Stmt::Send(narrow)ch <- yonchan float64is_untyped_constantis structural and conservative: int/rune literals,-x,a op bover constants, and references to an untypedconst— file-level only when declared without a type annotation (const k int = 3stays typed and rejects; fn-local consts fail open as untyped, sinceDefinerecords no annotation — documented fail-open, same direction askinds_conflict). Anything that reads a variable, calls, receives, or indexes is typed by construction in Go →false, i.e.value_conflictsis stricter, never looser, thankinds_conflict.The
Stmt::Sendcheck is deliberately narrow (Float elem ← non-untyped Int only): kind-level chan-element conflicts stay owned by HYB-E3011's shape rules, so no double-reporting.Untouched on purpose:
kinds_conflictitself,equality_kinds_conflict(1 == 1.0still legal),conversion_kinds_conflict(float64(y)still legal), kind-level container recursion ([]float64vs[]intvariables — out of issue scope).Side fix: the array-literal checker's literal-only
const_int_valueguard false-rejected an untyped file const (const k = 1+[2]float64{k}→ E1002; Go accepts). Subsumed byvalue_conflicts; now accepts, and typed/variable elements still reject.Validation
hy-check/tests/typed_int_float_coercion_issue_1112.rs: 29 tests — 20 reject faces (every table row above, incl. both send forms and f32) + 7 accept-control groups (literal/neg/binary/rune, untyped file and localconstat init/assign/return/arg/append/array/slice/map/send/+=, float→float,float64(x)conversion,1 == 1.0, classicreturn 1).cargo test --workspacegreen except the pre-existingspec_t3_stringsfailure, reproduced on cleanHEAD(it readsSPEC-LANGUAGE.md's T3 fence — unrelated).typed-int-into-float64-reject.hy(EXPECTED-VERDICT: REJECT BUILDABLE+EXPECTED-DIAGNOSTIC: HYB-E1002); census 126 → 127 on all 8 surfaces; harness 127/127, tripwire not fired; negative flip verified (exit 2 flipped / exit 0 restored).Credit
tests/assign_types.rs) and mhatipog's PR Fix/typed int float assignment 1112 #1117. This PR supersedes both with full-site coverage — happy to fold their test files in if the maintainer prefers.