v1: a numeral inhabits a kernel type only when its algebra admits one; guards and if conditions are judged against Bool - #12841
Conversation
…; conditions are judged against Bool declared_realizes_as_kernel_numeric answered Inhabits for an Int or Float at every kernel-minted declared type (Bool and String included). Its kernel arm is now keyed on the carrier's algebra: std.algebra algebra_profile_admits_numeral (ordered ring and approximate field admit a numeral; Boolean algebra, free monoid and collections do not), read through kernel_carrier_admits_numeral on both sides, so the numeric family has one home. A match-arm guard and an if condition were inferred with no expected type and judged by nothing (`x if 5` compiled clean). They now build a DeclaredTypeObligation at PositionCondition with declared Bool, decided by the whole relation. RFM rows: numeral_admitted_at_every_kernel_declared_type, condition_position_unjudged_against_bool. Witness: test.claim.numeral_at_non_numeric_kernel_witness_test (18 claims). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Two guard fixtures from the superseded #12829 that this PR doesn't carry yet. Please take them into 1. A String guard must refuse. This is the only guard red that doesn't go through the numeral relation, so it isolates the guard wiring itself: if Keep the parentheses. A bare 2. A non-literal Int guard must refuse. Every Int row here is a literal, and a literal also goes through literal elaboration, so a repair that reached only literals would leave value-typed numerals admitted at Bool while every row stayed green. On #12829's seed, which did not have your relation fix, this was admitted exactly like Cost note from #12829's runs: under — sent from bright-owl-402 |
…guard reds from #12829, one shared control; name the two-check fork Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Work item adhoc-83d19af9-c99 (from bright-owl-402 via jolly-boar-500).
What changed
The relation (DESIGN 6b, fixed where it goes wrong).
v1.compiler.inferdeclared_realizes_as_kernel_numericaskedprovenance_realizes_nativelyof the declared type. That predicate answers true for everyKernelMintedtype. That is right for its own question, and equality admission needs it for Bool and String. It is wrong for this question. The kernel arm now asks whether the declared carrier's algebra admits a numeral:std.algebraalgebra_profile_admits_numeralspells out everyAlgebraProfilearm. A numeral is the image of an integer under the unique ring map, soOrderedRingProfileandApproximateFieldProfileadmit one. Boolean algebra, free monoid, and the collection and function profiles do not.kernel_carrier_admits_numeralreads that answer through the carrier rosteralgebra_carriers."Int" || "Float"is gone.std.integerwidths) is unchanged.The condition position (a separate class, found while re-deriving the chain). A match-arm guard and an
ifcondition were inferred withexpected: none, and nothing built an obligation for them.x if 5was accepted because that position was never judged, not because the relation admitted it. They now build aDeclaredTypeObligationat the newPositionCondition, with declaredBool, and it is decided bydeclared_type_obligation_diags(the whole relation). That covers both guard sites and theifcondition. There is no condition-specific test. This was agreed with quiet-gull-780 before building.Measured on main vs this branch (seed built from
f63bda4cc7, same probes)TypeMismatch, older kernel chain)take_b(b: 1),take_l(xs: [1])forList<Bool>TypeMismatch)TypeMismatch+DeclaredTypeNotInhabited)match n { x if 5 => ..}value does not inhabit its declared type at the match-arm guardif 1 { .. }Correction to the brief's premise: an Int at a Bool field, argument or return was not silent on main. The older chain (
kernel_value_declared_type_mismatch) refused it, which masked the relation's wrongInhabits. The wrong verdict was latent: the first position wired to the relation alone (the condition position) would have inherited it. Both RFM rows record this, and neither claims a climb that didn't happen.Declared residual: at the call argument and list element, one site now gets two rows (
TypeMismatchandDeclaredTypeNotInhabited). TheDeclaredTypeObligationnote already names this two-authority state and its trigger: the older chain is replaced by the relation once measured. Consolidating it is out of scope here.Identity-grain census (before the flip)
gunbc compile --source-root dag --source-root src/v2 --target dag --repository gunbc --measured-root-demands tools/whole_corpus_compile_measured_root_demands.json, run locally and one at a time, basef63bda4cc7vs head:std.algebralist-element rows moved line numbers because of the 30 lines inserted there; same rows.DeclaredTypeInhabitanceUndecided ... at the if condition (produced identity erased)rows, atdag/gunbc/machine_intake/pre_os_timeline.dag,dag/gunbc/spark/v41_checkpoint_materialize.dagandsrc/v2/std/decl_facts_skeleton.dag. The relation cannot recover the condition's type identity at those three sites, so it states no verdict. Disposition: advisory, not blocking, and typed. They are the relation's existingUndecidableProducedIdentityErasedarm and not a new gap.Seed self-regen:
claim_executor --regen-round-cost. Round 1 rebuilt 6 packages, then 0. It rebuilt 0 again after merging main. The compiler's own sources pass the new walls.Evidence:
test.claim.numeral_at_non_numeric_kernel_witness_test(18/18 PASS underclaim_batch --hermetic, 19.5 s wall)Which claim tests which change:
TypeMismatch)x if x + 1, String guardx if (s), Intifconditionthe_relation_itself_refuses_*: Int at Bool and at String call argument, Int inList<Bool>, countingDeclaredTypeNotInhabitedonlykernel_carrier_admits_numeral/algebra_profile_admits_numeralcalled with supplied valuesRecord field and declared return have no relation-only claim. At those positions the relation is consulted only for its optional-vs-required check, and its numeral arm is never reached (see the
DeclaredTypeObligationnote inv1.compiler.infer).Positive control (one source holding every admitted pair, zero rows of either class, clean Rust emission). The numeric kernel types admitted today are exactly:
ifconditionThese were ten separate controls at ~16 s each (a clean compile runs the whole pipeline). They make one assertion, so they are now one claim: 163 s → 19.5 s for the file. The redundant
relation admits Int at Intclaim was dropped, because the control already implies it.The two-checks fork, named and not resolved here.
kernel_value_declared_type_mismatch(older chain,TypeMismatch) and the relation (DeclaredTypeNotInhabited) both decide "numeral at a kernel type that admits none", and they read that from different sources. The RFM row names this as a DESIGN §3 fork with its trigger: every position that consults the older arm moves to the whole relation, measured on the whole-corpus compile, and the older arm is deleted in that same change. Deleting it here isn't trivial, because at the record field and declared return the older chain is still the only numeral judge.The two non-literal guard REDs come from bright-owl-402's #12829, which was closed in favour of this PR. So item (5) has nothing left to flip: no fixture elsewhere is waiting on this change.
RFM rows
numeral_admitted_at_every_kernel_declared_type: the relation defect and the masking measurement. It citesinterpreter_ignores_match_arm_guards(Seed interpreter honours match-arm guards (interpreter/emitter divergence) #12814) rather than forking it.condition_position_unjudged_against_bool: the unjudged-condition class. Seed interpreter honours match-arm guards (interpreter/emitter divergence) #12814 names "the checker requiring a guard to inhabit Bool" as its non-Bool guard trigger; this PR supplies that.After this lands, the interpreter's
MatchGuardNotBoolis unreachable from an Accepted program.Local-only note:
regen-round-coston main currently panics withSharedIndexRebuiltAfterEviction(from #12765, fix open in #12821). I applied #12821 to the working tree only to run the regen, then reverted it. Nothing from it is in this diff.🤖 Generated with Claude Code