From 888256226a1e22875fb2a58263fda55fd15f93a2 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Mon, 28 Sep 2026 11:05:30 +0000 Subject: [PATCH 01/21] WIP: Float de-fork (binary64 in extdeps, kernel type denotation) --- dag/extdeps/languages/rust/primitives.dag | 72 ++++++ dag/extdeps/standards/ieee_754_2019.dag | 219 +++++++++++++++++- dag/gunbc/defork_type_name_census.dag | 16 +- dag/gunbc/doc_graph_roots.dag | 2 +- dag/gunbc/fleet/fleet_intent.dag | 3 +- dag/gunbc/non_fold_residue.dag | 5 - dag/gunbc/rust_source_type_bindings.dag | 8 +- dag/std/float.dag | 18 -- dag/std/kernel_type_denotation.dag | 69 ++++++ ...float_binary64_denotation_witness_test.dag | 185 +++++++++++++++ src/v2/std/float.dag | 173 -------------- 11 files changed, 555 insertions(+), 215 deletions(-) delete mode 100644 dag/std/float.dag create mode 100644 dag/std/kernel_type_denotation.dag create mode 100644 dag/test/claim/kernel_float_binary64_denotation_witness_test.dag delete mode 100644 src/v2/std/float.dag diff --git a/dag/extdeps/languages/rust/primitives.dag b/dag/extdeps/languages/rust/primitives.dag index 330df525afe..4d83d82aca3 100644 --- a/dag/extdeps/languages/rust/primitives.dag +++ b/dag/extdeps/languages/rust/primitives.dag @@ -4,6 +4,10 @@ import std.algebra { OrderedRing, Semiring, BooleanAlgebra } import std.bit { Bit, Byte, Word16, Word32, Word64, Word128 } import extdeps.external_authority { ExternalAuthority } import extdeps.uri { Uri, Https } +import std.kernel_type_denotation { + KernelTypeDenotationAdmission, KernelTypeDenoted, KernelTypeUndenoted, + BinaryInterchangeFormatMeaning, kernel_type_denotation_for +} data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority { uri: Uri { @@ -109,3 +113,71 @@ data rust_grounding_primitives: List = [ NonIntegerPrimitive { target_name: "()", algebra: TerminalAlgebra, carrier: TerminalCarrier, is_copy: true } ] + +// Rust f64 IS NOT THE DEFINITION OF KERNEL Float; it is a checked binding to what Float denotes +// (std.kernel_type_denotation, IEEE 754-2019 binary64). The constants below are Rust's own, as the +// standard library documents them at the anchor, under Rust's conventions: MANTISSA_DIGITS counts +// the implicit bit (= p); MAX_EXP and MIN_EXP are one above IEEE's emax and emin (so MAX_EXP = +// emax + 1 and MIN_EXP = emin + 1 = 2 - emax). The Rust reference describes f64 as the IEEE 754-2008 +// binary64 format; the binary64 interchange parameters are unchanged in the 2019 revision. +data rust_std_f64_anchor: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "doc.rust-lang.org/std/primitive.f64.html" + } +} + +type RustFloatBinding { + kernel_name: String + target_name: String + authority: ExternalAuthority + radix: Int + mantissa_digits: Int + max_exp: Int + min_exp: Int +} + +data rust_f64_binding: RustFloatBinding = RustFloatBinding { + kernel_name: "Float", + target_name: "f64", + authority: rust_std_f64_anchor, + radix: 2, + mantissa_digits: 53, + max_exp: 1024, + min_exp: -1021 +} + +type RustFloatBindingVerdict + = RustFloatBindingHolds + | RustFloatBindingUndenoted { kernel_name: String } + | RustFloatBindingDisagrees { kernel_name: String, target_name: String } + | RustFloatBindingNoPrimitive { target_name: String } + +fn rust_grounding_primitive_named(target_name: String) -> Bool { + rust_grounding_primitives |> any(p => match p { + IntegerPrimitive { target_name: n, algebra: _, carrier: _, range_min_inclusive: _, range_max_inclusive: _, is_copy: _, overflow: _ } => false + NonIntegerPrimitive { target_name: n, algebra: a, carrier: _, is_copy: _ } => n == target_name && a == ApproximateFieldAlgebra + }) +} + +// The denotation rows are a parameter so a claim can plant a mismatched table at this interface; +// the production reading is rust_float_binding_verdict(b, denotations: kernel_type_denotation_rows). +fn rust_float_binding_verdict(b: RustFloatBinding, denotations: List) -> RustFloatBindingVerdict { + if rust_grounding_primitive_named(target_name: b.target_name) == false { + RustFloatBindingNoPrimitive { target_name: b.target_name } + } else { + match kernel_type_denotation_for(name: b.kernel_name, rows: denotations) { + KernelTypeUndenoted { name: n } => RustFloatBindingUndenoted { kernel_name: n } + KernelTypeDenoted { meaning: BinaryInterchangeFormatMeaning { format: f } } => + if b.radix == 2 + && b.mantissa_digits == f.p + && b.max_exp == f.emax + 1 + && b.min_exp == 2 - f.emax + { + RustFloatBindingHolds + } else { + RustFloatBindingDisagrees { kernel_name: b.kernel_name, target_name: b.target_name } + } + } + } +} diff --git a/dag/extdeps/standards/ieee_754_2019.dag b/dag/extdeps/standards/ieee_754_2019.dag index 4afca2d032d..a603c4f5957 100644 --- a/dag/extdeps/standards/ieee_754_2019.dag +++ b/dag/extdeps/standards/ieee_754_2019.dag @@ -1,8 +1,15 @@ module extdeps.standards.ieee_754_2019 -import extdeps.external_authority { ExternalAuthority, ExternalModelScope, ExternalSubjectRef } +import extdeps.external_authority { ExternalAuthority, ExternalModelScope, ExternalSubjectRef, FactCitation } import extdeps.uri { Uri, Https } -import std.decl_ref { DeclarationRef, WholeDeclaration } +import std.decl_ref { DeclarationRef, WholeDeclaration, decl_ref } +import std.types { Bool, Int, List, NonEmptyStr, String } +import std.bit { Bit } +import std.algebra { Ordering, Less, Equal, Greater } +import std.approximate_field { + Precision, BinaryPrecision, RoundingMode, ToNearestEven, SpecialValues, QuietAndSignalingNaN, + SignedInfinity, SignedZero, SubnormalPolicy, GradualUnderflow +} data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority { uri: Uri { @@ -38,3 +45,211 @@ data extdeps_model_scope: ExternalModelScope = ExternalModelScope { first_citation: extdeps.standards.ieee_754_2019.extdeps_external_authority_anchor, further_citations: [] } + +// THE BINARY INTERCHANGE FORMAT PARAMETERS, IEEE 754-2019 §3.6 Table 3.5, named by the table's own +// symbols: k storage width, p precision, emax, w exponent field width, t trailing significand field +// width. They are Int, not a Nat refinement: which Nat is the integer family's root is an open fork +// in gunbc.defork_type_name_census, and a standard's module must not pick its side by import. +type BinaryInterchangeFormat { + k: Int + p: Int + emax: Int + w: Int + t: Int +} + +data binary32: BinaryInterchangeFormat = BinaryInterchangeFormat { k: 32, p: 24, emax: 127, w: 8, t: 23 } + +data binary64: BinaryInterchangeFormat = BinaryInterchangeFormat { k: 64, p: 53, emax: 1023, w: 11, t: 52 } + +// binary64 INHABITS the generic std.approximate_field algebra: these are its parameters, each cited +// to the clause that fixes it. The Field base (the arithmetic operations of §5.4) is not supplied +// here; that is the frontier on which a full ApproximateField> value for +// binary64 lands, and nothing below pretends to it. +data binary64_precision: Precision = BinaryPrecision { significand_bits: 53, exponent_bits: 11 } + +data binary64_default_rounding: RoundingMode = ToNearestEven + +data binary64_special_values: SpecialValues = SpecialValues { + nan: QuietAndSignalingNaN, + infinity: SignedInfinity, + signed_zero: SignedZero +} + +data binary64_subnormal_policy: SubnormalPolicy = GradualUnderflow + +// A fact of this module cited to its clause under the spec's own term. The std vocabulary spells +// the rounding attribute generically (ToNearestEven); the standard's name for it is +// roundTiesToEven, and that name lives here, as data on the citation, not as a second variant. +type Ieee754ClauseCitation { + citation: FactCitation + clause: NonEmptyStr + spec_term: NonEmptyStr +} + +fn ieee_754_2019_cite(decl_name: String, clause: String, spec_term: String) -> Ieee754ClauseCitation { + Ieee754ClauseCitation { + citation: FactCitation { + fact: decl_ref(module_path: "extdeps.standards.ieee_754_2019", decl_name: decl_name), + authority: extdeps_external_authority_anchor + }, + clause: clause as NonEmptyStr, + spec_term: spec_term as NonEmptyStr + } +} + +data ieee_754_2019_clause_citations: List = [ + ieee_754_2019_cite(decl_name: "binary32", clause: "3.6 Table 3.5", spec_term: "binary32"), + ieee_754_2019_cite(decl_name: "binary64", clause: "3.6 Table 3.5", spec_term: "binary64"), + ieee_754_2019_cite(decl_name: "binary64_precision", clause: "3.6 Table 3.5", spec_term: "p, w"), + ieee_754_2019_cite(decl_name: "binary64_default_rounding", clause: "4.3.3", spec_term: "roundTiesToEven"), + ieee_754_2019_cite(decl_name: "binary64_special_values", clause: "3.3, 6.1, 6.2, 6.3", spec_term: "quiet NaN, signaling NaN, infinity, signed zero"), + ieee_754_2019_cite(decl_name: "binary64_subnormal_policy", clause: "3.4", spec_term: "subnormal numbers"), + ieee_754_2019_cite(decl_name: "BinaryInterchangeEncoding", clause: "3.4", spec_term: "S, E, T"), + ieee_754_2019_cite(decl_name: "class", clause: "5.7.2", spec_term: "class"), + ieee_754_2019_cite(decl_name: "compare_quiet", clause: "5.11", spec_term: "comparison relations"), + ieee_754_2019_cite(decl_name: "quiet_nan_trailing_significand_leading_bit", clause: "6.2.1", spec_term: "quiet NaN d1") +] + +// THE ENCODING, §3.4: sign bit S, biased exponent field E (w bits), trailing significand field T +// (t bits), each field MSB first. The widths are a construction fact of the FORMAT, so the encoding +// carries the format it was admitted under and binary_interchange_encoding refuses a field whose +// length disagrees with it. RUNG, stated honestly: mechanically preventable, not structural -- the +// record constructor stays public and a record-field Length refinement does not exist yet; the +// next-rung trigger is gunbc.plans.cardinality_refinement P3 (record-field `where Length`). +type BinaryInterchangeEncoding { + format: BinaryInterchangeFormat + s: Bit + e: List + t: List +} + +type EncodingFieldWidthRefusal + = BiasedExponentFieldWidth { expected_w: Int, observed: Int } + | TrailingSignificandFieldWidth { expected_t: Int, observed: Int } + +type EncodingAdmission + = EncodingAdmitted { encoding: BinaryInterchangeEncoding } + | EncodingRefused { refusal: EncodingFieldWidthRefusal } + +fn binary_interchange_encoding(format: BinaryInterchangeFormat, s: Bit, e: List, t: List) -> EncodingAdmission { + if list_length(e) != format.w { + EncodingRefused { refusal: BiasedExponentFieldWidth { expected_w: format.w, observed: list_length(e) } } + } else { + if list_length(t) != format.t { + EncodingRefused { refusal: TrailingSignificandFieldWidth { expected_t: format.t, observed: list_length(t) } } + } else { + EncodingAdmitted { encoding: BinaryInterchangeEncoding { format: format, s: s, e: e, t: t } } + } + } +} + +// A field read as the unsigned integer its bits spell MSB first. The widest field is t = 52 for +// binary64, inside Int's range; this is the whole of the arithmetic the module does. +fn bit_field_value(bits: List) -> Int { + bits |> fold(init: 0, f: (acc, b) => if b { acc * 2 + 1 } else { acc * 2 }) +} + +fn bit_field_all_ones(bits: List) -> Bool { + bits |> all(b => b) +} + +fn bit_field_all_zeros(bits: List) -> Bool { + bits |> all(b => b == false) +} + +// §6.2.1: a quiet NaN's trailing significand field has its first bit d1 = 1, a signaling NaN's +// d1 = 0. MSB first, d1 is set exactly when the field's value exceeds half its all-ones value. +fn quiet_nan_trailing_significand_leading_bit(t: List) -> Bool { + bit_field_value(t) * 2 > (t |> fold(init: 0, f: (acc, _b) => acc * 2 + 1)) +} + +// §5.7.2 class(x): the ten classes under the standard's own names. +type Ieee754Class + = SignalingNaN + | QuietNaN + | NegativeInfinity + | NegativeNormal + | NegativeSubnormal + | NegativeZero + | PositiveZero + | PositiveSubnormal + | PositiveNormal + | PositiveInfinity + +fn class(x: BinaryInterchangeEncoding) -> Ieee754Class { + if bit_field_all_ones(x.e) { + if bit_field_all_zeros(x.t) { + if x.s { NegativeInfinity } else { PositiveInfinity } + } else { + if quiet_nan_trailing_significand_leading_bit(x.t) { QuietNaN } else { SignalingNaN } + } + } else { + if bit_field_all_zeros(x.e) { + if bit_field_all_zeros(x.t) { + if x.s { NegativeZero } else { PositiveZero } + } else { + if x.s { NegativeSubnormal } else { PositiveSubnormal } + } + } else { + if x.s { NegativeNormal } else { PositiveNormal } + } + } +} + +fn is_nan(x: BinaryInterchangeEncoding) -> Bool { + bit_field_all_ones(x.e) && (bit_field_all_zeros(x.t) == false) +} + +fn is_zero(x: BinaryInterchangeEncoding) -> Bool { + bit_field_all_zeros(x.e) && bit_field_all_zeros(x.t) +} + +// §5.11: every pair of operands stands in exactly one of four relations. Unordered is the +// standard's answer when either operand is a NaN, and it is the ONLY answer a NaN operand gets: +// an Ordering is produced solely for non-NaN operands, so no caller can read a NaN as ordered. +// This is compareQuiet's relation, NOT totalOrder (§5.10), which orders NaNs by sign and payload +// and is not implemented here. +type ComparisonRelation + = Ordered { ordering: Ordering } + | Unordered + +// Non-NaN operands of one format: +0 and -0 are equal (§5.11); otherwise negative precedes +// positive, and within one sign the magnitude order IS the lexicographic order of (E, T) -- which +// places infinity (E all ones) above every finite value without a special case. +fn compare_quiet(a: BinaryInterchangeEncoding, b: BinaryInterchangeEncoding) -> ComparisonRelation { + if is_nan(a) || is_nan(b) { + Unordered + } else { + if is_zero(a) && is_zero(b) { + Ordered { ordering: Equal } + } else { + if a.s != b.s { + if a.s { Ordered { ordering: Less } } else { Ordered { ordering: Greater } } + } else { + let magnitude = magnitude_ordering(a: a, b: b) + if a.s { Ordered { ordering: ordering_reverse(o: magnitude) } } else { Ordered { ordering: magnitude } } + } + } + } +} + +fn int_ordering(a: Int, b: Int) -> Ordering { + if a < b { Less } else { if a > b { Greater } else { Equal } } +} + +fn magnitude_ordering(a: BinaryInterchangeEncoding, b: BinaryInterchangeEncoding) -> Ordering { + match int_ordering(a: bit_field_value(a.e), b: bit_field_value(b.e)) { + Less => Less + Greater => Greater + Equal => int_ordering(a: bit_field_value(a.t), b: bit_field_value(b.t)) + } +} + +fn ordering_reverse(o: Ordering) -> Ordering { + match o { + Less => Greater + Greater => Less + Equal => Equal + } +} diff --git a/dag/gunbc/defork_type_name_census.dag b/dag/gunbc/defork_type_name_census.dag index b7d97789d7a..b18bcb5b759 100644 --- a/dag/gunbc/defork_type_name_census.dag +++ b/dag/gunbc/defork_type_name_census.dag @@ -112,6 +112,7 @@ type ForkResolution = ResolvedByRenamingV2 { renamed_to: String, citation: String } | ResolvedByDeletingV2 { reason: String } | ResolvedByRenamingDag { renamed_to: String, citation: String } + | ResolvedByRehomingBothToExtdeps { authority: String, citation: String } type ResolvedSharedTypeName { names: List @@ -189,15 +190,6 @@ data defork_census_rows: List = [ }, disposition: ForkOpen { reason: "next PR of the de-fork wave (the v2 side has ~40 consumer sites across `v2.extdeps.formatters.*`)" } }, - SharedTypeNameRow { - names: ["Float"], - reading: AuthoredResolutionReading { - dag_side: "`= Float64` → `std.float` `Float64`", - v2_side: "`= Binary64` → `v2.std.float` `Binary64` (was `= Float64`, byte-identical text, different referent)", - class: "resolution-divergent (text was identical)" - }, - disposition: ForkAwaitingRuling { question: "seed kernel name — out of scope for the wave" } - }, SharedTypeNameRow { names: ["String"], reading: AuthoredResolutionReading { @@ -291,6 +283,11 @@ data defork_census_rows: List = [ ] data defork_census_resolved: List = [ + ResolvedSharedTypeName { + names: ["Float"], + resolution: ResolvedByRehomingBothToExtdeps { authority: "extdeps.standards.ieee_754_2019 binary64", citation: "IEEE 754-2019 §3.6 (operator ruling relayed 2026-09-28): `std.float` (Float = Float64, uncited) and `v2.std.float` (Float = Binary64) both deleted; kernel Float's meaning is the `std.kernel_type_denotation` row, not a std alias" }, + change: 0 + }, ResolvedSharedTypeName { names: ["ProjectionKind"], resolution: ResolvedByDeletingV2 { reason: "`v2.std.projection` (compiler lens kinds) had zero importers; `std.planar_projection` keeps the name for drawing views" }, @@ -348,6 +345,7 @@ fn census_resolution_text(r: ForkResolution) -> String { ResolvedByRenamingV2 { renamed_to, citation } => concat(concat(concat("v2 side renamed `", renamed_to), "` — "), citation) ResolvedByDeletingV2 { reason } => concat("v2 side deleted — ", reason) ResolvedByRenamingDag { renamed_to, citation } => concat(concat(concat("dag side renamed `", renamed_to), "` — "), citation) + ResolvedByRehomingBothToExtdeps { authority, citation } => concat(concat(concat("both sides deleted; the concept is homed at `", authority), "` — "), citation) } } diff --git a/dag/gunbc/doc_graph_roots.dag b/dag/gunbc/doc_graph_roots.dag index 17c3a52db57..cebfec22202 100644 --- a/dag/gunbc/doc_graph_roots.dag +++ b/dag/gunbc/doc_graph_roots.dag @@ -700,7 +700,7 @@ data hand_authored_doc_bind_incomings: List = [ slug: "groupcompletion-pair-construction-design", primary_work: DeclarationRef { module_path: "std.algebra", decl_name: "GroupCompletion", field: WholeDeclaration }, additional_works: [ - DeclarationRef { module_path: "std.float", decl_name: "Real", field: WholeDeclaration }, + DeclarationRef { module_path: "std.approximate_field", decl_name: "ApproximateField", field: WholeDeclaration }, DeclarationRef { module_path: "std.rational", decl_name: "Rational", field: WholeDeclaration }, ], dissolution: PlanRetiresWhen { condition: unbound_dissolution(description: "the work this document plans lands and its subject GroupCompletion describes shipped behavior rather than a planned change; the row deletes with the document. Registered at subject grain: the systems bound here are the ones whose movement would make this document's purpose false, not every system its prose mentions.") }, diff --git a/dag/gunbc/fleet/fleet_intent.dag b/dag/gunbc/fleet/fleet_intent.dag index 7132f0fa74b..6cd7bc405d9 100644 --- a/dag/gunbc/fleet/fleet_intent.dag +++ b/dag/gunbc/fleet/fleet_intent.dag @@ -39,7 +39,7 @@ import extdeps.bmc.endpoint { BmcEndpoint, Redfish } import std.credentials { CredentialFlow, Stored } import std.measure { hertz, ByteSize, byte_size, byte_size_count, Bandwidth, HardwareThreadCount, hardware_thread_count_value, Nano, measure_count, Nanosecond, nanosecond, nanosecond_count } import std.os.types { OperatingSystemSurface, Linux, Posix, PosixProcess } -import std.types { List, NonEmptyStr, Bool, Int, String } +import std.types { List, NonEmptyStr, Bool, Int, String, Float } import std.realization_schedule { CostAccount, CostAxis, CostAxisMeasured, CostAxisUnestablished, CostTimeAxis, CostTimeMeasured, CostTimeUnestablished, @@ -49,7 +49,6 @@ import std.realization_measurement { cost_axis_add_time, cost_axis_peak_space, } import std.nat { Nat } -import std.float { Float } type IsolationBoundary = SharedHostHome | PerJobFilesystem | ContainerHermetic | Vm diff --git a/dag/gunbc/non_fold_residue.dag b/dag/gunbc/non_fold_residue.dag index 188d684eb86..6a0b894da06 100644 --- a/dag/gunbc/non_fold_residue.dag +++ b/dag/gunbc/non_fold_residue.dag @@ -867,11 +867,6 @@ data non_fold_residue_frontier: List = [ reason: nfr_reason_mint_era, dissolution: nfr_dissolve_wildcard_total, }, - FrontierRow { - subject: PathSubject { path: "src/v2/std/float.dag::float_body_is_nan" }, - reason: nfr_reason_mint_era, - dissolution: nfr_dissolve_wildcard_total, - }, FrontierRow { subject: PathSubject { path: "src/v2/std/native_agreement.dag::runtime_value_discriminant_octet" }, reason: nfr_reason_native_agreement_octet, diff --git a/dag/gunbc/rust_source_type_bindings.dag b/dag/gunbc/rust_source_type_bindings.dag index 47b6229199c..8cf89d71b55 100644 --- a/dag/gunbc/rust_source_type_bindings.dag +++ b/dag/gunbc/rust_source_type_bindings.dag @@ -7,7 +7,7 @@ import std.target_representation { MigratedToExactBinding, ProvenUniqueKernelBinding, StillBareNameDebt } import extdeps.languages.rust.representation { - RustRepresentation, RustStdString, RustI64, RustF64, RustBool, RustUnit, RustVecU8, RustSerdeJsonValue + RustRepresentation, RustStdString, RustI64, RustBool, RustUnit, RustVecU8, RustSerdeJsonValue } // THE CORPUS'S HALF OF THE THREE-IDENTITY SPLIT (std.target_representation): which of THIS corpus's @@ -55,7 +55,6 @@ data rust_source_type_binding_rows: List List { }, CheckpointRowMigration { dag_name: "Float" as NonEmptyStr, - disposition: StillBareNameDebt { - reason: "std.float Float has an exact row (RustF64). v2.std.float Float (= Binary64) is answered f64 by the bare-name bypass with no ruling that this is its modeled realization; the kernel float_type mint rides the same row." as NonEmptyStr, - restoration_trigger: "The same ruling as Int, for v2.std.float Float; then ProvenUniqueKernelBinding on the f64 primitive token." as NonEmptyStr + disposition: ProvenUniqueKernelBinding { + proof: "No .dag declaration of the spelling Float remains: the Float de-fork (operator ruling relayed 2026-09-28) deleted std.float (Float = Float64 = Real64) and v2.std.float (Float = Binary64) together, and moved the IEEE 754-2019 binary64 facts to extdeps.standards.ieee_754_2019. What reaches this row is the kernel float_type mint and a bare Float in a module importing std.types Float, which is the same kernel name. What kernel Float MEANS is std.kernel_type_denotation (binary64), target-independent; this row states only how Rust spells it. That realization is checked against the denotation by extdeps.languages.rust.primitives rust_float_binding_verdict, and `f64` is a primitive token no use-line can shadow." as NonEmptyStr } }, CheckpointRowMigration { diff --git a/dag/std/float.dag b/dag/std/float.dag deleted file mode 100644 index 3bca93d2985..00000000000 --- a/dag/std/float.dag +++ /dev/null @@ -1,18 +0,0 @@ -module std.float - -import std.algebra { Field, FieldOfFractions } -import std.integer { Int } -import std.machine_constraints { Compose, MachineWidth } -import std.approximate_field { ApproximateField } - -type Ieee754Float - -type Real = ApproximateField> - -type Real32 = Compose> -type Real64 = Compose> - -type Float32 = Real32 -type Float64 = Real64 - -type Float = Float64 diff --git a/dag/std/kernel_type_denotation.dag b/dag/std/kernel_type_denotation.dag new file mode 100644 index 00000000000..80c120af270 --- /dev/null +++ b/dag/std/kernel_type_denotation.dag @@ -0,0 +1,69 @@ +module std.kernel_type_denotation + +import std.types { Bool, List, String, is_kernel_type } +import extdeps.standards.ieee_754_2019 { BinaryInterchangeFormat, binary64 } + +// WHAT A KERNEL TYPE NAME MEANS, INDEPENDENT OF ANY TARGET. The kernel names are rostered in +// std.types kernel_type_set; how each one is REALIZED on a target is that target's binding (for +// Rust, gunbc.rust_source_type_bindings and extdeps.languages.rust.representation), and none of +// those is the definition. This module is the one home for the definition: one row per kernel name +// whose meaning is a cited external authority. It carries one row today, Float -> IEEE 754-2019 +// binary64 (operator ruling relayed 2026-09-28, the Float de-fork). A later row for String, Int or +// Bool is an ADDITION HERE -- a new KernelTypeMeaning arm and a row -- never a new home. Every +// target's check reads its expected semantics from kernel_type_denotation_for, so two targets +// realizing one kernel name are checked against the same denotation rather than against each other. +// +// It lives above std.types and std.algebra rather than inside them because both sit below +// std.decl_ref and below every extdeps module in the import graph; carrying the denotation there +// would need an import cycle or a stringly reference (the two alternatives refused on the ruling). + +type KernelTypeMeaning + = BinaryInterchangeFormatMeaning { format: BinaryInterchangeFormat } + +// A key is a kernel name only by membership in std.types kernel_type_set, read through +// is_kernel_type rather than restated. RUNG: mechanically preventable -- the record constructor of +// KernelTypeDenotation stays public; every row below is built through kernel_type_denotation_row, +// and kernel_type_denotation_rows_admitted is the executed check that none was refused. +type KernelTypeDenotation { + kernel_name: String + meaning: KernelTypeMeaning +} + +type KernelTypeDenotationAdmission + = KernelTypeDenotationAdmitted { denotation: KernelTypeDenotation } + | NotAKernelTypeName { name: String } + +fn kernel_type_denotation_row(kernel_name: String, meaning: KernelTypeMeaning) -> KernelTypeDenotationAdmission { + if is_kernel_type(name: kernel_name) { + KernelTypeDenotationAdmitted { denotation: KernelTypeDenotation { kernel_name: kernel_name, meaning: meaning } } + } else { + NotAKernelTypeName { name: kernel_name } + } +} + +data kernel_type_denotation_rows: List = [ + kernel_type_denotation_row(kernel_name: "Float", meaning: BinaryInterchangeFormatMeaning { format: binary64 }) +] + +fn kernel_type_denotation_rows_admitted(rows: List) -> Bool { + rows |> all(r => match r { + KernelTypeDenotationAdmitted { denotation: _ } => true + NotAKernelTypeName { name: _ } => false + }) +} + +type KernelTypeDenotationLookup + = KernelTypeDenoted { meaning: KernelTypeMeaning } + | KernelTypeUndenoted { name: String } + +// The rows are a parameter so a claim can supply a planted table at this one interface; the +// production reading is kernel_type_denotation_for(name, rows: kernel_type_denotation_rows). +fn kernel_type_denotation_for(name: String, rows: List) -> KernelTypeDenotationLookup { + rows |> fold(init: KernelTypeUndenoted { name: name }, f: (acc, r) => match acc { + KernelTypeDenoted { meaning: _ } => acc + KernelTypeUndenoted { name: _ } => match r { + KernelTypeDenotationAdmitted { denotation: d } => if d.kernel_name == name { KernelTypeDenoted { meaning: d.meaning } } else { acc } + NotAKernelTypeName { name: _ } => acc + } + }) +} diff --git a/dag/test/claim/kernel_float_binary64_denotation_witness_test.dag b/dag/test/claim/kernel_float_binary64_denotation_witness_test.dag new file mode 100644 index 00000000000..dff874b6706 --- /dev/null +++ b/dag/test/claim/kernel_float_binary64_denotation_witness_test.dag @@ -0,0 +1,185 @@ +module test.claim.kernel_float_binary64_denotation_witness_test + +import std.types { Bool, Int, List, String } +import std.bit { Bit } +import std.algebra { Less, Equal, Greater } +import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly } +import extdeps.standards.ieee_754_2019 { + BinaryInterchangeEncoding, EncodingAdmission, EncodingAdmitted, EncodingRefused, + BiasedExponentFieldWidth, TrailingSignificandFieldWidth, binary32, binary64, + binary_interchange_encoding, class, compare_quiet, Ordered, Unordered, + QuietNaN, SignalingNaN, PositiveSubnormal, NegativeZero, PositiveNormal, PositiveInfinity +} +import std.kernel_type_denotation { + KernelTypeDenotationAdmission, KernelTypeDenotationAdmitted, NotAKernelTypeName, + KernelTypeDenotation, BinaryInterchangeFormatMeaning, + kernel_type_denotation_row, kernel_type_denotation_rows, kernel_type_denotation_rows_admitted +} +import extdeps.languages.rust.primitives { + RustFloatBinding, RustFloatBindingHolds, RustFloatBindingDisagrees, RustFloatBindingUndenoted, + RustFloatBindingNoPrimitive, rust_f64_binding, rust_float_binding_verdict +} + +data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly + +// KERNEL Float DENOTES binary64, AND RUST f64 IS CHECKED AGAINST THAT DENOTATION. The route claims +// run the production rows (kernel_type_denotation_rows, rust_f64_binding); the REDs plant a row at +// the one interface that takes rows as a parameter, so each refusal is discriminated by the plant +// alone. The binary64 claims build encodings through the admitting constructor, never the record. + +fn bits(b: Bit, n: Int) -> List { + if n <= 0 { [] } else { concat([b], bits(b: b, n: n - 1)) } +} + +fn admitted(a: EncodingAdmission) -> Bool { + match a { + EncodingAdmitted { encoding: _ } => true + EncodingRefused { refusal: _ } => false + } +} + +// Fields are w = 11 and t = 52 for binary64. A test encoding that fails admission is a defect in +// the claim, so the fallback is a signaling NaN, which no ordered claim below can accept. +fn enc(s: Bit, e: List, t: List) -> BinaryInterchangeEncoding { + match binary_interchange_encoding(format: binary64, s: s, e: e, t: t) { + EncodingAdmitted { encoding: x } => x + EncodingRefused { refusal: _ } => BinaryInterchangeEncoding { format: binary64, s: false, e: bits(b: true, n: 11), t: concat(bits(b: false, n: 51), [true]) } + } +} + +// 1.0 = E 01111111111, T 0; 2.0 = E 10000000000, T 0. +fn one() -> BinaryInterchangeEncoding { enc(s: false, e: concat([false], bits(b: true, n: 10)), t: bits(b: false, n: 52)) } +fn two() -> BinaryInterchangeEncoding { enc(s: false, e: concat([true], bits(b: false, n: 10)), t: bits(b: false, n: 52)) } +fn minus_one() -> BinaryInterchangeEncoding { enc(s: true, e: concat([false], bits(b: true, n: 10)), t: bits(b: false, n: 52)) } +fn plus_zero() -> BinaryInterchangeEncoding { enc(s: false, e: bits(b: false, n: 11), t: bits(b: false, n: 52)) } +fn minus_zero() -> BinaryInterchangeEncoding { enc(s: true, e: bits(b: false, n: 11), t: bits(b: false, n: 52)) } +fn plus_infinity() -> BinaryInterchangeEncoding { enc(s: false, e: bits(b: true, n: 11), t: bits(b: false, n: 52)) } +fn minus_infinity() -> BinaryInterchangeEncoding { enc(s: true, e: bits(b: true, n: 11), t: bits(b: false, n: 52)) } +fn max_finite() -> BinaryInterchangeEncoding { enc(s: false, e: concat(bits(b: true, n: 10), [false]), t: bits(b: true, n: 52)) } +fn smallest_subnormal() -> BinaryInterchangeEncoding { enc(s: false, e: bits(b: false, n: 11), t: concat(bits(b: false, n: 51), [true])) } +fn quiet_nan() -> BinaryInterchangeEncoding { enc(s: false, e: bits(b: true, n: 11), t: concat([true], bits(b: false, n: 51))) } +fn signaling_nan() -> BinaryInterchangeEncoding { enc(s: false, e: bits(b: true, n: 11), t: concat(bits(b: false, n: 51), [true])) } + +fn is_ordered_as(a: BinaryInterchangeEncoding, b: BinaryInterchangeEncoding, expected: std.algebra.Ordering) -> Bool { + match compare_quiet(a: a, b: b) { + Ordered { ordering: o } => o == expected + Unordered => false + } +} + +fn is_unordered(a: BinaryInterchangeEncoding, b: BinaryInterchangeEncoding) -> Bool { + match compare_quiet(a: a, b: b) { + Ordered { ordering: _ } => false + Unordered => true + } +} + +// ---- the denotation and the Rust binding, production route ---- + +test fn w_production_denotation_rows_are_all_kernel_names() -> Bool { + kernel_type_denotation_rows_admitted(rows: kernel_type_denotation_rows) +} + +test fn w_rust_f64_holds_against_what_float_denotes() -> Bool { + rust_float_binding_verdict(b: rust_f64_binding, denotations: kernel_type_denotation_rows) == RustFloatBindingHolds +} + +// ---- REDs at the denotation interface ---- + +test fn w_planted_float_denotes_binary32_refuses_f64() -> Bool { + let planted = [kernel_type_denotation_row(kernel_name: "Float", meaning: BinaryInterchangeFormatMeaning { format: binary32 })] + match rust_float_binding_verdict(b: rust_f64_binding, denotations: planted) { + RustFloatBindingDisagrees { kernel_name: k, target_name: t } => k == "Float" && t == "f64" + _ => false + } +} + +test fn w_non_kernel_name_key_is_refused() -> Bool { + match kernel_type_denotation_row(kernel_name: "Real", meaning: BinaryInterchangeFormatMeaning { format: binary64 }) { + NotAKernelTypeName { name: n } => n == "Real" + KernelTypeDenotationAdmitted { denotation: _ } => false + } +} + +test fn w_table_with_a_non_kernel_key_is_not_admitted() -> Bool { + let planted = [kernel_type_denotation_row(kernel_name: "Float64", meaning: BinaryInterchangeFormatMeaning { format: binary64 })] + kernel_type_denotation_rows_admitted(rows: planted) == false +} + +test fn w_undenoted_kernel_name_refuses_the_binding() -> Bool { + match rust_float_binding_verdict(b: rust_f64_binding, denotations: []) { + RustFloatBindingUndenoted { kernel_name: k } => k == "Float" + _ => false + } +} + +test fn w_binding_to_an_absent_primitive_refuses() -> Bool { + let planted = RustFloatBinding { + kernel_name: "Float", target_name: "f80", authority: rust_f64_binding.authority, + radix: 2, mantissa_digits: 53, max_exp: 1024, min_exp: -1021 + } + match rust_float_binding_verdict(b: planted, denotations: kernel_type_denotation_rows) { + RustFloatBindingNoPrimitive { target_name: t } => t == "f80" + _ => false + } +} + +// ---- binary64 encoding admission (§3.4 widths) ---- + +test fn w_encoding_with_ten_bit_exponent_field_refuses() -> Bool { + match binary_interchange_encoding(format: binary64, s: false, e: bits(b: false, n: 10), t: bits(b: false, n: 52)) { + EncodingRefused { refusal: BiasedExponentFieldWidth { expected_w: w, observed: o } } => w == 11 && o == 10 + _ => false + } +} + +test fn w_encoding_with_short_trailing_significand_refuses() -> Bool { + match binary_interchange_encoding(format: binary64, s: false, e: bits(b: false, n: 11), t: bits(b: false, n: 23)) { + EncodingRefused { refusal: TrailingSignificandFieldWidth { expected_t: t, observed: o } } => t == 52 && o == 23 + _ => false + } +} + +test fn w_every_named_value_is_admitted() -> Bool { + admitted(a: binary_interchange_encoding(format: binary64, s: false, e: bits(b: true, n: 11), t: concat([true], bits(b: false, n: 51)))) + && admitted(a: binary_interchange_encoding(format: binary64, s: false, e: concat(bits(b: true, n: 10), [false]), t: bits(b: true, n: 52))) +} + +// ---- §5.7.2 class ---- + +test fn w_class_separates_quiet_and_signaling_nan() -> Bool { + class(x: quiet_nan()) == QuietNaN && class(x: signaling_nan()) == SignalingNaN +} + +test fn w_class_names_subnormal_zero_normal_infinity() -> Bool { + class(x: smallest_subnormal()) == PositiveSubnormal + && class(x: minus_zero()) == NegativeZero + && class(x: one()) == PositiveNormal + && class(x: plus_infinity()) == PositiveInfinity +} + +// ---- §5.11 comparison: NaN is unordered, never ordered ---- + +test fn w_nan_is_unordered_against_every_operand() -> Bool { + is_unordered(a: quiet_nan(), b: one()) + && is_unordered(a: one(), b: signaling_nan()) + && is_unordered(a: quiet_nan(), b: quiet_nan()) + && is_unordered(a: plus_infinity(), b: quiet_nan()) +} + +test fn w_finite_order_follows_value() -> Bool { + is_ordered_as(a: one(), b: two(), expected: Less) + && is_ordered_as(a: two(), b: one(), expected: Greater) + && is_ordered_as(a: minus_one(), b: one(), expected: Less) + && is_ordered_as(a: minus_one(), b: minus_zero(), expected: Less) +} + +test fn w_signed_zeros_compare_equal() -> Bool { + is_ordered_as(a: plus_zero(), b: minus_zero(), expected: Equal) +} + +test fn w_infinities_bound_every_finite_value() -> Bool { + is_ordered_as(a: max_finite(), b: plus_infinity(), expected: Less) + && is_ordered_as(a: minus_infinity(), b: minus_one(), expected: Less) + && is_ordered_as(a: smallest_subnormal(), b: plus_zero(), expected: Greater) +} diff --git a/src/v2/std/float.dag b/src/v2/std/float.dag deleted file mode 100644 index 8a1f471ad44..00000000000 --- a/src/v2/std/float.dag +++ /dev/null @@ -1,173 +0,0 @@ -module v2.std.float - -import v2.std.algebra { Ordering, Less, Equal, Greater } -import v2.std.diagnostic { Diagnostic, Outcome, invariant_port_locus, Unavailable, UserInputBoundary, Accepted, None, diagnostics_singleton } -import v2.std.logic { Bool } -import v2.std.machine { Bit, Word32, Word64 } -import v2.std.nat { Nat, nat_compare, is_zero } -import v2.std.node { Symbol } -type Float32Interchange = Word32 -type Float64Interchange = Word64 - -type FloatSpecial - = QuietNan - | SignalingNan - | PosInfinity - | NegInfinity - -type FloatBody - = Finite { - sign: Bit - biased_exponent: v2.std.nat.Nat - trailing_significand: v2.std.nat.Nat - } - | NonFinite { tag: FloatSpecial } - -type Binary32 { - body: FloatBody -} - -type Binary64 { - body: FloatBody -} -type Float = Binary64 -fn sign_rank_lex(s: Bit) -> v2.std.nat.Nat { - match s { - true => v2.std.nat.Zero - false => v2.std.nat.Succ { prev: v2.std.nat.Zero } - } -} -fn ordering_invert(o: Ordering) -> Ordering { - match o { - Less => Greater - Greater => Less - Equal => Equal - } -} -fn float_finite_unsigned_field_order( - ea: v2.std.nat.Nat, - fa: v2.std.nat.Nat, - eb: v2.std.nat.Nat, - fb: v2.std.nat.Nat, -) -> Ordering { - let o2 = nat_compare(a: ea, b: eb) - match o2 { - Less => Less - Greater => Greater - Equal => nat_compare(a: fa, b: fb) - } -} - -fn float_special_rank(t: FloatSpecial) -> v2.std.nat.Nat { - match t { - NegInfinity => v2.std.nat.Zero - PosInfinity => v2.std.nat.Succ { prev: v2.std.nat.Zero } - QuietNan => v2.std.nat.Succ { prev: v2.std.nat.Succ { prev: v2.std.nat.Zero } } - SignalingNan => v2.std.nat.Succ { prev: v2.std.nat.Succ { prev: v2.std.nat.Succ { prev: v2.std.nat.Zero } } } - } -} - -fn float_body_is_nan(x: FloatBody) -> Bool { - match x { - NonFinite { tag: QuietNan } => true - NonFinite { tag: SignalingNan } => true - _ => false - } -} -fn float_finite_magnitude_zero(e: v2.std.nat.Nat, f: v2.std.nat.Nat) -> Bool { - is_zero(e) && is_zero(f) -} -fn float_body_compare_semantic_total(a: FloatBody, b: FloatBody) -> Ordering { - match a { - Finite { sign: sa, biased_exponent: ea, trailing_significand: fa } => match b { - Finite { sign: sb, biased_exponent: eb, trailing_significand: fb } => { - let o = nat_compare(a: sign_rank_lex(sa), b: sign_rank_lex(sb)) - match o { - Less => Less - Greater => Greater - Equal => { - let mag = float_finite_unsigned_field_order( - ea: ea, - fa: fa, - eb: eb, - fb: fb, - ) - match sa { - true => ordering_invert(o: mag) - false => mag - } - } - } - } - NonFinite { tag: tb } => match tb { - NegInfinity => Greater - _ => Less - } - } - NonFinite { tag: ta } => match b { - Finite { - sign: sb - biased_exponent: eb - trailing_significand: fb - } => match ta { - NegInfinity => Less - _ => Greater - } - NonFinite { tag: tb } => nat_compare( - a: float_special_rank(ta), - b: float_special_rank(tb) - ) - } - } -} -fn float_body_compare_ieee_ordered_outcome(a: FloatBody, b: FloatBody) -> Outcome { - if float_body_is_nan(a) { - float_ordered_compare_nan_rejected() - } else { - if float_body_is_nan(b) { - float_ordered_compare_nan_rejected() - } else { - Accepted { value: match a { - Finite { sign: sa, biased_exponent: ea, trailing_significand: fa } => match b { - Finite { sign: sb, biased_exponent: eb, trailing_significand: fb } => { - if float_finite_magnitude_zero(e: ea, f: fa) - && float_finite_magnitude_zero(e: eb, f: fb) - { - Equal - } else { - float_body_compare_semantic_total(a: a, b: b) - } - } - NonFinite { tag: tb } => float_body_compare_semantic_total(a: a, b: b) - } - NonFinite { tag: ta } => float_body_compare_semantic_total(a: a, b: b) - }, diagnostics: None } - } - } -} -fn float_ordered_compare_nan_rejected() -> Outcome { - Rejected { diagnostics: diagnostics_singleton(d: Diagnostic { - reason: ^float_totalizer_reason_ieee754_nan_unordered, - at: invariant_port_locus(port: ^float_totalizer_port_ieee754_nan_totalizer, invariant: ^float_totalizer_reason_ieee754_nan_unordered), - correction: Unavailable { reason: UserInputBoundary }, - }) } -} -fn float_ieee_ordered_compare_outcome(a: Float, b: Float) -> Outcome { - float_body_compare_ieee_ordered_outcome(a: a.body, b: b.body) -} -fn float_ordered_compare_tier2(a: Float, b: Float) -> Outcome { - float_ieee_ordered_compare_outcome(a: a, b: b) -} - -type NaNPropagation - = QuietNaNPropagation - | SignalingNaNEnabled - -type InfPropagation - = IEEEInfinityPropagation - | SaturatingInf - -type FloatExceptionDisposition - = SilentDefaultResult - | TrapEnabled - | FastMathUndefined From 64b8081e630db65797e6ca77dd085edfba6e49de Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Mon, 28 Sep 2026 14:32:01 +0000 Subject: [PATCH 02/21] kernel_type_denotation: one KernelTypeName carrier, admitted only via is_kernel_type --- dag/std/kernel_type_denotation.dag | 45 +++++++++++++------ ...float_binary64_denotation_witness_test.dag | 19 ++++++-- 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/dag/std/kernel_type_denotation.dag b/dag/std/kernel_type_denotation.dag index 80c120af270..77354ce0fcf 100644 --- a/dag/std/kernel_type_denotation.dag +++ b/dag/std/kernel_type_denotation.dag @@ -20,24 +20,43 @@ import extdeps.standards.ieee_754_2019 { BinaryInterchangeFormat, binary64 } type KernelTypeMeaning = BinaryInterchangeFormatMeaning { format: BinaryInterchangeFormat } -// A key is a kernel name only by membership in std.types kernel_type_set, read through -// is_kernel_type rather than restated. RUNG: mechanically preventable -- the record constructor of -// KernelTypeDenotation stays public; every row below is built through kernel_type_denotation_row, -// and kernel_type_denotation_rows_admitted is the executed check that none was refused. +// A KERNEL TYPE NAME, admitted only through std.types is_kernel_type (kernel_type_set is read, not +// restated). This is the ONE carrier for "a name the kernel rosters": every consumer that needs one +// -- this module's denotation rows, std.target_representation's kernel-parent variants -- takes a +// KernelTypeName rather than a String with its own membership check. RUNG: mechanically +// preventable -- the record constructor stays public (the language has no module-private +// constructor); kernel_type_name is the admitting route, and a String that is not a kernel name +// yields NotAKernelTypeName, never a KernelTypeName. +type KernelTypeName { + name: String +} + +type KernelTypeNameAdmission + = KernelTypeNameAdmitted { kernel_name: KernelTypeName } + | NotAKernelTypeName { name: String } + +fn kernel_type_name(name: String) -> KernelTypeNameAdmission { + if is_kernel_type(name: name) { + KernelTypeNameAdmitted { kernel_name: KernelTypeName { name: name } } + } else { + NotAKernelTypeName { name: name } + } +} + type KernelTypeDenotation { - kernel_name: String + kernel_name: KernelTypeName meaning: KernelTypeMeaning } type KernelTypeDenotationAdmission = KernelTypeDenotationAdmitted { denotation: KernelTypeDenotation } - | NotAKernelTypeName { name: String } + | KernelTypeDenotationRefused { refusal: KernelTypeNameAdmission } fn kernel_type_denotation_row(kernel_name: String, meaning: KernelTypeMeaning) -> KernelTypeDenotationAdmission { - if is_kernel_type(name: kernel_name) { - KernelTypeDenotationAdmitted { denotation: KernelTypeDenotation { kernel_name: kernel_name, meaning: meaning } } - } else { - NotAKernelTypeName { name: kernel_name } + let admission = kernel_type_name(name: kernel_name) + match admission { + KernelTypeNameAdmitted { kernel_name: k } => KernelTypeDenotationAdmitted { denotation: KernelTypeDenotation { kernel_name: k, meaning: meaning } } + NotAKernelTypeName { name: _ } => KernelTypeDenotationRefused { refusal: admission } } } @@ -48,7 +67,7 @@ data kernel_type_denotation_rows: List = [ fn kernel_type_denotation_rows_admitted(rows: List) -> Bool { rows |> all(r => match r { KernelTypeDenotationAdmitted { denotation: _ } => true - NotAKernelTypeName { name: _ } => false + KernelTypeDenotationRefused { refusal: _ } => false }) } @@ -62,8 +81,8 @@ fn kernel_type_denotation_for(name: String, rows: List fold(init: KernelTypeUndenoted { name: name }, f: (acc, r) => match acc { KernelTypeDenoted { meaning: _ } => acc KernelTypeUndenoted { name: _ } => match r { - KernelTypeDenotationAdmitted { denotation: d } => if d.kernel_name == name { KernelTypeDenoted { meaning: d.meaning } } else { acc } - NotAKernelTypeName { name: _ } => acc + KernelTypeDenotationAdmitted { denotation: d } => if d.kernel_name.name == name { KernelTypeDenoted { meaning: d.meaning } } else { acc } + KernelTypeDenotationRefused { refusal: _ } => acc } }) } diff --git a/dag/test/claim/kernel_float_binary64_denotation_witness_test.dag b/dag/test/claim/kernel_float_binary64_denotation_witness_test.dag index dff874b6706..8f495e23f6f 100644 --- a/dag/test/claim/kernel_float_binary64_denotation_witness_test.dag +++ b/dag/test/claim/kernel_float_binary64_denotation_witness_test.dag @@ -11,7 +11,8 @@ import extdeps.standards.ieee_754_2019 { QuietNaN, SignalingNaN, PositiveSubnormal, NegativeZero, PositiveNormal, PositiveInfinity } import std.kernel_type_denotation { - KernelTypeDenotationAdmission, KernelTypeDenotationAdmitted, NotAKernelTypeName, + KernelTypeDenotationAdmission, KernelTypeDenotationAdmitted, KernelTypeDenotationRefused, + KernelTypeNameAdmitted, NotAKernelTypeName, kernel_type_name, KernelTypeDenotation, BinaryInterchangeFormatMeaning, kernel_type_denotation_row, kernel_type_denotation_rows, kernel_type_denotation_rows_admitted } @@ -96,9 +97,21 @@ test fn w_planted_float_denotes_binary32_refuses_f64() -> Bool { test fn w_non_kernel_name_key_is_refused() -> Bool { match kernel_type_denotation_row(kernel_name: "Real", meaning: BinaryInterchangeFormatMeaning { format: binary64 }) { - NotAKernelTypeName { name: n } => n == "Real" - KernelTypeDenotationAdmitted { denotation: _ } => false + KernelTypeDenotationRefused { refusal: NotAKernelTypeName { name: n } } => n == "Real" + _ => false + } +} + +test fn w_kernel_type_name_admits_only_rostered_names() -> Bool { + let float_admitted = match kernel_type_name(name: "Float") { + KernelTypeNameAdmitted { kernel_name: k } => k.name == "Float" + NotAKernelTypeName { name: _ } => false + } + let binary64_refused = match kernel_type_name(name: "Binary64") { + NotAKernelTypeName { name: n } => n == "Binary64" + KernelTypeNameAdmitted { kernel_name: _ } => false } + float_admitted && binary64_refused } test fn w_table_with_a_non_kernel_key_is_not_admitted() -> Bool { From 59d8efb428c9741789b6313cb8658bb514f9a6b3 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Mon, 28 Sep 2026 14:46:29 +0000 Subject: [PATCH 03/21] Split KernelTypeName into leaf std.kernel_type_name (keeps IEEE model out of the seed closure); fix stale std.float citation in emit_rust annotation --- dag/std/kernel_type_denotation.dag | 26 ++-------------- dag/std/kernel_type_name.dag | 31 +++++++++++++++++++ ...float_binary64_denotation_witness_test.dag | 2 +- src/v1/05_emit_rust.dag | 7 +++-- 4 files changed, 38 insertions(+), 28 deletions(-) create mode 100644 dag/std/kernel_type_name.dag diff --git a/dag/std/kernel_type_denotation.dag b/dag/std/kernel_type_denotation.dag index 77354ce0fcf..07fc4d364a3 100644 --- a/dag/std/kernel_type_denotation.dag +++ b/dag/std/kernel_type_denotation.dag @@ -1,6 +1,7 @@ module std.kernel_type_denotation -import std.types { Bool, List, String, is_kernel_type } +import std.types { Bool, List, String } +import std.kernel_type_name { KernelTypeName, KernelTypeNameAdmission, KernelTypeNameAdmitted, NotAKernelTypeName, kernel_type_name } import extdeps.standards.ieee_754_2019 { BinaryInterchangeFormat, binary64 } // WHAT A KERNEL TYPE NAME MEANS, INDEPENDENT OF ANY TARGET. The kernel names are rostered in @@ -20,29 +21,6 @@ import extdeps.standards.ieee_754_2019 { BinaryInterchangeFormat, binary64 } type KernelTypeMeaning = BinaryInterchangeFormatMeaning { format: BinaryInterchangeFormat } -// A KERNEL TYPE NAME, admitted only through std.types is_kernel_type (kernel_type_set is read, not -// restated). This is the ONE carrier for "a name the kernel rosters": every consumer that needs one -// -- this module's denotation rows, std.target_representation's kernel-parent variants -- takes a -// KernelTypeName rather than a String with its own membership check. RUNG: mechanically -// preventable -- the record constructor stays public (the language has no module-private -// constructor); kernel_type_name is the admitting route, and a String that is not a kernel name -// yields NotAKernelTypeName, never a KernelTypeName. -type KernelTypeName { - name: String -} - -type KernelTypeNameAdmission - = KernelTypeNameAdmitted { kernel_name: KernelTypeName } - | NotAKernelTypeName { name: String } - -fn kernel_type_name(name: String) -> KernelTypeNameAdmission { - if is_kernel_type(name: name) { - KernelTypeNameAdmitted { kernel_name: KernelTypeName { name: name } } - } else { - NotAKernelTypeName { name: name } - } -} - type KernelTypeDenotation { kernel_name: KernelTypeName meaning: KernelTypeMeaning diff --git a/dag/std/kernel_type_name.dag b/dag/std/kernel_type_name.dag new file mode 100644 index 00000000000..43d0591c629 --- /dev/null +++ b/dag/std/kernel_type_name.dag @@ -0,0 +1,31 @@ +module std.kernel_type_name + +import std.types { String, is_kernel_type } + +// A LEAF ON PURPOSE: it imports std.types and nothing else, so the v1 seed's closure (which reaches +// this carrier through std.target_representation) does not also reach the external models that +// std.kernel_type_denotation cites. What a kernel name MEANS lives there; that a String IS a kernel +// name lives here, once. +// +// A KERNEL TYPE NAME, admitted only through std.types is_kernel_type (kernel_type_set is read, not +// restated). This is the ONE carrier for "a name the kernel rosters": every consumer that needs one +// -- this module's denotation rows, std.target_representation's kernel-parent variants -- takes a +// KernelTypeName rather than a String with its own membership check. RUNG: mechanically +// preventable -- the record constructor stays public (the language has no module-private +// constructor); kernel_type_name is the admitting route, and a String that is not a kernel name +// yields NotAKernelTypeName, never a KernelTypeName. +type KernelTypeName { + name: String +} + +type KernelTypeNameAdmission + = KernelTypeNameAdmitted { kernel_name: KernelTypeName } + | NotAKernelTypeName { name: String } + +fn kernel_type_name(name: String) -> KernelTypeNameAdmission { + if is_kernel_type(name: name) { + KernelTypeNameAdmitted { kernel_name: KernelTypeName { name: name } } + } else { + NotAKernelTypeName { name: name } + } +} diff --git a/dag/test/claim/kernel_float_binary64_denotation_witness_test.dag b/dag/test/claim/kernel_float_binary64_denotation_witness_test.dag index 8f495e23f6f..0bea7f0b2cf 100644 --- a/dag/test/claim/kernel_float_binary64_denotation_witness_test.dag +++ b/dag/test/claim/kernel_float_binary64_denotation_witness_test.dag @@ -10,9 +10,9 @@ import extdeps.standards.ieee_754_2019 { binary_interchange_encoding, class, compare_quiet, Ordered, Unordered, QuietNaN, SignalingNaN, PositiveSubnormal, NegativeZero, PositiveNormal, PositiveInfinity } +import std.kernel_type_name { KernelTypeNameAdmitted, NotAKernelTypeName, kernel_type_name } import std.kernel_type_denotation { KernelTypeDenotationAdmission, KernelTypeDenotationAdmitted, KernelTypeDenotationRefused, - KernelTypeNameAdmitted, NotAKernelTypeName, kernel_type_name, KernelTypeDenotation, BinaryInterchangeFormatMeaning, kernel_type_denotation_row, kernel_type_denotation_rows, kernel_type_denotation_rows_admitted } diff --git a/src/v1/05_emit_rust.dag b/src/v1/05_emit_rust.dag index 7b2dd1fdb9d..3436d5df369 100644 --- a/src/v1/05_emit_rust.dag +++ b/src/v1/05_emit_rust.dag @@ -406,9 +406,10 @@ fn render_rust_arrow_type_in_scope(n: Node, generic_param_names: List, s // declaring module denotes the kernel post-#9813, which the host-carrier arm ahead of this one // answers. SCOPE: keyed to // the String spelling because String is the kernel-named STRUCTURAL text carrier with a measured -// error population; std.integer Int and std.float Float realize NATIVELY via -// numeric_realization_declaring_modules, so peeling them would render the algebra structure -// against i64 values -- their field-position rendering is a separate class with its own evidence. +// error population; std.integer Int realizes NATIVELY via numeric_realization_declaring_modules +// and kernel Float (no .dag declaration since the Float de-fork) via its kernel checkpoint row, so +// peeling them would render algebra structure against i64/f64 values -- their field-position +// rendering is a separate class with its own evidence. fn rust_overlayless_alias_leaf_requires_peel(env: TypeEnv, n: Node) -> Bool { let name = authored_name_at(source_indices: env.source_indices, node: n) n.connective == NoConnective From 15f9e2553ac3f728a91d341b72d699f4db9e42d3 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Mon, 28 Sep 2026 15:19:54 +0000 Subject: [PATCH 04/21] ieee_754_2019: cite helper takes NonEmptyStr (literals checked at call site); claim lists Ordering import --- dag/extdeps/standards/ieee_754_2019.dag | 6 +++--- .../claim/kernel_float_binary64_denotation_witness_test.dag | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dag/extdeps/standards/ieee_754_2019.dag b/dag/extdeps/standards/ieee_754_2019.dag index a603c4f5957..8825fb883af 100644 --- a/dag/extdeps/standards/ieee_754_2019.dag +++ b/dag/extdeps/standards/ieee_754_2019.dag @@ -87,14 +87,14 @@ type Ieee754ClauseCitation { spec_term: NonEmptyStr } -fn ieee_754_2019_cite(decl_name: String, clause: String, spec_term: String) -> Ieee754ClauseCitation { +fn ieee_754_2019_cite(decl_name: String, clause: NonEmptyStr, spec_term: NonEmptyStr) -> Ieee754ClauseCitation { Ieee754ClauseCitation { citation: FactCitation { fact: decl_ref(module_path: "extdeps.standards.ieee_754_2019", decl_name: decl_name), authority: extdeps_external_authority_anchor }, - clause: clause as NonEmptyStr, - spec_term: spec_term as NonEmptyStr + clause: clause, + spec_term: spec_term } } diff --git a/dag/test/claim/kernel_float_binary64_denotation_witness_test.dag b/dag/test/claim/kernel_float_binary64_denotation_witness_test.dag index 0bea7f0b2cf..554e021af5c 100644 --- a/dag/test/claim/kernel_float_binary64_denotation_witness_test.dag +++ b/dag/test/claim/kernel_float_binary64_denotation_witness_test.dag @@ -2,7 +2,7 @@ module test.claim.kernel_float_binary64_denotation_witness_test import std.types { Bool, Int, List, String } import std.bit { Bit } -import std.algebra { Less, Equal, Greater } +import std.algebra { Ordering, Less, Equal, Greater } import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly } import extdeps.standards.ieee_754_2019 { BinaryInterchangeEncoding, EncodingAdmission, EncodingAdmitted, EncodingRefused, @@ -61,7 +61,7 @@ fn smallest_subnormal() -> BinaryInterchangeEncoding { enc(s: false, e: bits(b: fn quiet_nan() -> BinaryInterchangeEncoding { enc(s: false, e: bits(b: true, n: 11), t: concat([true], bits(b: false, n: 51))) } fn signaling_nan() -> BinaryInterchangeEncoding { enc(s: false, e: bits(b: true, n: 11), t: concat(bits(b: false, n: 51), [true])) } -fn is_ordered_as(a: BinaryInterchangeEncoding, b: BinaryInterchangeEncoding, expected: std.algebra.Ordering) -> Bool { +fn is_ordered_as(a: BinaryInterchangeEncoding, b: BinaryInterchangeEncoding, expected: Ordering) -> Bool { match compare_quiet(a: a, b: b) { Ordered { ordering: o } => o == expected Unordered => false From 5180d42d5b4b8d33684440ea9c751d1f2a6bfa94 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Mon, 28 Sep 2026 15:20:38 +0000 Subject: [PATCH 05/21] defork census: Float resolution cites #12547 --- dag/gunbc/defork_type_name_census.dag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dag/gunbc/defork_type_name_census.dag b/dag/gunbc/defork_type_name_census.dag index b18bcb5b759..fed07fb2b9d 100644 --- a/dag/gunbc/defork_type_name_census.dag +++ b/dag/gunbc/defork_type_name_census.dag @@ -286,7 +286,7 @@ data defork_census_resolved: List = [ ResolvedSharedTypeName { names: ["Float"], resolution: ResolvedByRehomingBothToExtdeps { authority: "extdeps.standards.ieee_754_2019 binary64", citation: "IEEE 754-2019 §3.6 (operator ruling relayed 2026-09-28): `std.float` (Float = Float64, uncited) and `v2.std.float` (Float = Binary64) both deleted; kernel Float's meaning is the `std.kernel_type_denotation` row, not a std alias" }, - change: 0 + change: 12547 }, ResolvedSharedTypeName { names: ["ProjectionKind"], From f99d50386e62be82339e1b5406b295e68d545cad Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Mon, 28 Sep 2026 15:34:04 +0000 Subject: [PATCH 06/21] rust primitives: drop unimported 'any' (UnimportedBareProvider); fold over a helper instead --- dag/extdeps/languages/rust/primitives.dag | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/dag/extdeps/languages/rust/primitives.dag b/dag/extdeps/languages/rust/primitives.dag index 4d83d82aca3..57dc3007641 100644 --- a/dag/extdeps/languages/rust/primitives.dag +++ b/dag/extdeps/languages/rust/primitives.dag @@ -154,10 +154,14 @@ type RustFloatBindingVerdict | RustFloatBindingNoPrimitive { target_name: String } fn rust_grounding_primitive_named(target_name: String) -> Bool { - rust_grounding_primitives |> any(p => match p { - IntegerPrimitive { target_name: n, algebra: _, carrier: _, range_min_inclusive: _, range_max_inclusive: _, is_copy: _, overflow: _ } => false + rust_grounding_primitives |> fold(init: false, f: (found, p) => if found { true } else { rust_primitive_is_float_named(p: p, target_name: target_name) }) +} + +fn rust_primitive_is_float_named(p: RustPrimitive, target_name: String) -> Bool { + match p { + IntegerPrimitive { target_name: _, algebra: _, carrier: _, range_min_inclusive: _, range_max_inclusive: _, is_copy: _, overflow: _ } => false NonIntegerPrimitive { target_name: n, algebra: a, carrier: _, is_copy: _ } => n == target_name && a == ApproximateFieldAlgebra - }) + } } // The denotation rows are a parameter so a claim can plant a mismatched table at this interface; From 4ebb3c4ae374a50b16828e153042fe6ed6f5f329 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Mon, 28 Sep 2026 15:45:34 +0000 Subject: [PATCH 07/21] RustFloatBinding holds the KernelTypeName admission; denotation lookup keyed on KernelTypeName; non-kernel-name RED --- dag/extdeps/languages/rust/primitives.dag | 44 ++++++++++++------- dag/std/kernel_type_denotation.dag | 12 ++--- ...float_binary64_denotation_witness_test.dag | 19 ++++++-- 3 files changed, 49 insertions(+), 26 deletions(-) diff --git a/dag/extdeps/languages/rust/primitives.dag b/dag/extdeps/languages/rust/primitives.dag index 57dc3007641..ab0f195ab61 100644 --- a/dag/extdeps/languages/rust/primitives.dag +++ b/dag/extdeps/languages/rust/primitives.dag @@ -4,6 +4,7 @@ import std.algebra { OrderedRing, Semiring, BooleanAlgebra } import std.bit { Bit, Byte, Word16, Word32, Word64, Word128 } import extdeps.external_authority { ExternalAuthority } import extdeps.uri { Uri, Https } +import std.kernel_type_name { KernelTypeName, KernelTypeNameAdmission, KernelTypeNameAdmitted, NotAKernelTypeName, kernel_type_name } import std.kernel_type_denotation { KernelTypeDenotationAdmission, KernelTypeDenoted, KernelTypeUndenoted, BinaryInterchangeFormatMeaning, kernel_type_denotation_for @@ -127,8 +128,11 @@ data rust_std_f64_anchor: ExternalAuthority = ExternalAuthority { } } +// kernel_name is the ADMISSION, not a String: the row is built through std.kernel_type_name +// kernel_type_name, so a binding keyed on a name the kernel does not roster is refused by the +// verdict rather than silently undenoted. type RustFloatBinding { - kernel_name: String + kernel_name: KernelTypeNameAdmission target_name: String authority: ExternalAuthority radix: Int @@ -138,7 +142,7 @@ type RustFloatBinding { } data rust_f64_binding: RustFloatBinding = RustFloatBinding { - kernel_name: "Float", + kernel_name: kernel_type_name(name: "Float"), target_name: "f64", authority: rust_std_f64_anchor, radix: 2, @@ -149,8 +153,9 @@ data rust_f64_binding: RustFloatBinding = RustFloatBinding { type RustFloatBindingVerdict = RustFloatBindingHolds - | RustFloatBindingUndenoted { kernel_name: String } - | RustFloatBindingDisagrees { kernel_name: String, target_name: String } + | RustFloatBindingNotAKernelName { name: String } + | RustFloatBindingUndenoted { kernel_name: KernelTypeName } + | RustFloatBindingDisagrees { kernel_name: KernelTypeName, target_name: String } | RustFloatBindingNoPrimitive { target_name: String } fn rust_grounding_primitive_named(target_name: String) -> Bool { @@ -170,18 +175,25 @@ fn rust_float_binding_verdict(b: RustFloatBinding, denotations: List RustFloatBindingUndenoted { kernel_name: n } - KernelTypeDenoted { meaning: BinaryInterchangeFormatMeaning { format: f } } => - if b.radix == 2 - && b.mantissa_digits == f.p - && b.max_exp == f.emax + 1 - && b.min_exp == 2 - f.emax - { - RustFloatBindingHolds - } else { - RustFloatBindingDisagrees { kernel_name: b.kernel_name, target_name: b.target_name } - } + match b.kernel_name { + NotAKernelTypeName { name: n } => RustFloatBindingNotAKernelName { name: n } + KernelTypeNameAdmitted { kernel_name: k } => rust_float_binding_against_denotation(b: b, kernel_name: k, denotations: denotations) } } } + +fn rust_float_binding_against_denotation(b: RustFloatBinding, kernel_name: KernelTypeName, denotations: List) -> RustFloatBindingVerdict { + match kernel_type_denotation_for(kernel_name: kernel_name, rows: denotations) { + KernelTypeUndenoted { kernel_name: k } => RustFloatBindingUndenoted { kernel_name: k } + KernelTypeDenoted { meaning: BinaryInterchangeFormatMeaning { format: f } } => + if b.radix == 2 + && b.mantissa_digits == f.p + && b.max_exp == f.emax + 1 + && b.min_exp == 2 - f.emax + { + RustFloatBindingHolds + } else { + RustFloatBindingDisagrees { kernel_name: kernel_name, target_name: b.target_name } + } + } +} diff --git a/dag/std/kernel_type_denotation.dag b/dag/std/kernel_type_denotation.dag index 07fc4d364a3..e905763874b 100644 --- a/dag/std/kernel_type_denotation.dag +++ b/dag/std/kernel_type_denotation.dag @@ -51,15 +51,15 @@ fn kernel_type_denotation_rows_admitted(rows: List) -> KernelTypeDenotationLookup { - rows |> fold(init: KernelTypeUndenoted { name: name }, f: (acc, r) => match acc { +// production reading is kernel_type_denotation_for(kernel_name, rows: kernel_type_denotation_rows). +fn kernel_type_denotation_for(kernel_name: KernelTypeName, rows: List) -> KernelTypeDenotationLookup { + rows |> fold(init: KernelTypeUndenoted { kernel_name: kernel_name }, f: (acc, r) => match acc { KernelTypeDenoted { meaning: _ } => acc - KernelTypeUndenoted { name: _ } => match r { - KernelTypeDenotationAdmitted { denotation: d } => if d.kernel_name.name == name { KernelTypeDenoted { meaning: d.meaning } } else { acc } + KernelTypeUndenoted { kernel_name: _ } => match r { + KernelTypeDenotationAdmitted { denotation: d } => if d.kernel_name.name == kernel_name.name { KernelTypeDenoted { meaning: d.meaning } } else { acc } KernelTypeDenotationRefused { refusal: _ } => acc } }) diff --git a/dag/test/claim/kernel_float_binary64_denotation_witness_test.dag b/dag/test/claim/kernel_float_binary64_denotation_witness_test.dag index 554e021af5c..cc9ecf3f5d6 100644 --- a/dag/test/claim/kernel_float_binary64_denotation_witness_test.dag +++ b/dag/test/claim/kernel_float_binary64_denotation_witness_test.dag @@ -18,7 +18,7 @@ import std.kernel_type_denotation { } import extdeps.languages.rust.primitives { RustFloatBinding, RustFloatBindingHolds, RustFloatBindingDisagrees, RustFloatBindingUndenoted, - RustFloatBindingNoPrimitive, rust_f64_binding, rust_float_binding_verdict + RustFloatBindingNoPrimitive, RustFloatBindingNotAKernelName, rust_f64_binding, rust_float_binding_verdict } data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly @@ -90,7 +90,7 @@ test fn w_rust_f64_holds_against_what_float_denotes() -> Bool { test fn w_planted_float_denotes_binary32_refuses_f64() -> Bool { let planted = [kernel_type_denotation_row(kernel_name: "Float", meaning: BinaryInterchangeFormatMeaning { format: binary32 })] match rust_float_binding_verdict(b: rust_f64_binding, denotations: planted) { - RustFloatBindingDisagrees { kernel_name: k, target_name: t } => k == "Float" && t == "f64" + RustFloatBindingDisagrees { kernel_name: k, target_name: t } => k.name == "Float" && t == "f64" _ => false } } @@ -121,14 +121,14 @@ test fn w_table_with_a_non_kernel_key_is_not_admitted() -> Bool { test fn w_undenoted_kernel_name_refuses_the_binding() -> Bool { match rust_float_binding_verdict(b: rust_f64_binding, denotations: []) { - RustFloatBindingUndenoted { kernel_name: k } => k == "Float" + RustFloatBindingUndenoted { kernel_name: k } => k.name == "Float" _ => false } } test fn w_binding_to_an_absent_primitive_refuses() -> Bool { let planted = RustFloatBinding { - kernel_name: "Float", target_name: "f80", authority: rust_f64_binding.authority, + kernel_name: kernel_type_name(name: "Float"), target_name: "f80", authority: rust_f64_binding.authority, radix: 2, mantissa_digits: 53, max_exp: 1024, min_exp: -1021 } match rust_float_binding_verdict(b: planted, denotations: kernel_type_denotation_rows) { @@ -196,3 +196,14 @@ test fn w_infinities_bound_every_finite_value() -> Bool { && is_ordered_as(a: minus_infinity(), b: minus_one(), expected: Less) && is_ordered_as(a: smallest_subnormal(), b: plus_zero(), expected: Greater) } + +test fn w_binding_keyed_on_a_non_kernel_name_refuses() -> Bool { + let planted = RustFloatBinding { + kernel_name: kernel_type_name(name: "Float64"), target_name: "f64", authority: rust_f64_binding.authority, + radix: 2, mantissa_digits: 53, max_exp: 1024, min_exp: -1021 + } + match rust_float_binding_verdict(b: planted, denotations: kernel_type_denotation_rows) { + RustFloatBindingNotAKernelName { name: n } => n == "Float64" + _ => false + } +} From 42f2322bcf9289108757efaa1c565f420f29367f Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Mon, 28 Sep 2026 16:11:25 +0000 Subject: [PATCH 08/21] Regenerate stage0 gunbc_rust_source_type_bindings.rs (std.float Float row gone; Float verdict ProvenUniqueKernelBinding) --- src/v1/stage0/src/gunbc_rust_source_type_bindings.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/v1/stage0/src/gunbc_rust_source_type_bindings.rs b/src/v1/stage0/src/gunbc_rust_source_type_bindings.rs index 39c9a0f933c..cf75eef61de 100644 --- a/src/v1/stage0/src/gunbc_rust_source_type_bindings.rs +++ b/src/v1/stage0/src/gunbc_rust_source_type_bindings.rs @@ -3,7 +3,7 @@ pub use crate::extdeps_languages_rust_representation::RustRepresentation; use crate::extdeps_languages_rust_representation::RustRepresentation::{ - RustBool, RustF64, RustI64, RustSerdeJsonValue, RustStdString, RustUnit, RustVecU8, + RustBool, RustI64, RustSerdeJsonValue, RustStdString, RustUnit, RustVecU8, }; pub use crate::std_decl_ref::decl_ref; pub use crate::std_decl_ref::DeclarationRef; @@ -37,7 +37,7 @@ pub fn rust_source_binding( pub fn rust_source_type_binding_rows() -> Rc>>> { thread_local! { static CACHED: Rc>>> = { - Rc::new(vec![rust_source_binding("v2.std.node".to_string(), "Symbol".to_string(), RustRepresentation::RustStdString), rust_source_binding("std.types".to_string(), "Secret".to_string(), RustRepresentation::RustStdString), rust_source_binding("std.integer".to_string(), "Int".to_string(), RustRepresentation::RustI64), rust_source_binding("std.float".to_string(), "Float".to_string(), RustRepresentation::RustF64), rust_source_binding("std.types".to_string(), "Bool".to_string(), RustRepresentation::RustBool), rust_source_binding("std.types".to_string(), "Unit".to_string(), RustRepresentation::RustUnit), rust_source_binding("v2.std.cardinality".to_string(), "Unit".to_string(), RustRepresentation::RustUnit), rust_source_binding("std.types".to_string(), "Bytes".to_string(), RustRepresentation::RustVecU8), rust_source_binding("std.types".to_string(), "Json".to_string(), RustRepresentation::RustSerdeJsonValue)]) + Rc::new(vec![rust_source_binding("v2.std.node".to_string(), "Symbol".to_string(), RustRepresentation::RustStdString), rust_source_binding("std.types".to_string(), "Secret".to_string(), RustRepresentation::RustStdString), rust_source_binding("std.integer".to_string(), "Int".to_string(), RustRepresentation::RustI64), rust_source_binding("std.types".to_string(), "Bool".to_string(), RustRepresentation::RustBool), rust_source_binding("std.types".to_string(), "Unit".to_string(), RustRepresentation::RustUnit), rust_source_binding("v2.std.cardinality".to_string(), "Unit".to_string(), RustRepresentation::RustUnit), rust_source_binding("std.types".to_string(), "Bytes".to_string(), RustRepresentation::RustVecU8), rust_source_binding("std.types".to_string(), "Json".to_string(), RustRepresentation::RustSerdeJsonValue)]) }; } CACHED.with(|c: &Rc>>>| c.clone()) @@ -72,9 +72,8 @@ pub fn checkpoint_row_migration_rows() -> Rc>> { }), }), Rc::new(CheckpointRowMigration { dag_name: "Float".to_string(), - disposition: Rc::new(CheckpointRowDisposition::StillBareNameDebt { - reason: "std.float Float has an exact row (RustF64). v2.std.float Float (= Binary64) is answered f64 by the bare-name bypass with no ruling that this is its modeled realization; the kernel float_type mint rides the same row.".to_string(), - restoration_trigger: "The same ruling as Int, for v2.std.float Float; then ProvenUniqueKernelBinding on the f64 primitive token.".to_string(), + disposition: Rc::new(CheckpointRowDisposition::ProvenUniqueKernelBinding { + proof: "No .dag declaration of the spelling Float remains: the Float de-fork (operator ruling relayed 2026-09-28) deleted std.float (Float = Float64 = Real64) and v2.std.float (Float = Binary64) together, and moved the IEEE 754-2019 binary64 facts to extdeps.standards.ieee_754_2019. What reaches this row is the kernel float_type mint and a bare Float in a module importing std.types Float, which is the same kernel name. What kernel Float MEANS is std.kernel_type_denotation (binary64), target-independent; this row states only how Rust spells it. That realization is checked against the denotation by extdeps.languages.rust.primitives rust_float_binding_verdict, and `f64` is a primitive token no use-line can shadow.".to_string(), }), }), Rc::new(CheckpointRowMigration { dag_name: "Bool".to_string(), From 9aaeb66c66f1c39ba5781cadc3f80359d631f537 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Mon, 28 Sep 2026 17:02:00 +0000 Subject: [PATCH 09/21] Regenerate dag-v2-defork-audit projection (Float resolved, #12547) --- docs/plans/dag-v2-defork-audit.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/plans/dag-v2-defork-audit.md b/docs/plans/dag-v2-defork-audit.md index c9e70ad131f..8d3bafc3f5a 100644 --- a/docs/plans/dag-v2-defork-audit.md +++ b/docs/plans/dag-v2-defork-audit.md @@ -192,12 +192,11 @@ Definition-unification (§3b.2: delete the dag record-of-methods *definition*) a ## 2D. The shared type-name census (the one list): the population is derived, the dispositions are authored -**Derived:** every name declared as a `type` (record, coproduct or alias) under both `dag/std` and `src/v2/std`, read from the namespace by `gunbc.defork_type_name_census` `shared_type_names` at generation — **25 names** in this projection. **Authored:** each row's disposition, and — until the frontier below lands — the reading of what each side's body RESOLVES to. The two meet in an identity join by name, refused in both directions (a derived name no row disposes of; a row naming a pair that no longer exists), so this section cannot be generated from a stale disposition. Resolution, not body text, is what separates the classes: `Float = Float64` was byte-identical on both sides and bound two different `Float64`s. A **meaning fork** is one name for materially different concepts (DESIGN §3), resolved by renaming or deleting one side at its declaration, delete-first with no alias, the new name taken from the cited framework. **Frontier:** module-scoped type-reference resolution over the live pool, consumable from .dag: for a type declaration, each name its body references resolved to the declaration it binds in that module's scope (its own declarations, else its imports). When it lands, the three reading columns of every row here are derived from it and the authored readings are deleted; nothing else retires this frontier. Candidate home: `v2.compiler.name_resolve::resolve_with_admission`. +**Derived:** every name declared as a `type` (record, coproduct or alias) under both `dag/std` and `src/v2/std`, read from the namespace by `gunbc.defork_type_name_census` `shared_type_names` at generation — **24 names** in this projection. **Authored:** each row's disposition, and — until the frontier below lands — the reading of what each side's body RESOLVES to. The two meet in an identity join by name, refused in both directions (a derived name no row disposes of; a row naming a pair that no longer exists), so this section cannot be generated from a stale disposition. Resolution, not body text, is what separates the classes: `Float = Float64` was byte-identical on both sides and bound two different `Float64`s. A **meaning fork** is one name for materially different concepts (DESIGN §3), resolved by renaming or deleting one side at its declaration, delete-first with no alias, the new name taken from the cited framework. **Frontier:** module-scoped type-reference resolution over the live pool, consumable from .dag: for a type declaration, each name its body references resolved to the declaration it binds in that module's scope (its own declarations, else its imports). When it lands, the three reading columns of every row here are derived from it and the authored readings are deleted; nothing else retires this frontier. Candidate home: `v2.compiler.name_resolve::resolve_with_admission`. | name(s) | declared in (derived) | dag/std side (authored reading) | src/v2/std side (authored reading) | class (authored) | disposition | | --- | --- | --- | --- | --- | --- | | `NonNegativeInt`, `PositiveInt` | `dag/std/integer.dag`, `src/v2/std/refinement.dag` | `std.integer` — `= Nat` / `= Nat where gt_zero` (refinement of `std.nat` `Nat`) | `v2.std.refinement` — record `refined: Refined` (smart-constructor over `v2.std.integer` `Int`), consumed by the formatter extdeps | MEANING FORK | OPEN — next PR of the de-fork wave (the v2 side has ~40 consumer sites across `v2.extdeps.formatters.*`) | -| `Float` | `dag/std/float.dag`, `src/v2/std/float.dag` | `= Float64` → `std.float` `Float64` | `= Binary64` → `v2.std.float` `Binary64` (was `= Float64`, byte-identical text, different referent) | resolution-divergent (text was identical) | AWAITING OPERATOR RULING — seed kernel name — out of scope for the wave | | `String` | `dag/std/string_type.dag`, `src/v2/std/text.dag` | `= FreeMonoid` → `std.algebra` `FreeMonoid`, `std.types` `Char` | same referents | one concept, two declarations (duplicate) | AWAITING OPERATOR RULING — seed kernel name — out of scope for the wave | | `List` | `dag/std/types.dag`, `src/v2/std/collection.dag` | `= FreeMonoid` → `std.algebra` `FreeMonoid` | `= std.algebra.FreeMonoid` → same | one concept, two declarations (duplicate) | AWAITING OPERATOR RULING — seed kernel name — out of scope for the wave | | `Bool` | `dag/std/types.dag`, `src/v2/std/logic.dag` | `std.types` `= True \| False` | `v2.std.logic` `= True \| False` (arms are two more same-name declarations) | one concept, two declarations (duplicate) | AWAITING OPERATOR RULING — seed kernel name — out of scope for the wave | @@ -213,6 +212,7 @@ Definition-unification (§3b.2: delete the dag record-of-methods *definition*) a | name(s) | resolution | change | | --- | --- | --- | +| `Float` | both sides deleted; the concept is homed at `extdeps.standards.ieee_754_2019 binary64` — IEEE 754-2019 §3.6 (operator ruling relayed 2026-09-28): `std.float` (Float = Float64, uncited) and `v2.std.float` (Float = Binary64) both deleted; kernel Float's meaning is the `std.kernel_type_denotation` row, not a std alias | #12547 | | `ProjectionKind` | v2 side deleted — `v2.std.projection` (compiler lens kinds) had zero importers; `std.planar_projection` keeps the name for drawing views | #12252 | | `AlgebraCarrier` | v2 side deleted — `v2.std.rust_leaf_model_claim` type and datum were never read; `std.algebra` `AlgebraProfile` `OrderedRingProfile` already names that structure | #12252 | | `ApproximateField` | v2 side deleted — `v2.std.algebra` ops record had zero consumers; ops come from inhabitance (DESIGN §4) | #12252 | From c3f44b2eb776e3e673743bc2e462f2e91563a798 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Mon, 28 Sep 2026 14:32:44 +0000 Subject: [PATCH 10/21] WIP: native coproduct variant lowering (sources; mirrors regenerated after rebase) Co-Authored-By: Claude Opus 5.5 (1M context) --- dag/extdeps/languages/rust/representation.dag | 10 +- ...epted_source_emits_uncompilable_target.dag | 2 + dag/gunbc/rust_source_type_bindings.dag | 41 ++++- dag/std/target_representation.dag | 151 +++++++++++++++++- ...ative_variant_realization_witness_test.dag | 36 +++++ .../local_bool_coproduct_probe.dag | 20 +++ .../local_true_false_coproduct_probe.dag | 19 +++ .../native_bool_variant_probe.dag | 31 ++++ src/v1/00_core.dag | 7 +- src/v1/02_parse.dag | 11 +- src/v1/04_infer.dag | 87 +++++++--- src/v1/04_patterns.dag | 4 +- src/v1/05_emit.dag | 6 +- src/v1/05_emit_rust.dag | 106 +++++++++--- src/v1/coercion.dag | 31 +++- src/v1/compile.dag | 8 +- src/v1/compiler_tests_rust.dag | 47 ++++++ src/v1/complexity.dag | 10 +- src/v1/dag_collect.dag | 2 +- src/v1/dag_collect_support.dag | 2 +- src/v1/stage0/src/cli_run.rs | 3 +- src/v1/stage0/src/coproduct_reflection.rs | 3 + .../stage0/src/data_initializer_identity.rs | 2 +- .../src/emitted_closure_compile_host.rs | 39 +++++ src/v1/stage0/src/v1_interpreter.rs | 3 +- 25 files changed, 604 insertions(+), 77 deletions(-) create mode 100644 dag/test/claim/native_variant_realization_witness_test.dag create mode 100644 fixtures/fixture_closure_rustc/local_bool_coproduct_probe.dag create mode 100644 fixtures/fixture_closure_rustc/local_true_false_coproduct_probe.dag create mode 100644 fixtures/fixture_closure_rustc/native_bool_variant_probe.dag diff --git a/dag/extdeps/languages/rust/representation.dag b/dag/extdeps/languages/rust/representation.dag index 5d43e55ef37..88bb73a06f2 100644 --- a/dag/extdeps/languages/rust/representation.dag +++ b/dag/extdeps/languages/rust/representation.dag @@ -2,7 +2,7 @@ module extdeps.languages.rust.representation import std.types { List, String, Bool, NonEmptyStr } import std.coercion { TypeCheckpoint } -import std.target_representation { RepresentationSpelling, SourceTypeTargetBinding } +import std.target_representation { RepresentationSpelling, SourceTypeTargetBinding, RepresentationValue } import extdeps.external_authority { ExternalAuthority } import extdeps.uri { Uri, Https } @@ -113,3 +113,11 @@ fn rust_exact_type_checkpoint(binding: SourceTypeTargetBinding none } } + +// THE VALUES A REPRESENTATION HAS, spelled, where a source coproduct's arms realize onto them. Target +// facts only, naming no source declaration: the Rust Reference (types, "Boolean type") gives `bool` +// exactly two values, `true` and `false`. Which source arm means which value is the corpus's fact +// (gunbc.rust_source_type_bindings rust_source_variant_value_rows). +data rust_bool_true_value: RepresentationValue = RepresentationValue { representation: RustBool, value_spelling: "true" as NonEmptyStr } +data rust_bool_false_value: RepresentationValue = RepresentationValue { representation: RustBool, value_spelling: "false" as NonEmptyStr } +data rust_representation_values: List> = [rust_bool_true_value, rust_bool_false_value] diff --git a/dag/gunbc/recurring_failure_mode/accepted_source_emits_uncompilable_target.dag b/dag/gunbc/recurring_failure_mode/accepted_source_emits_uncompilable_target.dag index f6c951c86c2..c79b9b9c82c 100644 --- a/dag/gunbc/recurring_failure_mode/accepted_source_emits_uncompilable_target.dag +++ b/dag/gunbc/recurring_failure_mode/accepted_source_emits_uncompilable_target.dag @@ -298,6 +298,8 @@ data accepted_source_emits_uncompilable_target: RecurringFailureMode = Recurring "OCCURRENCE, 2026-09-24 (wise-hawk-615, routed from stern-raven-24's native App Attest row gunbc#12251, whose emitted crate refused at rustc with 45 errors in three emitter classes and one runtime-library gap). Each was worked to its earliest unjustified boundary (DESIGN section 6b) rather than at the call site. (C) STRING ORDERING: `a < b` over Timestamp, an alias of String (extdeps.standards.rfc_5280 x509_validity_at, gunbc.auth.approval_capability utc_instant_before). Timestamp comparison needed no new typed ordering: the interpreter already orders Strings byte-lexicographically, so the defect was the emitter's. The boundary was the operand classifier v1.compiler.emit_rust rust_operand_realization_of_type, which filed the corpus String as OperandIdentityUnavailable although the type renderer realizes it as the host text carrier by is_host_text_carrier_type; ordering then refused by operator class while `==` on the same operand passed. Repair: std.operator_realization HostRealizationReason gains HostTextCarrier and the classifier reads the renderer's own predicate, so both answer one question once; is_string_comparison admits the four ordering operators through the same host-string seam as equality, and an ordering over an OPTIONAL String refuses at emission (the interpreter has no Null-vs-Str ordering; Option's None-first order would be fabricated). (A) PRESENT BINDING: `match opt { null => a o => b }` bound the whole Option in emitted code (E0308, E0609) while v1.compiler.infer narrows `o` to the present value. ALL THREE match renderings now read the checker's optional_scrutinee_binding_is_present over match_unguarded_absent_arm_index and emit `Some(o)` in exactly that arm, never re-deriving the narrowing: emit_typed_match_arm_strs for ordinary matches, and emit_typed_tco_match_arm for matches inside the tail-call lowering, which the native App Attest run surfaced separately (extdeps.standards.rfc_5280 read_extensions_list, the one error left after the first renderer was repaired); and emit_typed_match's String-literal re-emission (needs_string_from), where a review of this PR found the decision dropped -- there a string-literal arm over an optional scrutinee also emits `Some(ref __s)`, since a literal matches only a present value. (D) OCTETS: std.bytes bytes_octets and utf8_encode_bytes were interpreter-intercepted builtins whose .dag bodies were placeholders -- `[pure_dag_seam_unreachable()]`, a one-element list of `1 / 0`, and `s as Bytes`, a cast no Rust row realizes and which emitted a runtime panic. Both are now declared HostRealizedSeams (self-call bodies, std.primitive_projection rows, std.primitive_identity declarations with SourcePreservingOrder traversal facts, extdeps.languages.rust.emit rt_function_registry rows, v1.runtime_rust bodies); bytes_octets is typed List under the bounded_natural_arithmetic_evaluated_as_unbounded_int ruling, since UInt8 has no emitted realization that holds an octet and bytes_qualified_octets is the one boundary observing the range. Two further links surfaced by execution: a REALIZED seam's self-call was lowered by the name-keyed tail-call rewrite into a non-terminating loop (rust_host_seam_is_realized now exempts it, see host_seam_self_call_diverges_when_its_arm_is_absent), and rustc's deny-by-default unconditional_panic refused every crate reaching std.bytes because of pure_dag_seam_unreachable's constant `1 / 0`. The first cut relaxed that lint for all generated code; review 71098 refused it as widening a real check to admit one placeholder, and the placeholder was the earlier link: pure_dag_seam_unreachable is now a rostered HostRealizedSeam too, refusing in the interpreter with a typed error naming the seam and panicking by name in v1_rt, so the lint stays on. EVIDENCE: the fixture test.fixture.emitted_interpreted_parity.string_order_octets_present_binding exits 0 interpreted and requires the thirteen-field line `T F T F T 6 2962370309 97 0 989 ex none q` -- fields 1-5 string ordering, 6-7 octets, 8-9 the ordinary-match present binding, 10 the tail-call-match present binding, 11-13 the String-literal re-emission -- with a RED control that exits 1 printing the observed line; its emitted crate builds and runs to the same line. The enrolled claim module test.claim.emitter_string_order_present_binding_witness_test carries the emission half: host-string ordering over an alias, the named refusal for an ordering over a String? (which inference admits today, so the arm is reachable), and the present binding in all three match renderings. The integration consumer is `gunbc test //gunbc/instruments:native-app-attest` on gunbc#12251. RUNG unchanged at mitigatable for the class: required CI still neither emits-and-compiles a fixture closure nor executes integration targets, which is this row's existing trigger.", "OCCURRENCE, 2026-09-25 (loyal-boar-23, found by swift-bat-511 on native App Attest P2b): CALLING A LOCALLY BOUND FUNCTION VALUE. extdeps.apple.app_attest first_assertion_refusal folded a List AssertionRefusal?> and called the lambda-bound element `r()`; gunbc#12251 rewrote that one fold as a named AssertionStep sum, leaving the idiom refused everywhere else. The brief placed the defect in emit_rust's callee resolution; re-deriving the chain (DESIGN 6b) placed it three links earlier and found two more downstream. (1) INFERENCE, the earliest unjustified boundary: v1.compiler.infer child_type_node, the total read of a child position's type, returned a child's inferred slot whenever it had one, and an Arrow type node carries its RETURN type there (make_callable_type) -- so the element of List Int> was Int, a lambda parameter bound under it was not callable, and the call refused as \"function 'r' not found in scope\" in `gunbc run` as well as in emission. An Arrow child is now its own type -- landed independently by gunbc#12295 (receipted on arity_proxy_for_callability_misroutes_a_found_local) while this change was in review; this change consumes it rather than restating it. (2) INFERENCE, the list literal: a lambda's typed node carries its BODY type, and a list literal took its first element's type, so [fn() { none }] against List Int?> was typed List; where the declared element is an arrow and any element is a lambda the declared arrow is the element type, every element still judged against it. (3) EMISSION, two value positions of a lambda: a lambda literal in a list was a bare closure (E0308, every closure its own type), and is now the arrow carrier through the record-field row (rust_callable_field_value_wrap) bound at the rendered arrow by a typed let, not an `as` cast, which cuts the expectation typing Some(7) as Option (E0271); a let-bound lambda was `|x|` with no call site to type x from (E0282 at x.clone()) and is now emitted with typed parameters through emit_typed_collection_lambda, staying a bare closure so it still enters an impl Fn parameter. The call sites themselves (r(), f(v), g(v)) needed no change. EVIDENCE: test.fixture.emitted_interpreted_parity local_callable_value_calls exits 0 interpreted and its emitted crate, driven by a two-line harness over its library, prints the same line `6 8 6 7 9 0` with main returning ExitSuccess; with the expected line mutated both sides refuse (interpreter exit 1, emitted main ExitFailure carrying the observed line); on the pre-fix seed the fixture refuses at resolve. test.claim.local_callable_value_call_witness_test carries three inference controls (fold, unary fold and map lambda parameters over callable elements) and two emission controls (the list-literal carrier and the typed let), all five FAIL on the pre-fix seed and PASS here. RESIDUE, stated: an UNANNOTATED let-bound lambda (`let h = fn(x) { x * 2 }`) has no parameter type a Rust closure can be written at and still emits `|x: _|`-equivalent (E0282); a non-lambda element (a let-bound closure variable) in a List keeps its bare rendering. RUNG unchanged at mitigatable: required CI still neither emits-and-compiles a fixture closure nor runs its crate, which is this row's existing trigger.", "OCCURRENCE, 2026-09-24 (lively-koi-275, gunbc#12208 MQ-1): A FIELD BOUND UNDER A NESTED VARIANT PATTERN KEEPS ITS BOX. The `diagnostics` field of `v2.std.diagnostic` `Outcome` is a recursive Optional, so `v1.compiler.emit_rust` `needs_box_wrapping` boxes it. At a SINGLE-LEVEL arm `Accepted { value: v, diagnostics: d } =>` the emitter binds the field by `ref` and unboxes it (`let d = diagnostics.as_ref()`). Under a NESTED arm `Present { value: Accepted { value: facts, diagnostics: d } } =>` it bound the Box itself, and passing `d` to `v2.std.diagnostic` `diagnostics_merge` failed rustc with E0308 (expected `Option>`, found `Box>`) in the emitted `v2.compiler.infer`. The `.dag` was accepted with zero diagnostics, and only the non-required emit-build lane (`//gunbc/instruments:self-host`) saw it. The author-side repair split the match into two single-level arms, which the rest of the corpus already does by habit. That habit is an unstated workaround: it explains why the population is small and is not evidence that it is zero. The existing trigger of this row covers it: the emitted carrier comes from the declaration, and nested-pattern binders must go through the same unboxing join as single-level arms.", + "OCCURRENCE, 2026-09-28 (warm-wolf-234, precursor to the Bool de-fork): THE ARMS OF A NATIVELY REALIZED COPRODUCT. std.types Bool = True | False is bound to Rust `bool` by gunbc.rust_source_type_bindings, and `match a { True => b False => False }` over it was accepted at zero blocking diagnostics and emitted `Bool::True` / `Bool::False` against a `bool` -- rustc E0308. The type binding said which carrier Bool realizes as and nothing said which of its values each arm is, so the emitter spelled the arm by its SOURCE name, the one spelling the carrier cannot express. It went unexercised because v2.std.logic's structural Bool answered every True/False in the corpus; retiring that declaration exposed it. REPAIRED AT THE OWNING LINK, not at the two sites that tripped it: std.target_representation SourceVariantTargetValue rows keyed on the parent's identity -- a DeclarationRef, or the kernel type name for the kernel mint every module's `Bool` resolves to, admitted by std.types is_kernel_type (the values themselves are target facts in extdeps.languages.rust.representation) -- that identity read once at inference and carried as VariantParentIdentity on VariantPattern and VariantValueBinding, and the emitter spelling the row's value or refusing located (compile_error!) where the identity is not recovered for an arm some row binds -- never falling back to the spelling. Standing controls: fixtures/fixture_closure_rustc/native_bool_variant_probe.dag (rustc, red before, green after), fixtures/fixture_closure_rustc/local_true_false_coproduct_probe.dag (a module-local coproduct whose arms are spelled True/False keeps its own enum, so the rows are identity-keyed), and test.claim.native_variant_realization_witness_test on the emitted bytes.", + "OCCURRENCE, 2026-09-28 (warm-wolf-234, found while choosing the control above; NOT repaired): A MODULE-LOCAL COPRODUCT SPELLED WITH A KERNEL TYPE NAME. `type Bool = True | False` declared in an ordinary module is accepted at zero blocking diagnostics, but kernel names are never overridden in type position, so every signature renders the kernel `bool` while the arms render the local `enum Bool` -- rustc E0308 on the specimen fixtures/fixture_closure_rustc/local_bool_coproduct_probe.dag, measured on origin/main by `gunbc compile --entry` plus cargo check. Two referents for one spelling in one module is the defect; the earlier boundary is the checker, which should refuse a declaration that shadows a kernel name (or the emitter should keep one referent). Rostered here with its specimen so it is not lost; the variant-realization change deliberately does not touch it." ], diff --git a/dag/gunbc/rust_source_type_bindings.dag b/dag/gunbc/rust_source_type_bindings.dag index 8cf89d71b55..0eed5a11d3c 100644 --- a/dag/gunbc/rust_source_type_bindings.dag +++ b/dag/gunbc/rust_source_type_bindings.dag @@ -3,11 +3,13 @@ module gunbc.rust_source_type_bindings import std.types { List, String, Bool, NonEmptyStr } import std.decl_ref { DeclarationRef, decl_ref } import std.target_representation { - SourceTypeTargetBinding, CheckpointRowMigration, CheckpointRowDisposition, + SourceTypeTargetBinding, SourceVariantTargetValue, VariantParentKey, VariantParentDeclaration, variant_parent_kernel_key, RepresentationValue, + CheckpointRowMigration, CheckpointRowDisposition, MigratedToExactBinding, ProvenUniqueKernelBinding, StillBareNameDebt } import extdeps.languages.rust.representation { - RustRepresentation, RustStdString, RustI64, RustBool, RustUnit, RustVecU8, RustSerdeJsonValue + RustRepresentation, RustStdString, RustI64, RustBool, RustUnit, RustVecU8, RustSerdeJsonValue, + rust_bool_true_value, rust_bool_false_value } // THE CORPUS'S HALF OF THE THREE-IDENTITY SPLIT (std.target_representation): which of THIS corpus's @@ -62,6 +64,41 @@ data rust_source_type_binding_rows: List +} + +data rust_bool_arm_values: List = [ + BoolArmValue { variant: "True" as NonEmptyStr, value: rust_bool_true_value }, + BoolArmValue { variant: "False" as NonEmptyStr, value: rust_bool_false_value } +] + +fn rust_bool_variant_rows(parent: VariantParentKey) -> List> { + rust_bool_arm_values |> map(a => SourceVariantTargetValue { parent: parent, variant: a.variant, value: a.value }) +} + +fn rust_bool_kernel_variant_rows() -> List> { + match variant_parent_kernel_key(kernel_name: "Bool") { + Present { value: k } => rust_bool_variant_rows(parent: k) + Absent => [] + } +} + +data rust_source_variant_value_rows: List> = concat( + rust_bool_variant_rows(parent: VariantParentDeclaration { declaration: decl_ref(module_path: "std.types", decl_name: "Bool") }), + rust_bool_kernel_variant_rows() +) + fn rust_bound_declaration_refs() -> List { rust_source_type_binding_rows |> map(r => r.source) } diff --git a/dag/std/target_representation.dag b/dag/std/target_representation.dag index beb4e593528..dc23c878a6d 100644 --- a/dag/std/target_representation.dag +++ b/dag/std/target_representation.dag @@ -1,6 +1,6 @@ module std.target_representation -import std.types { List, String, Bool, Int, NonEmptyStr } +import std.types { List, String, Bool, Int, NonEmptyStr, is_kernel_type } import std.decl_ref { DeclarationRef, declaration_ref_eq } // THREE IDENTITIES THAT ONE CHECKPOINT ROW USED TO FUSE, separated because each has a different @@ -124,3 +124,152 @@ fn checkpoint_row_disposition_keeps_bare_row(disposition: CheckpointRowDispositi fn checkpoint_row_migration_for(dag_name: NonEmptyStr, migrations: List) -> CheckpointRowMigration? { migrations |> filter(m => m.dag_name == dag_name) |> first } + +// A NATIVELY REALIZED COPRODUCT HAS ARMS, AND EACH ARM NEEDS A TARGET VALUE. A SourceTypeTargetBinding +// says the declaration std.types Bool realizes as the target's `bool`; it says nothing about which +// of Bool's arms is which of `bool`'s values, so a renderer holding only the type binding spelled +// the arm by its SOURCE name (`Bool::True`) against a carrier that has no such path -- accepted +// source emitting an uncompilable target (gunbc.recurring_failure_mode +// accepted_source_emits_uncompilable_target). The fact is split by owner exactly as the type half is: +// RepresentationValue -- representation -> one of its values, spelled. Owned by the TARGET +// authority and naming no source declaration (Rust's `bool` has the +// two values `true` and `false`). +// SourceVariantTargetValue -- source arm (its parent declaration by identity, the arm by name within +// it) -> one of those values. Owned by the CORPUS, because only the +// corpus knows which of its arms it means by which value. +// Keyed on the parent DeclarationRef, never on the parent's spelling: a module-local coproduct that +// happens to be named Bool with True/False arms has no binding and renders its own enum. +type RepresentationValue { + representation: R + value_spelling: NonEmptyStr +} + +// WHICH COPRODUCT AN ARM BELONGS TO, as one exhaustive key. A reference to a kernel type name +// (std.types kernel_type_set) resolves to the KERNEL MINT, which carries no declaration: the kernel +// namespace is closed, so the mint's name IS its identity -- the same standing +// gunbc.rust_source_type_bindings ProvenUniqueKernelBinding gives the kernel mint at the type level. +// A key is a kernel name only by membership, read through std.types is_kernel_type (the membership +// std.kernel_type_denotation keys on), and it is built only through variant_parent_kernel_key. +type VariantParentKey + = VariantParentDeclaration { declaration: DeclarationRef } + | VariantParentKernelType { kernel_name: String } + +fn variant_parent_kernel_key(kernel_name: String) -> VariantParentKey? { + if is_kernel_type(name: kernel_name) { + Present { value: VariantParentKernelType { kernel_name: kernel_name } } + } else { none } +} + +fn variant_parent_key_eq(a: VariantParentKey, b: VariantParentKey) -> Bool { + match a { + VariantParentDeclaration { declaration: da } => + match b { + VariantParentDeclaration { declaration: db } => declaration_ref_eq(a: da, b: db) + VariantParentKernelType { kernel_name: _ } => false + } + VariantParentKernelType { kernel_name: ka } => + match b { + VariantParentDeclaration { declaration: _ } => false + VariantParentKernelType { kernel_name: kb } => ka == kb + } + } +} + +fn variant_parent_key_label(k: VariantParentKey) -> String { + match k { + VariantParentDeclaration { declaration: d } => concat(d.module_path as String, ".", d.decl_name as String) + VariantParentKernelType { kernel_name: n } => concat("kernel ", n) + } +} + +type SourceVariantTargetValue { + parent: VariantParentKey + variant: NonEmptyStr + value: RepresentationValue +} + +// WHICH DECLARATION A VARIANT OCCURRENCE BELONGS TO, read ONCE at inference where the scrutinee's (or +// the value's) resolved type is live, and carried on the typed tree for emission -- the same shape +// std.operator_realization OperandDeclaration carries for a binary operator, for the same measured +// reason: at emission only the module env survives, and re-resolving a spelling there answers by pool +// precedence, not by the reference's own binding. Identified carries the key; Unrecovered is the +// located refusal and says why; BeforeInference is the parser's state for a pattern inference has +// not yet read, and emission treats it as unrecovered. There is no default. +type VariantParentIdentity + = VariantParentIdentified { key: VariantParentKey } + | VariantParentUnrecovered { cause: NonEmptyStr } + | VariantParentBeforeInference + +type VariantValueRealization + = VariantRealizesAsTargetValue { value_spelling: NonEmptyStr } + | VariantRealizesStructurally + | VariantTargetValueUnbound { parent: VariantParentKey, variant: NonEmptyStr } + | VariantTargetValueAmbiguous { parent: VariantParentKey, variant: NonEmptyStr, candidate_count: Int } + | VariantParentIdentityUnavailable { cause: NonEmptyStr } + +fn variant_rows_for(key: VariantParentKey, variant: NonEmptyStr, values: List>) -> List> { + values |> filter(v => variant_parent_key_eq(a: v.parent, b: key) && (v.variant as String) == (variant as String)) +} + +fn variant_value_from_hits(key: VariantParentKey, variant: NonEmptyStr, hits: List>) -> VariantValueRealization { + let n = hits |> count + if n == 1 { + match hits |> first { + Present { value: v } => VariantRealizesAsTargetValue { value_spelling: v.value.value_spelling } + Absent => VariantTargetValueUnbound { parent: key, variant: variant } + } + } else if n == 0 { + VariantTargetValueUnbound { parent: key, variant: variant } + } else { + VariantTargetValueAmbiguous { parent: key, variant: variant, candidate_count: n } + } +} + +// THE DECISION, total over the identity arms. A declared parent with no type binding renders its own +// structure (the ordinary answer); a declared parent bound natively MUST bind every arm it is asked +// about, and a value row whose value belongs to a different representation than the parent is +// bound to cannot answer for it. A kernel parent has no declaration binding to consult: it realizes +// natively exactly where the kernel name has variant rows, and then every arm asked about must have +// one. An arm with no row refuses rather than falling back to the source spelling, because that +// spelling is precisely what the target cannot express. An identity that is not Identified is +// answered as unavailable, never as structural. +fn variant_value_realization( + parent: VariantParentIdentity, + variant: NonEmptyStr, + bindings: List>, + values: List>, + same_representation: fn(R, R) -> Bool +) -> VariantValueRealization { + match parent { + VariantParentBeforeInference => VariantParentIdentityUnavailable { cause: "the variant was never read by inference" as NonEmptyStr } + VariantParentUnrecovered { cause: c } => VariantParentIdentityUnavailable { cause: c } + VariantParentIdentified { key: key } => + match key { + VariantParentKernelType { kernel_name: _ } => + let kernel_rows = values |> filter(v => variant_parent_key_eq(a: v.parent, b: key)) + if kernel_rows |> count == 0 { VariantRealizesStructurally } + else { variant_value_from_hits(key: key, variant: variant, hits: variant_rows_for(key: key, variant: variant, values: values)) } + VariantParentDeclaration { declaration: d } => + match resolve_exact_binding(source: Present { value: d }, rows: bindings) { + ExactBindingAbsent => VariantRealizesStructurally + ExactSourceIdentityUnavailable { cause: c } => VariantParentIdentityUnavailable { cause: c } + ExactBindingAmbiguous { candidate_count: n } => VariantTargetValueAmbiguous { parent: key, variant: variant, candidate_count: n } + ResolvedExactBinding { binding: b } => + variant_value_from_hits(key: key, variant: variant, hits: variant_rows_for(key: key, variant: variant, values: values) |> filter(v => same_representation(v.value.representation, b.representation))) + } + } + } +} + +fn variant_value_realization_refusal_message(r: VariantValueRealization) -> String? { + match r { + VariantRealizesAsTargetValue { value_spelling: _ } => none + VariantRealizesStructurally => none + VariantTargetValueUnbound { parent: p, variant: v } => + Present { value: concat("variant realization: ", variant_parent_key_label(k: p), " realizes natively on this target but its arm `", v as String, "` has no target value row; the source spelling cannot be emitted against the native carrier") } + VariantTargetValueAmbiguous { parent: p, variant: v, candidate_count: n } => + Present { value: concat("variant realization: arm `", v as String, "` of ", variant_parent_key_label(k: p), " has ", to_string(value: n), " target value rows (corpus authoring defect)") } + VariantParentIdentityUnavailable { cause: c } => + Present { value: concat("variant realization: the coproduct this variant belongs to was not recovered (", c as String, "), so whether it realizes natively cannot be decided") } + } +} diff --git a/dag/test/claim/native_variant_realization_witness_test.dag b/dag/test/claim/native_variant_realization_witness_test.dag new file mode 100644 index 00000000000..29f4b91f580 --- /dev/null +++ b/dag/test/claim/native_variant_realization_witness_test.dag @@ -0,0 +1,36 @@ +module test.claim.native_variant_realization_witness_test + +import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly } + +data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly + +// THE EMITTED BYTES OF A NATIVELY REALIZED COPRODUCT'S ARMS, through the PRODUCTION v1 emitter +// (compile_dag_rust_emit_check). std.types Bool = True | False realizes as Rust `bool` +// (gunbc.rust_source_type_bindings), and gunbc.rust_source_type_bindings +// rust_source_variant_value_rows binds its arms to that carrier's values, keyed on the declaration. +// The rustc half -- that these bytes type-check -- is fixtures/fixture_closure_rustc/ +// native_bool_variant_probe.dag on the fixture-closure route (v1.compiler.compiler_tests_rust +// ct_native_bool_variant_fixture_closure_discrimination_test). + +// The RED this row turns on: the source spelling `Bool::True` against a `bool`, which is what the +// emitter wrote before the rows existed (rustc E0308). +test fn native_bool_arms_emit_the_carrier_values() -> Bool { + compile_dag_rust_emit_check( + "module test.claim.native_bool_arm_probe\nimport std.types { Bool }\nfn probe(a: Bool, b: Bool) -> Bool {\n match a {\n True => b\n False => False\n }\n}\nfn probe_top() -> Bool { True }\n", + "src/test_claim_native_bool_arm_probe.rs", + ["true => ", "false => false"], + ["Bool::True", "Bool::False"] + ) +} + +// THE IDENTITY CONTROL: a module-local coproduct whose arms are spelled True/False has no row, so it +// keeps its own enum and its arms keep their enum paths. A lowering keyed on the arm spelling would +// pass the row above and fail this one. +test fn local_coproduct_with_true_false_arms_keeps_its_enum() -> Bool { + compile_dag_rust_emit_check( + "module test.claim.local_verdict_arm_probe\ntype Verdict = True | False\nfn probe(a: Verdict) -> Verdict {\n match a {\n True => False\n False => True\n }\n}\n", + "src/test_claim_local_verdict_arm_probe.rs", + ["Verdict::True", "Verdict::False"], + ["true => ", "false => "] + ) +} diff --git a/fixtures/fixture_closure_rustc/local_bool_coproduct_probe.dag b/fixtures/fixture_closure_rustc/local_bool_coproduct_probe.dag new file mode 100644 index 00000000000..ba5b7dea7e3 --- /dev/null +++ b/fixtures/fixture_closure_rustc/local_bool_coproduct_probe.dag @@ -0,0 +1,20 @@ +module fixture.closure.rustc_local_bool_coproduct_probe + +// A STANDING RED, NOT A CONTROL: a module-local coproduct spelled with a kernel type name. The front +// end ACCEPTS it, but kernel names are never overridden in type position, so every `Bool` in a +// signature renders the kernel `bool` while the arms render the local `enum Bool` -- rustc E0308 +// (gunbc.recurring_failure_mode accepted_source_emits_uncompilable_target, the 2026-09-28 +// kernel-name-shadowing receipt). Either the checker refuses the shadowing declaration or the +// emitter keeps one referent; until then this file is the executable specimen. +type Bool = True | False + +fn local_negate(a: Bool) -> Bool { + match a { + True => False + False => True + } +} + +fn local_top() -> Bool { + True +} diff --git a/fixtures/fixture_closure_rustc/local_true_false_coproduct_probe.dag b/fixtures/fixture_closure_rustc/local_true_false_coproduct_probe.dag new file mode 100644 index 00000000000..bf087e58841 --- /dev/null +++ b/fixtures/fixture_closure_rustc/local_true_false_coproduct_probe.dag @@ -0,0 +1,19 @@ +module fixture.closure.rustc_local_true_false_coproduct_probe + +// THE IDENTITY-KEYED CONTROL for native_bool_variant_probe. This module declares its OWN coproduct +// whose arms are spelled True/False. It has no row in gunbc.rust_source_type_bindings +// rust_source_variant_value_rows, so it renders its own enum and its arms keep their enum paths: a +// lowering keyed on the arm spelling would rewrite them to `true`/`false` against an enum, and rustc +// would refuse. (A local coproduct spelled Bool cannot be this control: see local_bool_coproduct_probe.) +type Verdict = True | False + +fn verdict_negate(a: Verdict) -> Verdict { + match a { + True => False + False => True + } +} + +fn verdict_top() -> Verdict { + True +} diff --git a/fixtures/fixture_closure_rustc/native_bool_variant_probe.dag b/fixtures/fixture_closure_rustc/native_bool_variant_probe.dag new file mode 100644 index 00000000000..98f68e0a259 --- /dev/null +++ b/fixtures/fixture_closure_rustc/native_bool_variant_probe.dag @@ -0,0 +1,31 @@ +module fixture.closure.rustc_native_bool_variant_probe + +import std.types { Bool, Int } + +// THE ARMS OF A NATIVELY REALIZED COPRODUCT, POSED TO RUSTC. std.types Bool = True | False realizes +// as Rust `bool` (gunbc.rust_source_type_bindings), so its arms must be spelled as that carrier's +// two values -- in value position, in pattern position, and nested inside another variant's +// pattern -- by the rows gunbc.rust_source_type_bindings rust_source_variant_value_rows, keyed on the +// declaration. Before that lowering the emitter spelled them `Bool::True` against a `bool`, which +// the front end accepted and rustc refused (gunbc.recurring_failure_mode +// accepted_source_emits_uncompilable_target). +type Gate = Open { admitted: Bool } | Shut + +fn probe_meet(a: Bool, b: Bool) -> Bool { + match a { + True => b + False => False + } +} + +fn probe_top() -> Bool { + True +} + +fn probe_gate_admits(g: Gate) -> Int { + match g { + Open { admitted: True } => 1 + Open { admitted: False } => 2 + Shut => 0 + } +} diff --git a/src/v1/00_core.dag b/src/v1/00_core.dag index 6903c6df7cf..ce45dace75e 100644 --- a/src/v1/00_core.dag +++ b/src/v1/00_core.dag @@ -16,6 +16,7 @@ import std.coercion { import std.dissolution { DissolutionCondition, unbound_dissolution } import std.literal_elaboration { LiteralElaboration } import std.operator_realization { OperandDeclaration } +import std.target_representation { VariantParentIdentity } import std.induction { SubValueRelation } import std.occurrence_identity { NodeOccurrenceIdentity, @@ -141,7 +142,7 @@ fn has_inferred(n: Node) -> Bool { type VarBindingKind = LocalValueBinding | FunctionValueBinding - | VariantValueBinding { parent_enum: String } + | VariantValueBinding { parent_enum: String, parent_identity: VariantParentIdentity } | MatchBoundBinding | ServiceValueBinding @@ -311,7 +312,7 @@ type ExprData type MatchPattern = Bind { declaration: Node } | LitPattern { value: LiteralValue } - | VariantPattern { name: String, parent_enum: String?, field_bindings: List } + | VariantPattern { name: String, parent_enum: String?, field_bindings: List, parent_identity: VariantParentIdentity } | Wildcard // IRREFUTABILITY IS A FACT ABOUT `MatchPattern`, SO IT LIVES WITH THE TYPE. It was previously @@ -326,7 +327,7 @@ fn match_pattern_is_irrefutable(pattern: MatchPattern) -> Bool { match pattern { Wildcard => true Bind { declaration: _ } => true - VariantPattern { name: _, parent_enum: _, field_bindings: _ } => false + VariantPattern { name: _, parent_enum: _, field_bindings: _, parent_identity: _ } => false LitPattern { value: _ } => false } } diff --git a/src/v1/02_parse.dag b/src/v1/02_parse.dag index dd8c43f0a96..52730a9ccf3 100644 --- a/src/v1/02_parse.dag +++ b/src/v1/02_parse.dag @@ -1,5 +1,6 @@ module v1.compiler.parse +import std.target_representation { VariantParentBeforeInference } import v1.std.core { Unmarked, TestMarked, module_node, import_node, Node, InferredNode, Resolved, CompilerError, TypeVariable, @@ -1318,7 +1319,7 @@ fn occurrence_allocator_after_match_pattern( ) -> OccurrenceIdAllocator { match pattern { Present { value: Bind { declaration: declaration } } => occurrence_allocator_after_node(alloc: alloc, node: declaration) - Present { value: VariantPattern { name: _, parent_enum: _, field_bindings: bindings } } => occurrence_allocator_after_node_list(alloc: alloc, nodes: bindings) + Present { value: VariantPattern { name: _, parent_enum: _, field_bindings: bindings, parent_identity: _ } } => occurrence_allocator_after_node_list(alloc: alloc, nodes: bindings) Present { value: LitPattern { value: _ } } => alloc Present { value: Wildcard } => alloc Absent => alloc @@ -1470,6 +1471,7 @@ fn stamp_parsed_pattern( name: name, parent_enum: parent_enum, field_bindings: field_bindings, + parent_identity: parent_identity, }, } => let stamped = stamp_parsed_node_list( @@ -1484,6 +1486,7 @@ fn stamp_parsed_pattern( name: name, parent_enum: parent_enum, field_bindings: stamped.nodes, + parent_identity: parent_identity, }, }, ctx: stamped.ctx, @@ -5940,7 +5943,7 @@ fn parse_variant_pattern(tokens: TokenStream, ctx: ParseContext, name: String) - if has_err(err: r.err) { return PatternResult { pattern: Wildcard, tokens: r.tokens, ctx: r.ctx, err: r.err } } let r2 = expect(tokens: skip_newlines(tokens: r.tokens), expected: ExpectRBrace) if has_err(err: r2.err) { return PatternResult { pattern: Wildcard, tokens: r2.tokens, ctx: r.ctx, err: r2.err } } - PatternResult { pattern: VariantPattern { name: name, parent_enum: none, field_bindings: r.field_bindings }, tokens: r2.tokens, ctx: r.ctx, err: none } + PatternResult { pattern: VariantPattern { name: name, parent_enum: none, field_bindings: r.field_bindings, parent_identity: VariantParentBeforeInference }, tokens: r2.tokens, ctx: r.ctx, err: none } } else if tok_is_lparen(tok: token_stream_first(stream: tokens)) { let r = parse_pattern(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx) if has_err(err: r.err) { return PatternResult { pattern: Wildcard, tokens: r.tokens, ctx: r.ctx, err: r.err } } @@ -5948,9 +5951,9 @@ fn parse_variant_pattern(tokens: TokenStream, ctx: ParseContext, name: String) - if has_err(err: r2.err) { return PatternResult { pattern: Wildcard, tokens: r2.tokens, ctx: r.ctx, err: r2.err } } let minted = mint_parsed_node_identity(ctx: r.ctx) let fb = make_field_binding_node(occurrence_identity: minted.identity, field_name: "0", binding: r.pattern, span: span, name_span: kernel_span(name: "0")) - PatternResult { pattern: VariantPattern { name: name, parent_enum: none, field_bindings: [fb] }, tokens: r2.tokens, ctx: minted.ctx, err: none } + PatternResult { pattern: VariantPattern { name: name, parent_enum: none, field_bindings: [fb], parent_identity: VariantParentBeforeInference }, tokens: r2.tokens, ctx: minted.ctx, err: none } } else { - PatternResult { pattern: VariantPattern { name: name, parent_enum: none, field_bindings: [] }, tokens: tokens, ctx: ctx, err: none } + PatternResult { pattern: VariantPattern { name: name, parent_enum: none, field_bindings: [], parent_identity: VariantParentBeforeInference }, tokens: tokens, ctx: ctx, err: none } } } diff --git a/src/v1/04_infer.dag b/src/v1/04_infer.dag index dd721f1117d..b4854f77711 100644 --- a/src/v1/04_infer.dag +++ b/src/v1/04_infer.dag @@ -10,6 +10,7 @@ import std.content_hash { import extdeps.container.oci.digest { oci_other_digest_algorithm, oci_other_digest_encoded } import std.syntax { Add, Sub, Mul, Div, Mod, Eq, Ne, Lt, Gt, Le, Ge, And, Or, NullCoalesce, BinOp, LitStr, LitInt, LitBool, LiteralValue } import std.decl_ref { DeclarationRef } +import std.target_representation { VariantParentIdentity, VariantParentIdentified, VariantParentUnrecovered, VariantParentDeclaration, variant_parent_kernel_key } import std.operator_realization { OperandDeclaration } import std.literal_elaboration { LiteralElaboration, LiteralHomomorphism, LiteralUnfolding, PeanoUnfold, BooleanUnfold, UnicodeScalarSequenceUnfold, @@ -17,14 +18,14 @@ import std.literal_elaboration { elaborate_literal_at, literal_source_kind_of, literal_elaboration_refusal_message } import gunbc.structural_realization_bindings { literal_homomorphism_rows } -import std.coercion { dag_can_cast, is_dag_cast_domain_type, dag_cast_requires_proof, SubtractionRefinementAmbiguous } +import std.coercion { dag_can_cast, is_dag_cast_domain_type, dag_cast_requires_proof, SubtractionRefinementAmbiguous, KernelMinted } import v1.compiler.type_head_exposure { TypeHeadView, KernelScalarHead, ApplicationHead, ProductHead, CoproductHead, CallableHead, TypeHeadExposure, ExposedTypeHead, OpaqueTypeHead, StuckTypeHead, MalformedApplicationHead, type_declaration_identity_key, type_head_exposure_is_kernel_scalar, type_head_exposure_is_product, type_head_exposure_is_coproduct } -import v1.std.core { Unmarked, +import v1.std.core { Unmarked, declaration_provenance_of, callable_identity, DeclaredCallableIdentity, resolved_node_is_kernel_identity_for_name, Node, InternTable, @@ -740,6 +741,31 @@ fn variant_reference_inferred_node(expected: Node?, name: String, owner_name: St } } +// THE DECLARATION A VARIANT BELONGS TO, read here where the owning coproduct's node is live +// (std.target_representation VariantParentIdentity): the same census-by-identity read +// type_reference_declaration performs for a binary operator's operand, and for the same reason it is +// done at inference and carried -- emission holds only the module env, and re-resolving the owner's +// spelling there answers by pool precedence. An owner the census cannot identify says so; nothing +// here falls back to the owner's spelling or to the reference's file. +fn variant_parent_identity_of(owner: Node?, scope: InferScope) -> VariantParentIdentity { + match owner { + Absent => VariantParentUnrecovered { cause: "no owning coproduct declaration was found for the variant" as NonEmptyStr } + Present { value: o } => + match type_reference_declaration(n: o, source_indices: scope.type_env.source_indices, env: scope.type_env) { + Present { value: od } => VariantParentIdentified { key: VariantParentDeclaration { declaration: od.declaration } } + Absent => + match declaration_provenance_of(item: o) { + KernelMinted { minted_name: m } => + match variant_parent_kernel_key(kernel_name: m) { + Present { value: k } => VariantParentIdentified { key: k } + Absent => VariantParentUnrecovered { cause: "the owning coproduct is a kernel mint whose name is not a kernel type" as NonEmptyStr } + } + _ => VariantParentUnrecovered { cause: "the owning coproduct is neither an identified corpus declaration nor a kernel type (alias or unresolved)" as NonEmptyStr } + } + } + } +} + fn variant_owner_node(scope: InferScope, name: String) -> Node? { if contains(name, ".") { match symbol_index_lookup(index: scope.type_env.symbol_index, qualified_name: name) { @@ -915,7 +941,7 @@ fn expected_type_is_arrow(expected: Node?) -> Bool { fn infer_var_binding_kind(scope: InferScope, name: String) -> VarBindingKind { match lookup_variant_parent_enum(scope: scope, name: name) { - Present { value: parent_enum } => VariantValueBinding { parent_enum: parent_enum } + Present { value: parent_enum } => VariantValueBinding { parent_enum: parent_enum, parent_identity: variant_parent_identity_of(owner: variant_owner_node(scope: scope, name: name), scope: scope) } Absent => match map_get(scope.locals, name) { Present { value: binding } => @@ -6367,7 +6393,7 @@ fn resolve_pattern_subject(scope: InferScope, scrutinee_subject: PatternSubject) fn annotate_pattern_parent_enums(pattern: MatchPattern, scrutinee_subject: PatternSubject, scope: InferScope) -> MatchPattern { match pattern { - VariantPattern { name: variant_name, parent_enum: _, field_bindings: bindings } => + VariantPattern { name: variant_name, parent_enum: _, field_bindings: bindings, parent_identity: _ } => let resolved_scrut = resolve_pattern_subject(scope: scope, scrutinee_subject: scrutinee_subject) let inferred_parent = match resolved_scrut { PatternResolved { node: resolved_scrut_node } => @@ -6389,6 +6415,23 @@ fn annotate_pattern_parent_enums(pattern: MatchPattern, scrutinee_subject: Patte PatternLookupBlocked => none } let annotated_variant_name = variant_name + let wrapper_parent = match inferred_parent { + Present { value: p } => p == "Optional" || p == "Witness" + Absent => false + } + let parent_identity = if wrapper_parent { + VariantParentUnrecovered { cause: "the arm belongs to the optional or witness wrapper, not to the scrutinee's declared coproduct" as NonEmptyStr } + } else { match resolved_scrut { + PatternResolved { node: r } => + let scrutinee_is_coproduct = r.connective == Disj + if scrutinee_is_coproduct { + variant_parent_identity_of(owner: Present { value: r }, scope: scope) + } else { + VariantParentUnrecovered { cause: "the scrutinee's resolved type is not a coproduct declaration" as NonEmptyStr } + } + PatternDynamic { span: _ } => VariantParentUnrecovered { cause: "the scrutinee's type is dynamic" as NonEmptyStr } + PatternLookupBlocked => VariantParentUnrecovered { cause: "the scrutinee's type lookup was blocked" as NonEmptyStr } + } } let variant_lookup = lookup_variant_in_type(scrut: resolved_scrut, variant_name: variant_name, module_name: scope.module_name, env: scope.type_env, field_binding_count: bindings |> count) let variant_subject = lookup_result_subject(result: variant_lookup) let annotated_bindings = bindings |> map(binding => @@ -6401,10 +6444,11 @@ fn annotate_pattern_parent_enums(pattern: MatchPattern, scrutinee_subject: Patte VariantPattern { name: annotated_variant_name, parent_enum: parent_name, - field_bindings: annotated_bindings + field_bindings: annotated_bindings, + parent_identity: parent_identity } Absent => - VariantPattern { name: variant_name, parent_enum: none, field_bindings: annotated_bindings } + VariantPattern { name: variant_name, parent_enum: none, field_bindings: annotated_bindings, parent_identity: parent_identity } } _ => pattern } @@ -6422,7 +6466,7 @@ fn annotate_pattern_parent_enums(pattern: MatchPattern, scrutinee_subject: Patte fn present_arms_over_unresolved_scrutinee(arms: List, span: SourceSpan, module_name: String) -> List { flat_map(arms, arm => match arm_pattern(n: arm) { - VariantPattern { name: n, parent_enum: pe, field_bindings: _ } => + VariantPattern { name: n, parent_enum: pe, field_bindings: _, parent_identity: _ } => if qualified_last_segment(name: n) == "Present" && pe == none { [make_error_node(diagnostic: PresentArmScrutineeTypeUnresolved { pattern: n, span: span }, module_name: module_name)] } else { [] } @@ -6571,7 +6615,7 @@ fn extend_scope_with_pattern_node(scope: InferScope, pattern: MatchPattern, scru Bind { declaration: declaration } => PatternScopeResult { scope: extend_scope_match_bound(scope: scope, name: declaration.name, resolved: pattern_binding_type(subject: scrutinee_subject), provenance: scrutinee_provenance), diagnostics: [] } Wildcard => PatternScopeResult { scope: scope, diagnostics: [] } LitPattern { value: _ } => PatternScopeResult { scope: scope, diagnostics: [] } - VariantPattern { name: vname, parent_enum: _, field_bindings: bindings } => + VariantPattern { name: vname, parent_enum: _, field_bindings: bindings, parent_identity: _ } => let resolved_scrut = resolve_pattern_subject(scope: scope, scrutinee_subject: scrutinee_subject) let variant_lookup = lookup_variant_in_type(scrut: resolved_scrut, variant_name: vname, module_name: scope.module_name, env: scope.type_env, field_binding_count: bindings |> count) let variant_subject = lookup_result_subject(result: variant_lookup) @@ -7060,15 +7104,15 @@ fn elaborated_expr_node(name: String, expr_data: ExprData, children: List, } } -fn unfold_peano_image(n: Int, zero: String, succ: String, prev_field: String, parent: String, destination_type: Node, span: SourceSpan) -> Node { +fn unfold_peano_image(n: Int, zero: String, succ: String, prev_field: String, parent: String, parent_identity: VariantParentIdentity, destination_type: Node, span: SourceSpan) -> Node { if n <= 0 { elaborated_expr_node( name: zero, - expr_data: ExprVar { binding_kind: Present { value: VariantValueBinding { parent_enum: parent } } }, + expr_data: ExprVar { binding_kind: Present { value: VariantValueBinding { parent_enum: parent, parent_identity: parent_identity } } }, children: [], destination_type: destination_type, span: span ) } else { - let prev = unfold_peano_image(n: n - 1, zero: zero, succ: succ, prev_field: prev_field, parent: parent, destination_type: destination_type, span: span) + let prev = unfold_peano_image(n: n - 1, zero: zero, succ: succ, prev_field: prev_field, parent: parent, parent_identity: parent_identity, destination_type: destination_type, span: span) let field = make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: prev_field, value: prev, span: span, name_span: elaborated_span(name: prev_field)) elaborated_expr_node( name: succ, @@ -7117,6 +7161,7 @@ fn unfold_literal_image(lit: LiteralValue, elaboration: LiteralElaboration, dest n: n, zero: zero.decl_name as String, succ: succ.decl_name as String, prev_field: prev_field as String, parent: elaboration.destination.decl_name as String, + parent_identity: VariantParentIdentified { key: VariantParentDeclaration { declaration: elaboration.destination } }, destination_type: destination_type, span: span ) _ => make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: InternalExprError, message: "literal elaboration: a Peano unfolding row was selected for a non-integer literal (gunbc.structural_realization_bindings keys the row on KernelIntLiteral, so this row is malformed)", span: span) @@ -7126,7 +7171,7 @@ fn unfold_literal_image(lit: LiteralValue, elaboration: LiteralElaboration, dest LitBool { value: b } => elaborated_expr_node( name: if b { t.decl_name as String } else { f.decl_name as String }, - expr_data: ExprVar { binding_kind: Present { value: VariantValueBinding { parent_enum: elaboration.destination.decl_name as String } } }, + expr_data: ExprVar { binding_kind: Present { value: VariantValueBinding { parent_enum: elaboration.destination.decl_name as String, parent_identity: VariantParentIdentified { key: VariantParentDeclaration { declaration: elaboration.destination } } } } }, children: [], destination_type: destination_type, span: span ) _ => make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: InternalExprError, message: "literal elaboration: a Boolean unfolding row was selected for a non-boolean literal (gunbc.structural_realization_bindings keys the row on KernelBoolLiteral, so this row is malformed)", span: span) @@ -7240,7 +7285,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu typed: make_named_expr_node( occurrence_identity: texpr.occurrence_identity, name: name, - expr_data: ExprVar { binding_kind: Present { value: VariantValueBinding { parent_enum: scope_enum } } }, + expr_data: ExprVar { binding_kind: Present { value: VariantValueBinding { parent_enum: scope_enum, parent_identity: variant_parent_identity_of(owner: variant_owner_node(scope: scope, name: name), scope: scope) } } }, children: [], inferred: Present { value: Resolved { node: variant_reference_inferred_node(expected: expected, name: name, owner_name: scope_enum, scope: scope, fallback: binding.resolved) } }, span: span, @@ -7308,7 +7353,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu typed: make_named_expr_node( occurrence_identity: texpr.occurrence_identity, name: name, - expr_data: ExprVar { binding_kind: Present { value: VariantValueBinding { parent_enum: scope_enum } } }, + expr_data: ExprVar { binding_kind: Present { value: VariantValueBinding { parent_enum: scope_enum, parent_identity: variant_parent_identity_of(owner: variant_owner_node(scope: scope, name: name), scope: scope) } } }, children: [], inferred: Present { value: Resolved { node: variant_reference_inferred_node(expected: expected, name: name, owner_name: scope_enum, scope: scope, fallback: gbinding.resolved) } }, span: span, @@ -7323,7 +7368,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu typed: make_named_expr_node( occurrence_identity: texpr.occurrence_identity, name: name, - expr_data: ExprVar { binding_kind: Present { value: VariantValueBinding { parent_enum: authored_name_at(source_indices: scope.type_env.source_indices, node: exp_enum) } } }, + expr_data: ExprVar { binding_kind: Present { value: VariantValueBinding { parent_enum: authored_name_at(source_indices: scope.type_env.source_indices, node: exp_enum), parent_identity: variant_parent_identity_of(owner: Present { value: exp_enum }, scope: scope) } } }, children: [], inferred: Present { value: Resolved { node: exp_enum } }, span: span, @@ -7368,7 +7413,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu typed: make_named_expr_node( occurrence_identity: texpr.occurrence_identity, name: name, - expr_data: ExprVar { binding_kind: Present { value: VariantValueBinding { parent_enum: authored_name_at(source_indices: scope.type_env.source_indices, node: exp_enum) } } }, + expr_data: ExprVar { binding_kind: Present { value: VariantValueBinding { parent_enum: authored_name_at(source_indices: scope.type_env.source_indices, node: exp_enum), parent_identity: variant_parent_identity_of(owner: Present { value: exp_enum }, scope: scope) } } }, children: [], inferred: Present { value: Resolved { node: exp_enum } }, span: span, @@ -10815,7 +10860,7 @@ fn provenance_callee_sig(callee: String, param_types: Map, let_p fn descent_pattern_bound_names(pattern: MatchPattern) -> List { match pattern { Bind { declaration: declaration } => [declaration.name] - VariantPattern { name: _, parent_enum: _, field_bindings: bindings } => + VariantPattern { name: _, parent_enum: _, field_bindings: bindings, parent_identity: _ } => bindings |> flat_map(fb => descent_pattern_bound_names(pattern: field_binding_pattern(n: fb))) _ => [] } @@ -10954,7 +10999,7 @@ fn annotate_descent(body: Node, ctx: DescentContext) -> Node { Absent => if scrut_has_inductive { match arm_pattern(n: arm_node) { - VariantPattern { name: vname, parent_enum: _, field_bindings: bindings } => + VariantPattern { name: vname, parent_enum: _, field_bindings: bindings, parent_identity: _ } => match scrut_inducing_field { Present { value: ind_field } => if vname == "Present" { @@ -10971,7 +11016,7 @@ fn annotate_descent(body: Node, ctx: DescentContext) -> Node { per_field_vars: c.per_field_vars, body_locals: c.body_locals } - VariantPattern { name: inner_vname, parent_enum: _, field_bindings: inner_bindings } => + VariantPattern { name: inner_vname, parent_enum: _, field_bindings: inner_bindings, parent_identity: _ } => let inner_ind_fields = inductive_fields_for(env: c.type_env, type_name: ind_field.element_type) inner_bindings |> fold(init: c, f: (ic, inner_fb) => let inner_field_name = field_binding_name_at(n: inner_fb, source_indices: ctx.type_env.source_indices) @@ -11464,7 +11509,7 @@ fn classify_body_provenance(expr: Node, param_names: List, param_types: let arm_provs = arms |> map(arm => let arm_let_prov = match arm_pattern(n: arm) { - VariantPattern { name: vname, parent_enum: _, field_bindings: bindings } => + VariantPattern { name: vname, parent_enum: _, field_bindings: bindings, parent_identity: _ } => fold(bindings, init: let_prov, f: (acc, binding) => let field_label = field_binding_name_at(n: binding, source_indices: type_env.source_indices) let bind_name = match field_binding_pattern(n: binding) { @@ -11763,7 +11808,7 @@ fn intersect_prov_maps(a: Map, b: Map DescentContext? { match arm_pattern(n: arm_node) { - VariantPattern { name: vname, parent_enum: _, field_bindings: bindings } => + VariantPattern { name: vname, parent_enum: _, field_bindings: bindings, parent_identity: _ } => match map_get(sig.variant_provenance, vname) { Present { value: variant_field_map } => let call_args = call_args_by_name(call: scrut, source_indices: ctx.type_env.source_indices) diff --git a/src/v1/04_patterns.dag b/src/v1/04_patterns.dag index 27317cc0c10..5fb311b8f35 100644 --- a/src/v1/04_patterns.dag +++ b/src/v1/04_patterns.dag @@ -579,7 +579,7 @@ fn pattern_row_is_irrefutable(row: List) -> Bool { fn pattern_matches_constructor(p: MatchPattern, ctor: String) -> Bool { match p { - VariantPattern { name: n, parent_enum: _, field_bindings: _ } => + VariantPattern { name: n, parent_enum: _, field_bindings: _, parent_identity: _ } => variant_pattern_coverage_key(name: n) == variant_pattern_coverage_key(name: ctor) LitPattern { value: v } => match v { @@ -611,7 +611,7 @@ fn specialize_pattern_row(row: List, ctor: String, fields: List map(f => Wildcard), rest)] } else if pattern_matches_constructor(p: head, ctor: ctor) { match head { - VariantPattern { name: _, parent_enum: _, field_bindings: fbs } => + VariantPattern { name: _, parent_enum: _, field_bindings: fbs, parent_identity: _ } => [concat(fields |> map(f => field_binding_pattern_for(bindings: fbs, field_name: f.name, source_indices: source_indices)), rest)] _ => [concat(fields |> map(f => Wildcard), rest)] } diff --git a/src/v1/05_emit.dag b/src/v1/05_emit.dag index 6e21c82c13c..23006a8e87d 100644 --- a/src/v1/05_emit.dag +++ b/src/v1/05_emit.dag @@ -189,7 +189,7 @@ fn emit_simple_expr(expr: Node, target: RenderTarget, source_indices: Map match bk { Present { value: MatchBoundBinding } => false - Present { value: VariantValueBinding { parent_enum: _ } } => false + Present { value: VariantValueBinding { parent_enum: _, parent_identity: _ } } => false _ => true } _ => false @@ -3595,7 +3595,7 @@ fn emit_unified_pattern(pattern: MatchPattern, target: RenderTarget, source_indi match pattern { Bind { declaration: declaration } => emit_ident(name: declaration.name, target: target) LitPattern { value: v } => emit_literal(value: v, target: target) - VariantPattern { name: n, parent_enum: pe, field_bindings: fbs } => + VariantPattern { name: n, parent_enum: pe, field_bindings: fbs, parent_identity: _ } => emit_unified_variant_pattern(name: n, parent_enum: pe, field_bindings: fbs, target: target, source_indices: source_indices) Wildcard => "_" } @@ -3673,7 +3673,7 @@ fn emit_arm_guard(arm: Node, target: RenderTarget, render_guard_expr: fn(Node) - fn emit_go_match_arm_bindings(arm: Node, indent_level: Int, source_indices: Map) -> String { match arm_pattern(n: arm) { - VariantPattern { name: _, parent_enum: _, field_bindings: fbs } => + VariantPattern { name: _, parent_enum: _, field_bindings: fbs, parent_identity: _ } => if fbs |> count == 0 { "" } else { fbs |> map(fb => concat(make_indent(level: indent_level), emit_ident(name: field_binding_name_at(n: fb, source_indices: source_indices), target: Go), " := __gunbcMatch.", emit_export_ident(name: field_binding_name_at(n: fb, source_indices: source_indices), target: Go), "\n")) |> join(separator: "") } diff --git a/src/v1/05_emit_rust.dag b/src/v1/05_emit_rust.dag index 3436d5df369..96d39cb9867 100644 --- a/src/v1/05_emit_rust.dag +++ b/src/v1/05_emit_rust.dag @@ -2,7 +2,9 @@ module v1.compiler.emit_rust import std.occurrence_identity { OccurrenceSynthetic } import std.decl_ref { decl_ref, DeclarationRef, WholeDeclaration } -import std.target_representation { ResolvedExactBinding, ExactBindingAbsent, ExactBindingAmbiguous, ExactSourceIdentityUnavailable } +import std.target_representation { ResolvedExactBinding, ExactBindingAbsent, ExactBindingAmbiguous, ExactSourceIdentityUnavailable, + VariantParentIdentity, VariantParentUnrecovered, VariantRealizesAsTargetValue, VariantRealizesStructurally, VariantTargetValueUnbound, + VariantTargetValueAmbiguous, VariantParentIdentityUnavailable, variant_value_realization_refusal_message } import extdeps.languages.rust.representation { rust_exact_type_checkpoint } import std.repair_input_origin { repair_input_origin_candidates, @@ -148,7 +150,8 @@ import v1.compiler.coercion { coerce_primitive_type, is_copy, target_callable, rust_lookup_exact_binding, declaration_realizes_natively_on_rust, type_reference_realization, declaration_realization, type_realization_decision, realized_checkpoint, realization_host_numeric_spelling, - realization_is_host_numeric, provenance_declares_structurally + realization_is_host_numeric, provenance_declares_structurally, + rust_variant_value_realization, rust_variant_arm_is_bound_somewhere } import std.coercion { TypeDeclarationProvenance, CorpusDeclared, KernelMinted, DeclarationIdentityAbsent, @@ -4296,7 +4299,7 @@ fn collect_items_field_import_surface_names(surface_names: List, emit_in // than guessing an enum (the candidate set may under-propose; it must never fabricate). fn collect_pattern_ref_names(pattern: MatchPattern, type_summaries: Map) -> List { match pattern { - VariantPattern { name: n, parent_enum: parent_enum, field_bindings: fbs } => + VariantPattern { name: n, parent_enum: parent_enum, field_bindings: fbs, parent_identity: _ } => let own = match pattern_parent_enum(name: qualified_last_segment(name: n), parent_enum: parent_enum, scrut_type: "", type_summaries: type_summaries) { Present { value: parent } => if parent == "" { [] } else { [parent] } Absent => [] @@ -4385,7 +4388,7 @@ fn emit_scrutinee_type_name(scrutinee: Node, source_indices: Map) -> List { match pattern { - VariantPattern { name: n, parent_enum: parent_enum, field_bindings: _ } => + VariantPattern { name: n, parent_enum: parent_enum, field_bindings: _, parent_identity: _ } => let bare_n = qualified_last_segment(name: n) match pattern_parent_enum(name: bare_n, parent_enum: parent_enum, scrut_type: scrut_type, type_summaries: type_summaries) { Present { value: parent } => if parent != "" { [parent] } else { [] } @@ -4397,7 +4400,7 @@ fn collect_pattern_rc_prelude_parent_enums(pattern: MatchPattern, scrut_type: St fn collect_rc_pattern_prelude_parent_enums(pattern: MatchPattern, rc_analysis: RcPatternAnalysis, scrut_type: String, shared_types: Set, source_indices: Map, emit_info: EmitGraphInfo) -> List { match pattern { - VariantPattern { name: n, parent_enum: parent_enum, field_bindings: fbs } => + VariantPattern { name: n, parent_enum: parent_enum, field_bindings: fbs, parent_identity: _ } => let bare_n = qualified_last_segment(name: n) if is_optional_variant_name(name: bare_n) && is_optional_parent(parent_enum: parent_enum) { if fbs |> count == 1 { @@ -9759,7 +9762,7 @@ fn collect_field_binding_string_guards(field_bindings: List, path_prefix: fn collect_pattern_string_guards(pattern: MatchPattern, path_prefix: List, source_indices: Map) -> String { match pattern { - VariantPattern { name: n, parent_enum: parent, field_bindings: fbs } => + VariantPattern { name: n, parent_enum: parent, field_bindings: fbs, parent_identity: _ } => if n == "Present" && parent == Present { value: "Optional" } && fbs |> count == 1 { match fbs |> first { Present { value: fb } => @@ -9826,8 +9829,12 @@ fn emit_pattern(pattern: MatchPattern, path_prefix: List, shared_types: match pattern { Bind { declaration: declaration } => emit_ident(name: declaration.name, target: Rust) LitPattern { value: v } => rust_literal_for_pattern(value: v) - VariantPattern { name: n, parent_enum: parent_enum, field_bindings: fbs } => + VariantPattern { name: n, parent_enum: parent_enum, field_bindings: fbs, parent_identity: identity } => + match rust_native_variant_spelling(parent: identity, leaf_name: qualified_last_segment(name: n)) { + Present { value: native } => native + Absent => emit_variant_pattern(name: n, parent_enum: parent_enum, field_bindings: fbs, path_prefix: path_prefix, shared_types: shared_types, scrut_type: scrut_type, source_indices: source_indices, emit_info: emit_info) + } Wildcard => "_" } } @@ -10094,7 +10101,7 @@ fn field_needs_rc_ref(field_name: String, rc_analysis: RcPatternAnalysis) -> Boo // `AdmitExportsFold`, four record sites). The record is decided by the same shared set. fn analyze_rc_pattern(pattern: MatchPattern, scrut_type: String, shared_types: Set, emit_info: EmitGraphInfo, source_indices: Map) -> RcPatternAnalysis { match pattern { - VariantPattern { name: n, parent_enum: parent_enum, field_bindings: fbs } => + VariantPattern { name: n, parent_enum: parent_enum, field_bindings: fbs, parent_identity: _ } => let bare_n = qualified_last_segment(name: n) if is_optional_variant_name(name: bare_n) && is_optional_parent(parent_enum: parent_enum) { if fbs |> count == 1 { @@ -10142,7 +10149,7 @@ fn analyze_rc_pattern(pattern: MatchPattern, scrut_type: String, shared_types: S fn box_bound_fields_for_pattern(pattern: MatchPattern, shared_types: Set, emit_info: EmitGraphInfo, scope: InferScope) -> List { match pattern { - VariantPattern { name: n, parent_enum: parent_enum, field_bindings: fbs } => + VariantPattern { name: n, parent_enum: parent_enum, field_bindings: fbs, parent_identity: _ } => let bare_n = qualified_last_segment(name: n) if is_optional_variant_name(name: bare_n) && is_optional_parent(parent_enum: parent_enum) { [] @@ -10215,8 +10222,12 @@ fn emit_pattern_rc_aware(pattern: MatchPattern, path_prefix: List, rc_an match pattern { Bind { declaration: declaration } => emit_ident(name: declaration.name, target: Rust) LitPattern { value: v } => rust_literal_for_pattern(value: v) - VariantPattern { name: n, parent_enum: parent_enum, field_bindings: fbs } => + VariantPattern { name: n, parent_enum: parent_enum, field_bindings: fbs, parent_identity: identity } => + match rust_native_variant_spelling(parent: identity, leaf_name: qualified_last_segment(name: n)) { + Present { value: native } => native + Absent => emit_variant_pattern_rc_aware(name: n, parent_enum: parent_enum, field_bindings: fbs, path_prefix: path_prefix, rc_analysis: rc_analysis, shared_types: shared_types, scrut_type: scrut_type, source_indices: source_indices, emit_info: emit_info) + } Wildcard => "_" } } @@ -10341,7 +10352,7 @@ fn variant_pattern_shape_for(name: String, parent_enum: String?, scrut_type: Str fn collect_pattern_rc_variant_guards(pattern: MatchPattern, rc_analysis: RcPatternAnalysis, shared_types: Set, source_indices: Map, emit_info: EmitGraphInfo) -> String { match pattern { - VariantPattern { name: n, parent_enum: parent_enum, field_bindings: fbs } => + VariantPattern { name: n, parent_enum: parent_enum, field_bindings: fbs, parent_identity: _ } => let bare_n = qualified_last_segment(name: n) if is_optional_variant_name(name: bare_n) && is_optional_parent(parent_enum: parent_enum) { if fbs |> count == 1 { @@ -10368,7 +10379,7 @@ fn collect_pattern_rc_variant_guards(pattern: MatchPattern, rc_analysis: RcPatte if match_pattern_is_irrefutable(pattern: fb_pat) { [] } else { match fb_pat { - VariantPattern { name: inner_n, parent_enum: inner_parent, field_bindings: _ } => + VariantPattern { name: inner_n, parent_enum: inner_parent, field_bindings: _, parent_identity: _ } => let inner_analysis = analyze_rc_pattern(pattern: fb_pat, scrut_type: "", shared_types: shared_types, emit_info: emit_info, source_indices: source_indices) let inner_guard = collect_pattern_rc_variant_guards(pattern: fb_pat, rc_analysis: inner_analysis, shared_types: shared_types, source_indices: source_indices, emit_info: emit_info) if inner_guard == "" { @@ -10400,7 +10411,7 @@ fn rust_as_ref_let_is_irrefutable(pattern: MatchPattern, emit_info: EmitGraphInf if match_pattern_is_irrefutable(pattern: pattern) { true } else { match pattern { - VariantPattern { name: n, parent_enum: parent, field_bindings: _ } => + VariantPattern { name: n, parent_enum: parent, field_bindings: _, parent_identity: _ } => let resolved = pattern_parent_enum(name: qualified_last_segment(name: n), parent_enum: parent, scrut_type: "", type_summaries: emit_info.type_summaries) match resolved { Present { value: enum_name } => @@ -10417,7 +10428,7 @@ fn rust_as_ref_let_is_irrefutable(pattern: MatchPattern, emit_info: EmitGraphInf fn rc_pattern_preludes(pattern: MatchPattern, rc_analysis: RcPatternAnalysis, shared_types: Set, source_indices: Map, emit_info: EmitGraphInfo) -> String { match pattern { - VariantPattern { name: n, parent_enum: parent_enum, field_bindings: fbs } => + VariantPattern { name: n, parent_enum: parent_enum, field_bindings: fbs, parent_identity: _ } => let bare_n = qualified_last_segment(name: n) if is_optional_variant_name(name: bare_n) && is_optional_parent(parent_enum: parent_enum) { if fbs |> count == 1 { @@ -10500,9 +10511,48 @@ fn explicit_record_struct_name(type_name: String?, inferred_node: Node, shared_t fn is_simple_type_node(n: Node, source_indices: Map) -> Bool { is_rust_value_type(n: n, source_indices: source_indices) } +// A VARIANT OF A NATIVELY REALIZED COPRODUCT IS SPELLED AS THE TARGET VALUE ITS ROW NAMES, in value +// and in pattern position alike (std.types Bool's True/False over Rust `bool` are `true`/`false`). +// Present answers the whole spelling for the occurrence -- the target value, or a located +// compile_error! refusal; Absent means the occurrence renders its own enum path as before. The +// decision is v1.compiler.coercion rust_variant_value_realization over the identity inference +// carried; see rust_variant_arm_is_bound_somewhere for why an unidentified occurrence refuses only +// when its arm is one a row binds. +fn rust_native_variant_spelling(parent: VariantParentIdentity, leaf_name: String) -> String? { + let r = rust_variant_value_realization(parent: parent, variant: leaf_name) + match r { + VariantRealizesAsTargetValue { value_spelling: s } => Present { value: s as String } + VariantRealizesStructurally => none + VariantParentIdentityUnavailable { cause: _ } => + if rust_variant_arm_is_bound_somewhere(variant: leaf_name) { + match variant_value_realization_refusal_message(r: r) { + Present { value: m } => Present { value: emit_rust_compile_error_expr(message: m) } + Absent => none + } + } else { none } + VariantTargetValueUnbound { parent: _, variant: _ } => + match variant_value_realization_refusal_message(r: r) { + Present { value: m } => Present { value: emit_rust_compile_error_expr(message: m) } + Absent => none + } + VariantTargetValueAmbiguous { parent: _, variant: _, candidate_count: _ } => + match variant_value_realization_refusal_message(r: r) { + Present { value: m } => Present { value: emit_rust_compile_error_expr(message: m) } + Absent => none + } + } +} + +fn rust_native_variant_spelling_of_binding(binding_kind: VarBindingKind?, leaf_name: String) -> String? { + match binding_kind { + Present { value: VariantValueBinding { parent_enum: _, parent_identity: identity } } => rust_native_variant_spelling(parent: identity, leaf_name: leaf_name) + _ => none + } +} + fn variant_parent_from_binding_kind(binding_kind: VarBindingKind?) -> String? { match binding_kind { - Present { value: VariantValueBinding { parent_enum: parent_enum } } => Present { value: parent_enum } + Present { value: VariantValueBinding { parent_enum: parent_enum, parent_identity: _ } } => Present { value: parent_enum } _ => none } } @@ -10660,6 +10710,12 @@ fn emit_var_ref(name: String, binding_kind: VarBindingKind?, resolved_type: Infe let variant_parent = effective_variant_parent(name: resolved_name, binding_kind: binding_kind, resolved_type: resolved_type, emit_info: emit_info, source_indices: source_indices) if (leaf_name == "none" || leaf_name == "None") && variant_parent == none { emit_none_keyword_for_resolved_type(resolved_type: resolved_type) } else if leaf_name == "true" || leaf_name == "false" { emit_keyword(key: leaf_name, target: Rust) } + else if rust_native_variant_spelling_of_binding(binding_kind: binding_kind, leaf_name: leaf_name) != none { + match rust_native_variant_spelling_of_binding(binding_kind: binding_kind, leaf_name: leaf_name) { + Present { value: s } => s + Absent => "" + } + } else { let moves_by_value = set_contains(emit_info.movable, resolved_name) @@ -10725,6 +10781,9 @@ fn emit_typed_expr_base(texpr: Node, registry: Map, scope: Inf if (leaf_name == "none" || leaf_name == "None") && variant_parent == none { emit_none_keyword_for_resolved_type(resolved_type: texpr.inferred) } else if leaf_name == "true" || leaf_name == "false" { emit_keyword(key: leaf_name, target: Rust) } else { + match rust_native_variant_spelling_of_binding(binding_kind: binding_kind, leaf_name: leaf_name) { + Present { value: native } => native + Absent => match variant_parent { Present { value: enum_name } => if freemonoid_empty_from_variant_parent(leaf_name: leaf_name, enum_name: enum_name) { @@ -10756,6 +10815,7 @@ fn emit_typed_expr_base(texpr: Node, registry: Map, scope: Inf emit_value_ref_ident(name: resolved_name, self_module: scope.module_name, registry: registry, emit_info: emit_info) } } + } } _ => emit_typed_expr(texpr: texpr, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info, fuel: 1024) } @@ -13035,14 +13095,14 @@ fn emit_typed_first_arg(args: List, registry: Map, scope fn freemonoid_match_arm_for(arms: List, variant: String) -> Node? { arms |> filter(arm => match arm_pattern(n: arm) { - VariantPattern { name: n, parent_enum: _, field_bindings: _ } => qualified_last_segment(name: n) == variant + VariantPattern { name: n, parent_enum: _, field_bindings: _, parent_identity: _ } => qualified_last_segment(name: n) == variant _ => false }) |> first } fn arm_resolved_parent_enum(arm: Node, scrut_type: String, type_summaries: Map) -> String? { match arm_pattern(n: arm) { - VariantPattern { name: n, parent_enum: pe, field_bindings: _ } => + VariantPattern { name: n, parent_enum: pe, field_bindings: _, parent_identity: _ } => pattern_parent_enum(name: qualified_last_segment(name: n), parent_enum: pe, scrut_type: scrut_type, type_summaries: type_summaries) _ => none } @@ -13197,7 +13257,7 @@ fn fm_head_bind_name(p: MatchPattern) -> String? { Wildcard => Present { value: "_" } Bind { declaration: d } => Present { value: d.name } LitPattern { value: _ } => none - VariantPattern { name: _, parent_enum: _, field_bindings: _ } => none + VariantPattern { name: _, parent_enum: _, field_bindings: _, parent_identity: _ } => none } } @@ -13217,7 +13277,7 @@ fn fm_analyze_pattern(pattern: MatchPattern, si: Map, fuel Wildcard => FmSpine { exact: false, len: 0, head_binds: [], tail_bind: "_" } Bind { declaration: d } => FmSpine { exact: false, len: 0, head_binds: [], tail_bind: d.name } LitPattern { value: _ } => FmUnsupportedArm { cause: FmLiteralAgainstList } - VariantPattern { name: n, parent_enum: _, field_bindings: fbs } => + VariantPattern { name: n, parent_enum: _, field_bindings: fbs, parent_identity: _ } => let bare = qualified_last_segment(name: n) if bare == "Empty" { FmSpine { exact: true, len: 0, head_binds: [], tail_bind: "" } @@ -13483,7 +13543,7 @@ fn ungroupable_arm_plan(variant: String, pat_str: String) -> RcGroupedArmPlan { fn rc_arm_plain_bindings(pattern: MatchPattern, ref_field: String, source_indices: Map) -> List { match pattern { - VariantPattern { name: _, parent_enum: _, field_bindings: fbs } => + VariantPattern { name: _, parent_enum: _, field_bindings: fbs, parent_identity: _ } => fbs |> flat_map(fb => let fb_name = field_binding_name_at(n: fb, source_indices: source_indices) if fb_name == ref_field { [] } @@ -13500,7 +13560,7 @@ fn rc_arm_plain_bindings(pattern: MatchPattern, ref_field: String, source_indice fn rc_arm_has_refutable_plain_field(pattern: MatchPattern, ref_field: String, source_indices: Map) -> Bool { match pattern { - VariantPattern { name: _, parent_enum: _, field_bindings: fbs } => + VariantPattern { name: _, parent_enum: _, field_bindings: fbs, parent_identity: _ } => fbs |> any(fb => field_binding_name_at(n: fb, source_indices: source_indices) != ref_field && !match_pattern_is_irrefutable(pattern: field_binding_pattern(n: fb)) @@ -13537,7 +13597,7 @@ fn rc_group_representative(entries: List, variant: String) -> fn variant_pattern_field_binding_named(pattern: MatchPattern, field_name: String, source_indices: Map) -> Node? { match pattern { - VariantPattern { name: _, parent_enum: _, field_bindings: fbs } => + VariantPattern { name: _, parent_enum: _, field_bindings: fbs, parent_identity: _ } => fbs |> filter(fb => field_binding_name_at(n: fb, source_indices: source_indices) == field_name) |> first _ => none } @@ -13545,7 +13605,7 @@ fn variant_pattern_field_binding_named(pattern: MatchPattern, field_name: String fn variant_pattern_bare_name(pattern: MatchPattern) -> String { match pattern { - VariantPattern { name: n, parent_enum: _, field_bindings: _ } => qualified_last_segment(name: n) + VariantPattern { name: n, parent_enum: _, field_bindings: _, parent_identity: _ } => qualified_last_segment(name: n) _ => "" } } diff --git a/src/v1/coercion.dag b/src/v1/coercion.dag index 7b6f864042f..26ee2315343 100644 --- a/src/v1/coercion.dag +++ b/src/v1/coercion.dag @@ -17,12 +17,13 @@ import std.decl_ref { DeclarationRef } import std.target_representation { ExactBindingResolution, ResolvedExactBinding, ExactBindingAbsent, ExactBindingAmbiguous, ExactSourceIdentityUnavailable, - resolve_exact_binding, checkpoint_row_migration_for, checkpoint_row_disposition_keeps_bare_row + resolve_exact_binding, checkpoint_row_migration_for, checkpoint_row_disposition_keeps_bare_row, + VariantParentIdentity, VariantValueRealization, variant_value_realization } -import extdeps.languages.rust.representation { RustRepresentation, rust_exact_type_checkpoint } +import extdeps.languages.rust.representation { RustRepresentation, rust_exact_type_checkpoint, rust_representation_eq } -import gunbc.rust_source_type_bindings { rust_source_type_binding_rows, checkpoint_row_migration_rows } +import gunbc.rust_source_type_bindings { rust_source_type_binding_rows, checkpoint_row_migration_rows, rust_source_variant_value_rows } import std.types { container_template_algebra, canonical_container_names, NonEmptyStr } @@ -683,3 +684,27 @@ fn extract_coercion_tests() -> List { copy_tests(), template_application_tests()) } + +// WHAT A VARIANT OCCURRENCE REALIZES AS ON RUST, decided from the declaration-keyed rows +// (gunbc.rust_source_type_bindings rust_source_type_binding_rows and rust_source_variant_value_rows) +// and the identity inference carried on the occurrence -- never from the parent's spelling. Target +// generic in std.target_representation variant_value_realization; this is the Rust binding of it. +fn rust_variant_value_realization(parent: VariantParentIdentity, variant: String) -> VariantValueRealization { + variant_value_realization( + parent: parent, + variant: variant as NonEmptyStr, + bindings: rust_source_type_binding_rows, + values: rust_source_variant_value_rows, + same_representation: fn(a, b) { rust_representation_eq(a: a, b: b) } + ) +} + +// WHETHER AN UNIDENTIFIED VARIANT OCCURRENCE COULD HAVE NEEDED A TARGET VALUE: its arm is spelled +// like an arm some row binds. This never SELECTS a realization -- a spelling cannot, which is the +// whole reason the rows are identity-keyed -- it only decides that an occurrence whose identity was +// not recovered cannot be shown to render structurally, so it must refuse rather than emit the +// source spelling (the absorbing fallback DESIGN section 5 forbids). An unidentified occurrence +// whose arm no row mentions cannot be a native arm and keeps its structural rendering. +fn rust_variant_arm_is_bound_somewhere(variant: String) -> Bool { + rust_source_variant_value_rows |> any(v => (v.variant as String) == variant) +} diff --git a/src/v1/compile.dag b/src/v1/compile.dag index ed0aa0d672e..050ee574577 100644 --- a/src/v1/compile.dag +++ b/src/v1/compile.dag @@ -424,7 +424,7 @@ fn function_value_target(texpr: Node, visible: Map, source_indic match kind { FunctionValueBinding => visible_or_qualified_key(visible: visible, name: authored_name_at(source_indices: source_indices, node: texpr)) LocalValueBinding => none - VariantValueBinding { parent_enum: _ } => none + VariantValueBinding { parent_enum: _, parent_identity: _ } => none MatchBoundBinding => none ServiceValueBinding => none } @@ -828,7 +828,7 @@ fn var_binding_kind_name(value: VarBindingKind) -> String { match value { LocalValueBinding => "LocalValueBinding" FunctionValueBinding => "FunctionValueBinding" - VariantValueBinding { parent_enum: _ } => "VariantValueBinding" + VariantValueBinding { parent_enum: _, parent_identity: _ } => "VariantValueBinding" MatchBoundBinding => "MatchBoundBinding" ServiceValueBinding => "ServiceValueBinding" } @@ -936,7 +936,7 @@ fn serialize_match_pattern(pattern: MatchPattern, source_indices: Map concat("{\"kind\": \"LitPattern\", \"value\": ", serialize_literal(value: inner), "}") - VariantPattern { name: inner, parent_enum: parent_enum, field_bindings: field_bindings } => + VariantPattern { name: inner, parent_enum: parent_enum, field_bindings: field_bindings, parent_identity: _ } => concat( "{\"kind\": \"VariantPattern\", \"name\": ", json_quote(s: inner), ", \"parent_enum\": ", json_optional_string(value: parent_enum), @@ -1121,7 +1121,7 @@ fn serialize_expr_data(expr_node: Node, source_indices: Map concat("{\"kind\": ", json_quote(s: var_binding_kind_name(value: inner)), match inner { - VariantValueBinding { parent_enum: parent_enum } => + VariantValueBinding { parent_enum: parent_enum, parent_identity: _ } => concat(", \"parent_enum\": ", json_quote(s: parent_enum)) _ => "" }, diff --git a/src/v1/compiler_tests_rust.dag b/src/v1/compiler_tests_rust.dag index a86930cf36b..df61624dbe3 100644 --- a/src/v1/compiler_tests_rust.dag +++ b/src/v1/compiler_tests_rust.dag @@ -558,6 +558,52 @@ fn ct_nested_refinement_cast_fixture_closure_discrimination_test() -> String { " }\n\n") } +fn ct_native_bool_variant_fixture_closure_discrimination_test() -> String { + concat( + " /// THE ARMS OF A NATIVELY REALIZED COPRODUCT, JUDGED BY RUSTC, AND THE IDENTITY CONTROL BESIDE IT.\n", + " ///\n", + " /// The subject is `v1.compiler.emit_rust` `rust_native_variant_spelling`: an arm of a\n", + " /// coproduct that realizes natively (std.types Bool over Rust `bool`) is spelled as the\n", + " /// carrier value its declaration-keyed row names, in value, pattern and nested-pattern\n", + " /// position. The first pair's control is that fixture and must COMPILE; before the rows it\n", + " /// emitted `Bool::True` against a `bool` and rustc refused it. The second pair's control is a\n", + " /// module-local coproduct whose arms are spelled True/False, which has no row and must keep its own enum -- the\n", + " /// evidence that the rows are keyed on identity rather than on the spelling. Both reds are\n", + " /// the route's own adjudicated red.\n", + " ///\n", + " /// #[ignore] AND WHY, on the same terms as the pairs beside it: each pair spawns cargo and\n", + " /// compiles two emitted crates. It is RUNNABLE ON DEMAND -- `cargo test --release -p\n", + " /// v1-compiler --lib native_bool_variant_fixture_closure_discrimination -- --ignored`. No CI\n", + " /// path invokes it (gunbc.rung_drop rust_unit_tests_off_the_merge_path); the emitted-bytes\n", + " /// half that does run on the floor is test.claim.native_variant_realization_witness_test.\n", + " #[test]\n", + " #[ignore]\n", + " fn native_bool_variant_fixture_closure_discrimination() {\n", + " let probe_root = crate::cli_run::local_emit_compile_probe_root().unwrap();\n", + " for (label, pair) in [\n", + " (\"native-bool-variant\", crate::cli_run::run_native_bool_variant_discrimination(&probe_root)),\n", + " (\"local-true-false-coproduct\", crate::cli_run::run_local_true_false_coproduct_discrimination(&probe_root)),\n", + " ] {\n", + " for line in crate::cli_run::fixture_discrimination_report(&pair) {\n", + " eprintln!(\"{} {}\", label, line);\n", + " }\n", + " assert!(\n", + " crate::cli_run::fixture_closure_reached_rustc(&pair.red),\n", + " \"{}: the red arm never reached a rustc verdict: {}\",\n", + " label,\n", + " crate::cli_run::fixture_closure_summary(&pair.red)\n", + " );\n", + " assert!(\n", + " crate::cli_run::fixture_discrimination_passed(&pair),\n", + " \"{}: the control must COMPILE and the route red must still be refused by rustc in its own module; control={} red={}\",\n", + " label,\n", + " crate::cli_run::fixture_closure_summary(&pair.green),\n", + " crate::cli_run::fixture_closure_summary(&pair.red)\n", + " );\n", + " }\n", + " }\n\n") +} + fn ct_phantom_marker_identity_fixture_closure_discrimination_test() -> String { concat( " /// THE PHANTOM-MARKER POSITION PAIR, JUDGED BY RUSTC, THROUGH THE FIXTURE-CLOSURE ROUTE.\n", @@ -5099,6 +5145,7 @@ fn compiler_tests_source() -> String { ct_evaluation_budget_consequence_falsifier_test(), ct_function_value_adapter_fixture_closure_discrimination_test(), ct_nested_refinement_cast_fixture_closure_discrimination_test(), + ct_native_bool_variant_fixture_closure_discrimination_test(), ct_phantom_marker_identity_fixture_closure_discrimination_test(), ct_empty_map_turbofish_fixture_closure_discrimination_test(), ct_argv_word_list_splice_fixture_closure_discrimination_test(), diff --git a/src/v1/complexity.dag b/src/v1/complexity.dag index 0588e869099..579a8d93b46 100644 --- a/src/v1/complexity.dag +++ b/src/v1/complexity.dag @@ -1737,7 +1737,7 @@ fn expr_contains_descent(expr: Node, param_name: String, vars: Map fn collect_field_binding_names(fb: Node, vars: Map) -> Map { match field_binding_pattern(n: fb) { Bind { declaration: declaration } => map_insert(vars, declaration.name, true) - VariantPattern { name: _, parent_enum: _, field_bindings: nested } => + VariantPattern { name: _, parent_enum: _, field_bindings: nested, parent_identity: _ } => nested |> fold(init: vars, f: (inner, nested_fb) => collect_field_binding_names(fb: nested_fb, vars: inner) ) @@ -1772,7 +1772,7 @@ fn is_match_option_descent(val: Node, param_name: String, vars: Map any(arm_node => match arm_pattern(n: arm_node) { - VariantPattern { name: _, parent_enum: _, field_bindings: bindings } => + VariantPattern { name: _, parent_enum: _, field_bindings: bindings, parent_identity: _ } => let binding_names = bindings |> fold(init: empty_map(), f: (acc, fb) => collect_field_binding_names(fb: fb, vars: acc) ) @@ -1889,7 +1889,7 @@ fn collect_descent_vars(body: Node, param_name: String, vars: Map, let with_patterns = if scrut_is_descent || scrut_is_param { match_arm_nodes(texpr: body) |> fold(init: vars, f: (acc, arm_node) => match arm_pattern(n: arm_node) { - VariantPattern { name: _, parent_enum: _, field_bindings: bindings } => + VariantPattern { name: _, parent_enum: _, field_bindings: bindings, parent_identity: _ } => bindings |> fold(init: acc, f: (inner, fb) => collect_field_binding_names(fb: fb, vars: inner) ) @@ -1980,7 +1980,7 @@ fn all_self_calls_descend_inc(body: Node, func_name: String, param_name: String, let arms_ok = match_arm_nodes(texpr: body) |> all(arm_node => let arm_vars = if scrut_is_descent || scrut_is_param { match arm_pattern(n: arm_node) { - VariantPattern { name: _, parent_enum: _, field_bindings: bindings } => + VariantPattern { name: _, parent_enum: _, field_bindings: bindings, parent_identity: _ } => bindings |> fold(init: vars, f: (inner, fb) => collect_field_binding_names(fb: fb, vars: inner) ) @@ -2300,7 +2300,7 @@ fn collect_evidence_incremental(body: Node, func_name: String, param_name: Strin else { let arm_vars = if scrut_is_descent || scrut_is_param { match arm_pattern(n: arm_node) { - VariantPattern { name: _, parent_enum: _, field_bindings: bindings } => + VariantPattern { name: _, parent_enum: _, field_bindings: bindings, parent_identity: _ } => bindings |> fold(init: vars, f: (inner, fb) => collect_field_binding_names(fb: fb, vars: inner) ) diff --git a/src/v1/dag_collect.dag b/src/v1/dag_collect.dag index bf584386b4b..03e6b70f2da 100644 --- a/src/v1/dag_collect.dag +++ b/src/v1/dag_collect.dag @@ -97,7 +97,7 @@ fn dag_collect_inferred(value: InferredNode?, slots: Map fn dag_collect_match_pattern(pattern: MatchPattern?, slots: Map, collision_errors: List) -> Map { match pattern { Present { value: Bind { declaration: d } } => dag_collect_insert_slots(node: d, slots: slots, collision_errors: collision_errors) - Present { value: VariantPattern { name: _, parent_enum: _, field_bindings: fbs } } => + Present { value: VariantPattern { name: _, parent_enum: _, field_bindings: fbs, parent_identity: _ } } => dag_collect_nodes_list(nodes: fbs, slots: slots, collision_errors: collision_errors) Present { value: LitPattern { value: _ } } => slots Present { value: Wildcard } => slots diff --git a/src/v1/dag_collect_support.dag b/src/v1/dag_collect_support.dag index 4c60e7bf4bf..2162ca208a3 100644 --- a/src/v1/dag_collect_support.dag +++ b/src/v1/dag_collect_support.dag @@ -137,7 +137,7 @@ fn match_pattern_fingerprint_rec(pattern: MatchPattern?) -> String { hash_combine(atom_identity_hash("Bind"), dag_node_surface_fingerprint_rec(node: d)) Present { value: LitPattern { value: v } } => atom_identity_hash(concat("LitPattern:", literal_value_fingerprint(value: v))) - Present { value: VariantPattern { name: n, parent_enum: pe, field_bindings: fbs } } => + Present { value: VariantPattern { name: n, parent_enum: pe, field_bindings: fbs, parent_identity: _ } } => let base = atom_identity_hash(concat( "VariantPattern:", n, "|", match pe { Present { value: p } => p Absent => "" })) diff --git a/src/v1/stage0/src/cli_run.rs b/src/v1/stage0/src/cli_run.rs index 22c5873d374..b31d4d8ce57 100644 --- a/src/v1/stage0/src/cli_run.rs +++ b/src/v1/stage0/src/cli_run.rs @@ -45353,7 +45353,8 @@ pub(crate) use emitted_closure_compile_host::{ fixture_closure_summary, fixture_discrimination_passed, fixture_discrimination_report, run_append_concat_form_discrimination, run_argv_word_list_splice_discrimination, run_empty_map_turbofish_discrimination, run_fixture_closure_discrimination, - run_function_value_adapter_discrimination, run_nested_refinement_cast_discrimination, + run_function_value_adapter_discrimination, run_local_true_false_coproduct_discrimination, + run_native_bool_variant_discrimination, run_nested_refinement_cast_discrimination, run_phantom_marker_identity_discrimination, run_shell_projection_arity_discrimination, FixtureClosureOutcome, }; diff --git a/src/v1/stage0/src/coproduct_reflection.rs b/src/v1/stage0/src/coproduct_reflection.rs index 15694dd0bcb..edebf322449 100644 --- a/src/v1/stage0/src/coproduct_reflection.rs +++ b/src/v1/stage0/src/coproduct_reflection.rs @@ -2497,6 +2497,9 @@ mod parse_only_uppercase_variant_regression_tests { Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new(VarBindingKind::VariantValueBinding { parent_enum: "Parent".to_string(), + parent_identity: Rc::new( + crate::std_target_representation::VariantParentIdentity::VariantParentBeforeInference, + ), })), }), empty_node_list(), diff --git a/src/v1/stage0/src/data_initializer_identity.rs b/src/v1/stage0/src/data_initializer_identity.rs index 48060b11551..d1c755683a1 100644 --- a/src/v1/stage0/src/data_initializer_identity.rs +++ b/src/v1/stage0/src/data_initializer_identity.rs @@ -430,7 +430,7 @@ fn is_variant_value_binding(expr: &Rc) -> bool { fn variant_value_binding_parent_enum(expr: &Rc) -> Option { match expr_var_binding_kind(expr).as_deref() { - Some(VarBindingKind::VariantValueBinding { parent_enum }) => Some(parent_enum.clone()), + Some(VarBindingKind::VariantValueBinding { parent_enum, .. }) => Some(parent_enum.clone()), _ => None, } } diff --git a/src/v1/stage0/src/emitted_closure_compile_host.rs b/src/v1/stage0/src/emitted_closure_compile_host.rs index 7d5015713d1..b73f3ff07be 100644 --- a/src/v1/stage0/src/emitted_closure_compile_host.rs +++ b/src/v1/stage0/src/emitted_closure_compile_host.rs @@ -1767,6 +1767,45 @@ pub(crate) fn run_nested_refinement_cast_discrimination( } } +/// THE ARMS OF A NATIVELY REALIZED COPRODUCT, POSED TO RUSTC. `std.types` `Bool = True | False` +/// realizes as Rust `bool`, so `True`/`False` in value, pattern and nested-pattern position must be +/// spelled as that carrier's values, from `gunbc.rust_source_type_bindings` +/// `rust_source_variant_value_rows` keyed on the declaration. Before those rows the emitter wrote +/// `Bool::True` against a `bool`: accepted source, rustc E0308 +/// (`gunbc.recurring_failure_mode` `accepted_source_emits_uncompilable_target`). +#[cfg(test)] +const FIXTURE_NATIVE_BOOL_VARIANT_GREEN_PATH: &str = + "fixtures/fixture_closure_rustc/native_bool_variant_probe.dag"; + +/// THE IDENTITY CONTROL for the pair above: a module-local coproduct (`Verdict`) whose arms are +/// spelled `True`/`False` has no row and must keep its own enum. A lowering keyed on the arm +/// spelling would rewrite them to `true`/`false` against an enum, which rustc refuses. +#[cfg(test)] +const FIXTURE_LOCAL_TRUE_FALSE_COPRODUCT_GREEN_PATH: &str = + "fixtures/fixture_closure_rustc/local_true_false_coproduct_probe.dag"; + +/// Both native-variant controls, each against the route's own adjudicated red -- the same arm +/// runner and predicate as every pair beside them, not a second harness. +#[cfg(test)] +pub(crate) fn run_native_bool_variant_discrimination( + probe_root: &PrivateProbeRoot, +) -> FixtureDiscrimination { + FixtureDiscrimination { + green: fixture_arm_verdict(FIXTURE_NATIVE_BOOL_VARIANT_GREEN_PATH, probe_root), + red: fixture_arm_verdict(FIXTURE_RED_PATH, probe_root), + } +} + +#[cfg(test)] +pub(crate) fn run_local_true_false_coproduct_discrimination( + probe_root: &PrivateProbeRoot, +) -> FixtureDiscrimination { + FixtureDiscrimination { + green: fixture_arm_verdict(FIXTURE_LOCAL_TRUE_FALSE_COPRODUCT_GREEN_PATH, probe_root), + red: fixture_arm_verdict(FIXTURE_RED_PATH, probe_root), + } +} + /// THE PHANTOM-MARKER POSITION PAIR, POSED THROUGH THE ROUTE ABOVE (node adhoc-f044ad97-222). /// /// IT IS NOT THE BROAD-VERSUS-POSITIONAL CLASSIFIER DISCRIMINATOR, AND SAYING SO IS THE POINT. diff --git a/src/v1/stage0/src/v1_interpreter.rs b/src/v1/stage0/src/v1_interpreter.rs index 1bcd4cdf3de..0510848e393 100644 --- a/src/v1/stage0/src/v1_interpreter.rs +++ b/src/v1/stage0/src/v1_interpreter.rs @@ -6845,7 +6845,7 @@ fn eval_var( } }; - if let Some(VarBindingKind::VariantValueBinding { parent_enum }) = binding_kind { + if let Some(VarBindingKind::VariantValueBinding { parent_enum, .. }) = binding_kind { // Bounded residual: Nat's intentional native representation is still selected by the // arm lexeme because the seed binding carrier lacks exact owner declaration identity. // The executable shorthand test and GuaranteeStall keep that silent-wrongness path @@ -8603,6 +8603,7 @@ fn match_pattern( name, parent_enum, field_bindings, + .. } => { // A qualified pattern spelling (`module.Variant`) resolves the arm name to its // containment path, but values are constructed with the bare last segment (the From 3b1eecb7524bc77503d177c758b62e1a3739ba27 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Mon, 28 Sep 2026 14:47:08 +0000 Subject: [PATCH 11/21] WIP: kernel arm holds std.kernel_type_name KernelTypeName Co-Authored-By: Claude Opus 5.5 (1M context) --- dag/gunbc/rust_source_type_bindings.dag | 11 ++++++----- dag/std/target_representation.dag | 19 +++++++------------ src/v1/04_infer.dag | 9 +++++---- 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/dag/gunbc/rust_source_type_bindings.dag b/dag/gunbc/rust_source_type_bindings.dag index 0eed5a11d3c..498c36b86e9 100644 --- a/dag/gunbc/rust_source_type_bindings.dag +++ b/dag/gunbc/rust_source_type_bindings.dag @@ -2,8 +2,9 @@ module gunbc.rust_source_type_bindings import std.types { List, String, Bool, NonEmptyStr } import std.decl_ref { DeclarationRef, decl_ref } +import std.kernel_type_name { kernel_type_name, KernelTypeNameAdmitted, NotAKernelTypeName } import std.target_representation { - SourceTypeTargetBinding, SourceVariantTargetValue, VariantParentKey, VariantParentDeclaration, variant_parent_kernel_key, RepresentationValue, + SourceTypeTargetBinding, SourceVariantTargetValue, VariantParentKey, VariantParentDeclaration, VariantParentKernelType, RepresentationValue, CheckpointRowMigration, CheckpointRowDisposition, MigratedToExactBinding, ProvenUniqueKernelBinding, StillBareNameDebt } @@ -70,7 +71,7 @@ data rust_source_type_binding_rows: List List List> { - match variant_parent_kernel_key(kernel_name: "Bool") { - Present { value: k } => rust_bool_variant_rows(parent: k) - Absent => [] + match kernel_type_name(name: "Bool") { + KernelTypeNameAdmitted { kernel_name: k } => rust_bool_variant_rows(parent: VariantParentKernelType { kernel_name: k }) + NotAKernelTypeName { name: _ } => [] } } diff --git a/dag/std/target_representation.dag b/dag/std/target_representation.dag index dc23c878a6d..94a2630d5b2 100644 --- a/dag/std/target_representation.dag +++ b/dag/std/target_representation.dag @@ -1,6 +1,7 @@ module std.target_representation -import std.types { List, String, Bool, Int, NonEmptyStr, is_kernel_type } +import std.types { List, String, Bool, Int, NonEmptyStr } +import std.kernel_type_name { KernelTypeName } import std.decl_ref { DeclarationRef, declaration_ref_eq } // THREE IDENTITIES THAT ONE CHECKPOINT ROW USED TO FUSE, separated because each has a different @@ -148,17 +149,11 @@ type RepresentationValue { // (std.types kernel_type_set) resolves to the KERNEL MINT, which carries no declaration: the kernel // namespace is closed, so the mint's name IS its identity -- the same standing // gunbc.rust_source_type_bindings ProvenUniqueKernelBinding gives the kernel mint at the type level. -// A key is a kernel name only by membership, read through std.types is_kernel_type (the membership -// std.kernel_type_denotation keys on), and it is built only through variant_parent_kernel_key. +// The kernel arm holds std.kernel_type_name KernelTypeName -- the one carrier for "a name +// admitted by std.types is_kernel_type" -- so it is built through kernel_type_name and nowhere else. type VariantParentKey = VariantParentDeclaration { declaration: DeclarationRef } - | VariantParentKernelType { kernel_name: String } - -fn variant_parent_kernel_key(kernel_name: String) -> VariantParentKey? { - if is_kernel_type(name: kernel_name) { - Present { value: VariantParentKernelType { kernel_name: kernel_name } } - } else { none } -} + | VariantParentKernelType { kernel_name: KernelTypeName } fn variant_parent_key_eq(a: VariantParentKey, b: VariantParentKey) -> Bool { match a { @@ -170,7 +165,7 @@ fn variant_parent_key_eq(a: VariantParentKey, b: VariantParentKey) -> Bool { VariantParentKernelType { kernel_name: ka } => match b { VariantParentDeclaration { declaration: _ } => false - VariantParentKernelType { kernel_name: kb } => ka == kb + VariantParentKernelType { kernel_name: kb } => ka.name == kb.name } } } @@ -178,7 +173,7 @@ fn variant_parent_key_eq(a: VariantParentKey, b: VariantParentKey) -> Bool { fn variant_parent_key_label(k: VariantParentKey) -> String { match k { VariantParentDeclaration { declaration: d } => concat(d.module_path as String, ".", d.decl_name as String) - VariantParentKernelType { kernel_name: n } => concat("kernel ", n) + VariantParentKernelType { kernel_name: n } => concat("kernel ", n.name) } } diff --git a/src/v1/04_infer.dag b/src/v1/04_infer.dag index b4854f77711..945da6a0bc2 100644 --- a/src/v1/04_infer.dag +++ b/src/v1/04_infer.dag @@ -10,7 +10,8 @@ import std.content_hash { import extdeps.container.oci.digest { oci_other_digest_algorithm, oci_other_digest_encoded } import std.syntax { Add, Sub, Mul, Div, Mod, Eq, Ne, Lt, Gt, Le, Ge, And, Or, NullCoalesce, BinOp, LitStr, LitInt, LitBool, LiteralValue } import std.decl_ref { DeclarationRef } -import std.target_representation { VariantParentIdentity, VariantParentIdentified, VariantParentUnrecovered, VariantParentDeclaration, variant_parent_kernel_key } +import std.target_representation { VariantParentIdentity, VariantParentIdentified, VariantParentUnrecovered, VariantParentDeclaration, VariantParentKernelType } +import std.kernel_type_name { kernel_type_name, KernelTypeNameAdmitted, NotAKernelTypeName } import std.operator_realization { OperandDeclaration } import std.literal_elaboration { LiteralElaboration, LiteralHomomorphism, LiteralUnfolding, PeanoUnfold, BooleanUnfold, UnicodeScalarSequenceUnfold, @@ -756,9 +757,9 @@ fn variant_parent_identity_of(owner: Node?, scope: InferScope) -> VariantParentI Absent => match declaration_provenance_of(item: o) { KernelMinted { minted_name: m } => - match variant_parent_kernel_key(kernel_name: m) { - Present { value: k } => VariantParentIdentified { key: k } - Absent => VariantParentUnrecovered { cause: "the owning coproduct is a kernel mint whose name is not a kernel type" as NonEmptyStr } + match kernel_type_name(name: m) { + KernelTypeNameAdmitted { kernel_name: k } => VariantParentIdentified { key: VariantParentKernelType { kernel_name: k } } + NotAKernelTypeName { name: _ } => VariantParentUnrecovered { cause: "the owning coproduct is a kernel mint whose name is not a kernel type" as NonEmptyStr } } _ => VariantParentUnrecovered { cause: "the owning coproduct is neither an identified corpus declaration nor a kernel type (alias or unresolved)" as NonEmptyStr } } From 486a84ba970dca94903bbd6afa5325878bb0d395 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Mon, 28 Sep 2026 18:25:35 +0000 Subject: [PATCH 12/21] stage0 regen: native coproduct variant lowering + std.kernel_type_name partition row Co-Authored-By: Claude Opus 5.5 (1M context) --- .../stage0_crate_partition_generated.dag | 1 + src/v1/stage0/src/compiler_tests.rs | 49 ++ src/v1/stage0/src/emitted_population.rs | 1 + .../extdeps_languages_rust_representation.rs | 39 +- .../gunbc_stage0_crate_partition_generated.rs | 2 +- src/v1/stage0/src/std_kernel_type_name.rs | 33 ++ .../stage0/src/std_target_representation.rs | 236 +++++++++ src/v1/stage0/src/v1_compiler_coercion.rs | 44 +- src/v1/stage0/src/v1_compiler_compile.rs | 25 +- .../src/v1_compiler_compiler_tests_rust.rs | 6 +- src/v1/stage0/src/v1_compiler_emit.rs | 5 +- src/v1/stage0/src/v1_compiler_emit_rust.rs | 466 +++++++++++------- src/v1/stage0/src/v1_compiler_infer.rs | 109 +++- src/v1/stage0/src/v1_compiler_parse.rs | 13 + src/v1/stage0/src/v1_std_core.rs | 20 +- src/v1/stage0_std_core/src/lib.rs | 3 + src/v2/workflow/rust_crate_partition.dag | 1 + 17 files changed, 844 insertions(+), 209 deletions(-) create mode 100644 src/v1/stage0/src/std_kernel_type_name.rs diff --git a/dag/gunbc/stage0/stage0_crate_partition_generated.dag b/dag/gunbc/stage0/stage0_crate_partition_generated.dag index 49acb153848..6da1f6258f8 100644 --- a/dag/gunbc/stage0/stage0_crate_partition_generated.dag +++ b/dag/gunbc/stage0/stage0_crate_partition_generated.dag @@ -72,6 +72,7 @@ data generated_partition_crate_rows: List = [ "extdeps_units_iso_80000_3", "std_occurrence_identity", "std_source_annotation", + "std_kernel_type_name", "std_target_representation", "std_literal_elaboration", "std_operator_realization", diff --git a/src/v1/stage0/src/compiler_tests.rs b/src/v1/stage0/src/compiler_tests.rs index c70e817185f..de4fc780b1e 100644 --- a/src/v1/stage0/src/compiler_tests.rs +++ b/src/v1/stage0/src/compiler_tests.rs @@ -1325,6 +1325,55 @@ mod compiler_tests { ); } + /// THE ARMS OF A NATIVELY REALIZED COPRODUCT, JUDGED BY RUSTC, AND THE IDENTITY CONTROL BESIDE IT. + /// + /// The subject is `v1.compiler.emit_rust` `rust_native_variant_spelling`: an arm of a + /// coproduct that realizes natively (std.types Bool over Rust `bool`) is spelled as the + /// carrier value its declaration-keyed row names, in value, pattern and nested-pattern + /// position. The first pair's control is that fixture and must COMPILE; before the rows it + /// emitted `Bool::True` against a `bool` and rustc refused it. The second pair's control is a + /// module-local coproduct whose arms are spelled True/False, which has no row and must keep its own enum -- the + /// evidence that the rows are keyed on identity rather than on the spelling. Both reds are + /// the route's own adjudicated red. + /// + /// #[ignore] AND WHY, on the same terms as the pairs beside it: each pair spawns cargo and + /// compiles two emitted crates. It is RUNNABLE ON DEMAND -- `cargo test --release -p + /// v1-compiler --lib native_bool_variant_fixture_closure_discrimination -- --ignored`. No CI + /// path invokes it (gunbc.rung_drop rust_unit_tests_off_the_merge_path); the emitted-bytes + /// half that does run on the floor is test.claim.native_variant_realization_witness_test. + #[test] + #[ignore] + fn native_bool_variant_fixture_closure_discrimination() { + let probe_root = crate::cli_run::local_emit_compile_probe_root().unwrap(); + for (label, pair) in [ + ( + "native-bool-variant", + crate::cli_run::run_native_bool_variant_discrimination(&probe_root), + ), + ( + "local-true-false-coproduct", + crate::cli_run::run_local_true_false_coproduct_discrimination(&probe_root), + ), + ] { + for line in crate::cli_run::fixture_discrimination_report(&pair) { + eprintln!("{} {}", label, line); + } + assert!( + crate::cli_run::fixture_closure_reached_rustc(&pair.red), + "{}: the red arm never reached a rustc verdict: {}", + label, + crate::cli_run::fixture_closure_summary(&pair.red) + ); + assert!( + crate::cli_run::fixture_discrimination_passed(&pair), + "{}: the control must COMPILE and the route red must still be refused by rustc in its own module; control={} red={}", + label, + crate::cli_run::fixture_closure_summary(&pair.green), + crate::cli_run::fixture_closure_summary(&pair.red) + ); + } + } + /// THE PHANTOM-MARKER POSITION PAIR, JUDGED BY RUSTC, THROUGH THE FIXTURE-CLOSURE ROUTE. /// /// NOT THE BROAD-VERSUS-POSITIONAL CLASSIFIER DISCRIMINATOR. That one's arms are two diff --git a/src/v1/stage0/src/emitted_population.rs b/src/v1/stage0/src/emitted_population.rs index 6e1c13dea52..6417234400d 100644 --- a/src/v1/stage0/src/emitted_population.rs +++ b/src/v1/stage0/src/emitted_population.rs @@ -67,6 +67,7 @@ // src/std_induction.rs // src/std_integer.rs // src/std_interface_summary.rs +// src/std_kernel_type_name.rs // src/std_keyed_roster.rs // src/std_keyed_row.rs // src/std_literal_elaboration.rs diff --git a/src/v1/stage0/src/extdeps_languages_rust_representation.rs b/src/v1/stage0/src/extdeps_languages_rust_representation.rs index 5b789b0217f..6dda87d9cd9 100644 --- a/src/v1/stage0/src/extdeps_languages_rust_representation.rs +++ b/src/v1/stage0/src/extdeps_languages_rust_representation.rs @@ -6,7 +6,9 @@ pub use crate::extdeps_external_authority::ExternalAuthority; use crate::extdeps_uri::UriScheme::Https; pub use crate::extdeps_uri::{Uri, UriScheme}; pub use crate::std_coercion::TypeCheckpoint; -pub use crate::std_target_representation::{RepresentationSpelling, SourceTypeTargetBinding}; +pub use crate::std_target_representation::{ + RepresentationSpelling, RepresentationValue, SourceTypeTargetBinding, +}; use crate::std_types::Bool::*; pub use crate::std_types::{Bool, List, NonEmptyStr}; use crate::v1_rt; @@ -137,6 +139,41 @@ pub fn rust_exact_type_checkpoint( } } +pub fn rust_bool_true_value() -> Rc> { + thread_local! { + static CACHED: Rc> = { + Rc::new(RepresentationValue { + representation: RustRepresentation::RustBool, + value_spelling: "true".to_string(), + _phantom: std::marker::PhantomData, + }) + }; + } + CACHED.with(|c: &Rc>| c.clone()) +} + +pub fn rust_bool_false_value() -> Rc> { + thread_local! { + static CACHED: Rc> = { + Rc::new(RepresentationValue { + representation: RustRepresentation::RustBool, + value_spelling: "false".to_string(), + _phantom: std::marker::PhantomData, + }) + }; + } + CACHED.with(|c: &Rc>| c.clone()) +} + +pub fn rust_representation_values() -> Rc>>> { + thread_local! { + static CACHED: Rc>>> = { + Rc::new(vec![rust_bool_true_value(), rust_bool_false_value()]) + }; + } + CACHED.with(|c: &Rc>>>| c.clone()) +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct RustStdString; #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] diff --git a/src/v1/stage0/src/gunbc_stage0_crate_partition_generated.rs b/src/v1/stage0/src/gunbc_stage0_crate_partition_generated.rs index 8c4426b1c82..35def67949f 100644 --- a/src/v1/stage0/src/gunbc_stage0_crate_partition_generated.rs +++ b/src/v1/stage0/src/gunbc_stage0_crate_partition_generated.rs @@ -54,7 +54,7 @@ pub fn generated_partition_crate_rows() -> Rc package_name: "v1-stage0-std-core".to_string(), crate_dir: "src/v1/stage0_std_core".to_string(), kind: GeneratedPartitionCrateKind::GeneratedLayeredCoreCrate, - modules: Rc::new(vec!["std_content_hash".to_string(), "std_coercion".to_string(), "extdeps_currency_currency".to_string(), "std_decl_ref".to_string(), "std_keyed_row".to_string(), "std_keyed_roster".to_string(), "std_roster_frontier".to_string(), "std_dissolution".to_string(), "std_disposition".to_string(), "std_error_primitives".to_string(), "std_emit_model".to_string(), "std_magnitude".to_string(), "std_measure".to_string(), "std_types".to_string(), "std_unicode_types".to_string(), "std_algebra".to_string(), "std_nat".to_string(), "std_node".to_string(), "std_syntax".to_string(), "std_computation".to_string(), "std_termination".to_string(), "std_checked_arithmetic".to_string(), "std_induction".to_string(), "std_graph".to_string(), "extdeps_uri".to_string(), "extdeps_external_authority".to_string(), "extdeps_ietf_http_semantics".to_string(), "std_process_termination".to_string(), "std_primitive_projection".to_string(), "extdeps_container_oci_digest".to_string(), "extdeps_units_dimensionless".to_string(), "extdeps_units_iec_80000_13".to_string(), "extdeps_units_iso8601".to_string(), "extdeps_units_iso_80000_3".to_string(), "std_occurrence_identity".to_string(), "std_source_annotation".to_string(), "std_target_representation".to_string(), "std_literal_elaboration".to_string(), "std_operator_realization".to_string(), "std_import".to_string(), "v1_std_core".to_string(), "gunbc_rust_emitted_edge".to_string()]), + modules: Rc::new(vec!["std_content_hash".to_string(), "std_coercion".to_string(), "extdeps_currency_currency".to_string(), "std_decl_ref".to_string(), "std_keyed_row".to_string(), "std_keyed_roster".to_string(), "std_roster_frontier".to_string(), "std_dissolution".to_string(), "std_disposition".to_string(), "std_error_primitives".to_string(), "std_emit_model".to_string(), "std_magnitude".to_string(), "std_measure".to_string(), "std_types".to_string(), "std_unicode_types".to_string(), "std_algebra".to_string(), "std_nat".to_string(), "std_node".to_string(), "std_syntax".to_string(), "std_computation".to_string(), "std_termination".to_string(), "std_checked_arithmetic".to_string(), "std_induction".to_string(), "std_graph".to_string(), "extdeps_uri".to_string(), "extdeps_external_authority".to_string(), "extdeps_ietf_http_semantics".to_string(), "std_process_termination".to_string(), "std_primitive_projection".to_string(), "extdeps_container_oci_digest".to_string(), "extdeps_units_dimensionless".to_string(), "extdeps_units_iec_80000_13".to_string(), "extdeps_units_iso8601".to_string(), "extdeps_units_iso_80000_3".to_string(), "std_occurrence_identity".to_string(), "std_source_annotation".to_string(), "std_kernel_type_name".to_string(), "std_target_representation".to_string(), "std_literal_elaboration".to_string(), "std_operator_realization".to_string(), "std_import".to_string(), "v1_std_core".to_string(), "gunbc_rust_emitted_edge".to_string()]), reexport_packages: Rc::new(vec!["v1-stage0-runtime".to_string()]), carries_non_empty_wrappers: false, }), Rc::new(GeneratedPartitionCrateRow { diff --git a/src/v1/stage0/src/std_kernel_type_name.rs b/src/v1/stage0/src/std_kernel_type_name.rs new file mode 100644 index 00000000000..bf11202d386 --- /dev/null +++ b/src/v1/stage0/src/std_kernel_type_name.rs @@ -0,0 +1,33 @@ +// Generated by v1 compiler -- do not edit. +// Source module: std.kernel_type_name + +use self::KernelTypeNameAdmission::*; +pub use crate::std_types::is_kernel_type; +use crate::v1_rt; +use crate::v1_rt::{VecCompat, VecJoin}; +use crate::NonEmptyBTreeSet; +use crate::NonEmptyVec; +use im::{vector as vec, HashMap, OrdSet as BTreeSet, Vector as Vec}; +use std::rc::Rc; + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct KernelTypeName { + pub name: String, +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +#[serde(tag = "_variant")] +pub enum KernelTypeNameAdmission { + KernelTypeNameAdmitted { kernel_name: Rc }, + NotAKernelTypeName { name: String }, +} + +pub fn kernel_type_name(name: String) -> Rc { + if crate::std_types::is_kernel_type(name.clone()) { + Rc::new(KernelTypeNameAdmission::KernelTypeNameAdmitted { + kernel_name: Rc::new(KernelTypeName { name: name.clone() }), + }) + } else { + Rc::new(KernelTypeNameAdmission::NotAKernelTypeName { name: name.clone() }) + } +} diff --git a/src/v1/stage0/src/std_target_representation.rs b/src/v1/stage0/src/std_target_representation.rs index b0fc0742568..031fe341f30 100644 --- a/src/v1/stage0/src/std_target_representation.rs +++ b/src/v1/stage0/src/std_target_representation.rs @@ -3,8 +3,12 @@ use self::CheckpointRowDisposition::*; use self::ExactBindingResolution::*; +use self::VariantParentIdentity::*; +use self::VariantParentKey::*; +use self::VariantValueRealization::*; pub use crate::std_decl_ref::declaration_ref_eq; pub use crate::std_decl_ref::DeclarationRef; +pub use crate::std_kernel_type_name::KernelTypeName; use crate::std_types::Bool::*; pub use crate::std_types::{Bool, List, NonEmptyStr}; use crate::v1_rt; @@ -171,3 +175,235 @@ pub fn checkpoint_row_migration_for( .first() .cloned() } + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct RepresentationValue { + pub representation: R, + pub value_spelling: NonEmptyStr, + pub _phantom: std::marker::PhantomData, +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +#[serde(tag = "_variant")] +pub enum VariantParentKey { + VariantParentDeclaration { declaration: Rc }, + VariantParentKernelType { kernel_name: Rc }, +} + +pub fn variant_parent_key_eq(a: Rc, b: Rc) -> bool { + match (*a.clone()).clone() { + VariantParentKey::VariantParentDeclaration { + declaration: da, .. + } => match (*b.clone()).clone() { + VariantParentKey::VariantParentDeclaration { + declaration: db, .. + } => crate::std_decl_ref::declaration_ref_eq(da.clone(), db.clone()), + VariantParentKey::VariantParentKernelType { kernel_name: _, .. } => false, + }, + VariantParentKey::VariantParentKernelType { + kernel_name: ka, .. + } => match (*b.clone()).clone() { + VariantParentKey::VariantParentDeclaration { declaration: _, .. } => false, + VariantParentKey::VariantParentKernelType { + kernel_name: kb, .. + } => (ka.name.clone() == kb.name.clone()), + }, + } +} + +pub fn variant_parent_key_label(k: Rc) -> String { + match (*k.clone()).clone() { + VariantParentKey::VariantParentDeclaration { declaration: d, .. } => v1_rt::concat( + v1_rt::concat(d.module_path.clone(), ".".to_string()), + d.decl_name.clone(), + ), + VariantParentKey::VariantParentKernelType { kernel_name: n, .. } => { + v1_rt::concat("kernel ".to_string(), n.name.clone()) + } + } +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct SourceVariantTargetValue { + pub parent: Rc, + pub variant: NonEmptyStr, + pub value: Rc>, + pub _phantom: std::marker::PhantomData, +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +#[serde(tag = "_variant")] +pub enum VariantParentIdentity { + VariantParentIdentified { key: Rc }, + VariantParentUnrecovered { cause: NonEmptyStr }, + VariantParentBeforeInference, +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +#[serde(tag = "_variant")] +pub enum VariantValueRealization { + VariantRealizesAsTargetValue { + value_spelling: NonEmptyStr, + }, + VariantRealizesStructurally, + VariantTargetValueUnbound { + parent: Rc, + variant: NonEmptyStr, + }, + VariantTargetValueAmbiguous { + parent: Rc, + variant: NonEmptyStr, + candidate_count: i64, + }, + VariantParentIdentityUnavailable { + cause: NonEmptyStr, + }, +} + +pub fn variant_rows_for( + key: Rc, + variant: String, + values: Rc>>>, +) -> Rc>>> { + Rc::new({ + let mut __result = Vec::new(); + for v in values.iter().cloned() { + if (variant_parent_key_eq(v.parent.clone(), key.clone()) + && (v.variant.clone() == variant.clone())) + { + __result.push(v); + } + } + __result + }) +} + +pub fn variant_value_from_hits( + key: Rc, + variant: String, + hits: Rc>>>, +) -> Rc { + { + let n = (hits.clone().len() as i64); + if (n.clone() == 1) { + match hits.clone().first().cloned() { + Some(v) => Rc::new(VariantValueRealization::VariantRealizesAsTargetValue { + value_spelling: v.value.clone().value_spelling.clone(), + }), + std::option::Option::None => { + Rc::new(VariantValueRealization::VariantTargetValueUnbound { + parent: key.clone(), + variant: variant.clone(), + }) + } + } + } else { + if (n.clone() == 0) { + Rc::new(VariantValueRealization::VariantTargetValueUnbound { + parent: key.clone(), + variant: variant.clone(), + }) + } else { + Rc::new(VariantValueRealization::VariantTargetValueAmbiguous { + parent: key.clone(), + variant: variant.clone(), + candidate_count: n.clone(), + }) + } + } + } +} + +pub fn variant_value_realization( + parent: Rc, + variant: String, + bindings: Rc>>>, + values: Rc>>>, + same_representation: impl Fn(R, R) -> bool + Clone, +) -> Rc { + match (*parent.clone()).clone() { + VariantParentIdentity::VariantParentBeforeInference => { + Rc::new(VariantValueRealization::VariantParentIdentityUnavailable { + cause: "the variant was never read by inference".to_string(), + }) + } + VariantParentIdentity::VariantParentUnrecovered { cause: c, .. } => { + Rc::new(VariantValueRealization::VariantParentIdentityUnavailable { cause: c.clone() }) + } + VariantParentIdentity::VariantParentIdentified { key: key, .. } => match (*key.clone()) + .clone() + { + VariantParentKey::VariantParentKernelType { kernel_name: _, .. } => { + let kernel_rows = Rc::new({ + let mut __result = Vec::new(); + for v in values.iter().cloned() { + if variant_parent_key_eq(v.parent.clone(), key.clone()) { + __result.push(v); + } + } + __result + }); + if ((kernel_rows.clone().len() as i64) == 0) { + Rc::new(VariantValueRealization::VariantRealizesStructurally) + } else { + variant_value_from_hits( + key.clone(), + variant.clone(), + variant_rows_for(key.clone(), variant.clone(), values.clone()), + ) + } + } + VariantParentKey::VariantParentDeclaration { declaration: d, .. } => { + match (*resolve_exact_binding(Some(d.clone()), bindings.clone())).clone() { + ExactBindingResolution::ExactBindingAbsent => { + Rc::new(VariantValueRealization::VariantRealizesStructurally) + } + ExactBindingResolution::ExactSourceIdentityUnavailable { cause: c, .. } => { + Rc::new(VariantValueRealization::VariantParentIdentityUnavailable { + cause: c.clone(), + }) + } + ExactBindingResolution::ExactBindingAmbiguous { + candidate_count: n, .. + } => Rc::new(VariantValueRealization::VariantTargetValueAmbiguous { + parent: key.clone(), + variant: variant.clone(), + candidate_count: n.clone(), + }), + ExactBindingResolution::ResolvedExactBinding { binding: b, .. } => { + variant_value_from_hits( + key.clone(), + variant.clone(), + Rc::new({ + let mut __result = Vec::new(); + for v in + variant_rows_for(key.clone(), variant.clone(), values.clone()) + .iter() + .cloned() + { + if same_representation( + v.value.clone().representation.clone(), + b.representation.clone(), + ) { + __result.push(v); + } + } + __result + }), + ) + } + } + } + }, + } +} + +pub fn variant_value_realization_refusal_message(r: Rc) -> Option { + match (*r.clone()).clone() { + VariantValueRealization::VariantRealizesAsTargetValue { value_spelling: _, .. } => std::option::Option::None, + VariantValueRealization::VariantRealizesStructurally => std::option::Option::None, + VariantValueRealization::VariantTargetValueUnbound { parent: p, variant: v, .. } => Some(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat("variant realization: ".to_string(), variant_parent_key_label(p.clone())), " realizes natively on this target but its arm `".to_string()), v.clone()), "` has no target value row; the source spelling cannot be emitted against the native carrier".to_string())), + VariantValueRealization::VariantTargetValueAmbiguous { parent: p, variant: v, candidate_count: n, .. } => Some(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat("variant realization: arm `".to_string(), v.clone()), "` of ".to_string()), variant_parent_key_label(p.clone())), " has ".to_string()), (n.clone()).to_string()), " target value rows (corpus authoring defect)".to_string())), + VariantValueRealization::VariantParentIdentityUnavailable { cause: c, .. } => Some(v1_rt::concat(v1_rt::concat("variant realization: the coproduct this variant belongs to was not recovered (".to_string(), c.clone()), "), so whether it realizes natively cannot be decided".to_string())), +} +} diff --git a/src/v1/stage0/src/v1_compiler_coercion.rs b/src/v1/stage0/src/v1_compiler_coercion.rs index d7c3bb2202f..58312be062e 100644 --- a/src/v1/stage0/src/v1_compiler_coercion.rs +++ b/src/v1/stage0/src/v1_compiler_coercion.rs @@ -10,15 +10,17 @@ pub use crate::extdeps_languages_python_types::{ python_algebra_inhabitants, python_callable, python_cast_syntax, python_optional_template, python_type_checkpoints, }; -pub use crate::extdeps_languages_rust_representation::rust_exact_type_checkpoint; pub use crate::extdeps_languages_rust_representation::RustRepresentation; use crate::extdeps_languages_rust_representation::RustRepresentation::*; +pub use crate::extdeps_languages_rust_representation::{ + rust_exact_type_checkpoint, rust_representation_eq, +}; pub use crate::extdeps_languages_rust_types::{ rust_algebra_inhabitants, rust_callable, rust_cast_syntax, rust_optional_template, rust_type_checkpoints, }; pub use crate::gunbc_rust_source_type_bindings::{ - checkpoint_row_migration_rows, rust_source_type_binding_rows, + checkpoint_row_migration_rows, rust_source_type_binding_rows, rust_source_variant_value_rows, }; use crate::std_coercion::RealizationGround::{ GroundedByCheckpointRow, GroundedByHostNumericAlias, GroundedByUnidentifiedBareRow, @@ -37,12 +39,17 @@ pub use crate::std_coercion::{ TypeCheckpoint, TypeDeclarationProvenance, TypeRealizationDecision, }; pub use crate::std_decl_ref::DeclarationRef; -pub use crate::std_target_representation::ExactBindingResolution; use crate::std_target_representation::ExactBindingResolution::{ ExactBindingAbsent, ExactBindingAmbiguous, ExactSourceIdentityUnavailable, ResolvedExactBinding, }; +use crate::std_target_representation::VariantParentIdentity::*; +use crate::std_target_representation::VariantValueRealization::*; pub use crate::std_target_representation::{ checkpoint_row_disposition_keeps_bare_row, checkpoint_row_migration_for, resolve_exact_binding, + variant_value_realization, +}; +pub use crate::std_target_representation::{ + ExactBindingResolution, VariantParentIdentity, VariantValueRealization, }; pub use crate::std_types::NonEmptyStr; pub use crate::std_types::{canonical_container_names, container_template_algebra}; @@ -823,3 +830,34 @@ pub fn extract_coercion_tests() -> Rc>> { template_application_tests(), ) } + +pub fn rust_variant_value_realization( + parent: Rc, + variant: String, +) -> Rc { + crate::std_target_representation::variant_value_realization( + parent.clone(), + variant.clone(), + rust_source_type_binding_rows(), + rust_source_variant_value_rows(), + |a, b| { + crate::extdeps_languages_rust_representation::rust_representation_eq( + a.clone(), + b.clone(), + ) + }, + ) +} + +pub fn rust_variant_arm_is_bound_somewhere(variant: String) -> bool { + { + let mut __found = false; + for v in rust_source_variant_value_rows().iter().cloned() { + if (v.variant.clone() == variant.clone()) { + __found = true; + break; + } + } + __found + } +} diff --git a/src/v1/stage0/src/v1_compiler_compile.rs b/src/v1/stage0/src/v1_compiler_compile.rs index dc0fb2eb0db..5426a3302c7 100644 --- a/src/v1/stage0/src/v1_compiler_compile.rs +++ b/src/v1/stage0/src/v1_compiler_compile.rs @@ -682,9 +682,7 @@ pub fn function_value_target( crate::v1_std_core::authored_name_at(source_indices.clone(), texpr.clone()), ), VarBindingKind::LocalValueBinding => std::option::Option::None, - VarBindingKind::VariantValueBinding { parent_enum: _, .. } => { - std::option::Option::None - } + VarBindingKind::VariantValueBinding { .. } => std::option::Option::None, VarBindingKind::MatchBoundBinding => std::option::Option::None, VarBindingKind::ServiceValueBinding => std::option::Option::None, }, @@ -1692,9 +1690,7 @@ pub fn var_binding_kind_name(value: Rc) -> String { match (*value.clone()).clone() { VarBindingKind::LocalValueBinding => "LocalValueBinding".to_string(), VarBindingKind::FunctionValueBinding => "FunctionValueBinding".to_string(), - VarBindingKind::VariantValueBinding { parent_enum: _, .. } => { - "VariantValueBinding".to_string() - } + VarBindingKind::VariantValueBinding { .. } => "VariantValueBinding".to_string(), VarBindingKind::MatchBoundBinding => "MatchBoundBinding".to_string(), VarBindingKind::ServiceValueBinding => "ServiceValueBinding".to_string(), } @@ -2480,15 +2476,14 @@ pub fn serialize_expr_data( ), ), match (*inner.clone()).clone() { - VarBindingKind::VariantValueBinding { - parent_enum: parent_enum, - .. - } => v1_rt::concat( - ", \"parent_enum\": ".to_string(), - crate::v1_compiler_dag_collect_support::json_quote( - parent_enum.clone(), - ), - ), + VarBindingKind::VariantValueBinding { parent_enum, .. } => { + v1_rt::concat( + ", \"parent_enum\": ".to_string(), + crate::v1_compiler_dag_collect_support::json_quote( + parent_enum.clone(), + ), + ) + } _ => "".to_string(), }, ), diff --git a/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs b/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs index 809af6003e8..dbec24f712e 100644 --- a/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs +++ b/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs @@ -64,6 +64,10 @@ pub fn ct_nested_refinement_cast_fixture_closure_discrimination_test() -> String v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(" /// REPRESENTATION-IDENTICAL REFINEMENT AND BRAND CASTS, JUDGED BY RUSTC (gunbc#10266).\n".to_string(), " ///\n".to_string()), " /// The subject is `v1.compiler.emit` `cast_representation_identical`: a cast whose source and\n".to_string()), " /// target are ONE host carrier reached through transparent refinement, alias and brand edges\n".to_string()), " /// asks the target for no operation, so the emission must be the operand unchanged. The\n".to_string()), " /// fixture exercises six such casts across three aliases in BOTH directions, plus one genuine\n".to_string()), " /// numeric conversion that must still go through the target cast syntax.\n".to_string()), " ///\n".to_string()), " /// WHY THIS SUBJECT NEEDS RUSTC AND NOT A SUBSTRING. `test.claim`\n".to_string()), " /// `emitter_nested_refinement_cast_witness_test` asserts the ABSENCE of the fabricated\n".to_string()), " /// unsupported-cast text, and absence is all a spelling oracle can honestly assert here:\n".to_string()), " /// asserting the presence of a particular replacement would pin one rendering of \"the operand\n".to_string()), " /// unchanged\". Whether the replacement TYPE-CHECKS as the declared return is a meaning-level\n".to_string()), " /// question, and the never type is exactly what let the defective form pass a type check.\n".to_string()), " ///\n".to_string()), " /// THE RED ARM IS THE ROUTE'S OWN, so this pair proves the route can still fail using the\n".to_string()), " /// discrimination already adjudicated for it rather than a fresh unadjudicated arm.\n".to_string()), " ///\n".to_string()), " /// #[ignore] AND WHY, on the same terms as the two pairs beside it: this arm spawns cargo and\n".to_string()), " /// compiles two emitted crates, which is minutes rather than milliseconds. It is ENROLLED AND\n".to_string()), " /// OPT-IN -- `cargo test --release -p v1-compiler --lib\n".to_string()), " /// nested_refinement_cast_fixture_closure_discrimination -- --ignored`. An #[ignore] is a cost\n".to_string()), " /// decision and NOT a rung: nothing here may be cited as coverage that executes on the merge\n".to_string()), " /// path.\n".to_string()), " #[test]\n".to_string()), " #[ignore]\n".to_string()), " fn nested_refinement_cast_fixture_closure_discrimination() {\n".to_string()), " let probe_root = crate::cli_run::local_emit_compile_probe_root().unwrap();\n".to_string()), " let pair = crate::cli_run::run_nested_refinement_cast_discrimination(&probe_root);\n".to_string()), " for line in crate::cli_run::fixture_discrimination_report(&pair) {\n".to_string()), " eprintln!(\"nested-refinement-cast {}\", line);\n".to_string()), " }\n".to_string()), " assert!(\n".to_string()), " crate::cli_run::fixture_closure_reached_rustc(&pair.red),\n".to_string()), " \"the red arm never reached a rustc verdict, so nothing about the emitted bytes was measured: {}\",\n".to_string()), " crate::cli_run::fixture_closure_summary(&pair.red)\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " crate::cli_run::fixture_discrimination_passed(&pair),\n".to_string()), " \"the representation-identical cast control must COMPILE -- an unsupported-cast panic emitted for any of its six casts is a type error at the declared return -- and the route red must still be refused by rustc in its own emitted module with the claimed error class; control={} red={} attribution={:?} diagnostic={:?}\",\n".to_string()), " crate::cli_run::fixture_closure_summary(&pair.green),\n".to_string()), " crate::cli_run::fixture_closure_summary(&pair.red),\n".to_string()), " crate::cli_run::fixture_closure_attributed_line(&pair.red),\n".to_string()), " crate::cli_run::fixture_closure_attributed_diagnostic(&pair.red)\n".to_string()), " );\n".to_string()), " }\n\n".to_string()) } +pub fn ct_native_bool_variant_fixture_closure_discrimination_test() -> String { + v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(" /// THE ARMS OF A NATIVELY REALIZED COPRODUCT, JUDGED BY RUSTC, AND THE IDENTITY CONTROL BESIDE IT.\n".to_string(), " ///\n".to_string()), " /// The subject is `v1.compiler.emit_rust` `rust_native_variant_spelling`: an arm of a\n".to_string()), " /// coproduct that realizes natively (std.types Bool over Rust `bool`) is spelled as the\n".to_string()), " /// carrier value its declaration-keyed row names, in value, pattern and nested-pattern\n".to_string()), " /// position. The first pair's control is that fixture and must COMPILE; before the rows it\n".to_string()), " /// emitted `Bool::True` against a `bool` and rustc refused it. The second pair's control is a\n".to_string()), " /// module-local coproduct whose arms are spelled True/False, which has no row and must keep its own enum -- the\n".to_string()), " /// evidence that the rows are keyed on identity rather than on the spelling. Both reds are\n".to_string()), " /// the route's own adjudicated red.\n".to_string()), " ///\n".to_string()), " /// #[ignore] AND WHY, on the same terms as the pairs beside it: each pair spawns cargo and\n".to_string()), " /// compiles two emitted crates. It is RUNNABLE ON DEMAND -- `cargo test --release -p\n".to_string()), " /// v1-compiler --lib native_bool_variant_fixture_closure_discrimination -- --ignored`. No CI\n".to_string()), " /// path invokes it (gunbc.rung_drop rust_unit_tests_off_the_merge_path); the emitted-bytes\n".to_string()), " /// half that does run on the floor is test.claim.native_variant_realization_witness_test.\n".to_string()), " #[test]\n".to_string()), " #[ignore]\n".to_string()), " fn native_bool_variant_fixture_closure_discrimination() {\n".to_string()), " let probe_root = crate::cli_run::local_emit_compile_probe_root().unwrap();\n".to_string()), " for (label, pair) in [\n".to_string()), " (\"native-bool-variant\", crate::cli_run::run_native_bool_variant_discrimination(&probe_root)),\n".to_string()), " (\"local-true-false-coproduct\", crate::cli_run::run_local_true_false_coproduct_discrimination(&probe_root)),\n".to_string()), " ] {\n".to_string()), " for line in crate::cli_run::fixture_discrimination_report(&pair) {\n".to_string()), " eprintln!(\"{} {}\", label, line);\n".to_string()), " }\n".to_string()), " assert!(\n".to_string()), " crate::cli_run::fixture_closure_reached_rustc(&pair.red),\n".to_string()), " \"{}: the red arm never reached a rustc verdict: {}\",\n".to_string()), " label,\n".to_string()), " crate::cli_run::fixture_closure_summary(&pair.red)\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " crate::cli_run::fixture_discrimination_passed(&pair),\n".to_string()), " \"{}: the control must COMPILE and the route red must still be refused by rustc in its own module; control={} red={}\",\n".to_string()), " label,\n".to_string()), " crate::cli_run::fixture_closure_summary(&pair.green),\n".to_string()), " crate::cli_run::fixture_closure_summary(&pair.red)\n".to_string()), " );\n".to_string()), " }\n".to_string()), " }\n\n".to_string()) +} + pub fn ct_phantom_marker_identity_fixture_closure_discrimination_test() -> String { v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(" /// THE PHANTOM-MARKER POSITION PAIR, JUDGED BY RUSTC, THROUGH THE FIXTURE-CLOSURE ROUTE.\n".to_string(), " ///\n".to_string()), " /// NOT THE BROAD-VERSUS-POSITIONAL CLASSIFIER DISCRIMINATOR. That one's arms are two\n".to_string()), " /// COMPILER behaviours over ONE source, and no pair of fixture FILES can be those arms --\n".to_string()), " /// files vary the source and hold the compiler fixed. This does not discharge that ceiling\n".to_string()), " /// row, which stays at MeaningDiscriminatorExecutedNotEnrolled (codex review 60742).\n".to_string()), " ///\n".to_string()), " /// The subject is `v1.compiler.emit_rust` `rust_type_arg_identity_spelling`: a type argument's\n".to_string()), " /// Rust identity is decided from the declaration visible in the module, never from the\n".to_string()), " /// syntactic position that happened to render it. `test.claim`\n".to_string()), " /// `phantom_marker_type_argument_identity_witness` already adjudicates the SPELLING half of\n".to_string()), " /// that decision across every outer renderer and STAYS ENROLLED (DESIGN 4b(4): a climb deletes\n".to_string()), " /// lower-rung production machinery, never the evidence). This arm is the half that witness\n".to_string()), " /// declares it cannot reach -- `compile_dag_rust_emit_check` stops at emitted TEXT and never\n".to_string()), " /// invokes rustc, which is what pinned that class at SourceToEmittedTextHonestyOnly.\n".to_string()), " ///\n".to_string()), " /// WHAT THE TWO ARMS ARE, AND WHAT THEY DO NOT ISOLATE. Both declare the same coproduct\n".to_string()), " /// `Marker = Alpha | Beta`. The control puts `Alpha` and `Beta` in the RULED POSITION --\n".to_string()), " /// arguments of an applied type node -- where they become distinct zero-sized markers, and\n".to_string()), " /// its emitted crate COMPILES. The red puts `Alpha` in a NON-APPLIED position, a record\n".to_string()), " /// field, and returns that `Alpha`-typed field from a function declared to return `Marker`;\n".to_string()), " /// its emitted crate is REFUSED at that return. So a green here is not \"some crate compiled\"\n".to_string()), " /// and the red is not \"something in the tree is broken\".\n".to_string()), " ///\n".to_string()), " /// THE PAIR DOES NOT ISOLATE POSITION AS THE SOLE CAUSE, and an earlier revision of this\n".to_string()), " /// description claimed it did (native comment review 5120541804). The arms also differ in\n".to_string()), " /// their RETURN CONTRACT -- the control returns an `Int` read through a wrapper -- and the\n".to_string()), " /// measured E0308 lands AT the return, so the return contract is load-bearing for the refusal\n".to_string()), " /// rather than incidental. What the pair characterizes is two CONCRETE CONSTRUCTIONS, not a\n".to_string()), " /// single-variable experiment over position.\n".to_string()), " ///\n".to_string()), " /// THE RED IS A KNOWN HOLE, NOT A WALL WORKING, and it is named as one so nobody reads its red\n".to_string()), " /// as coverage. It is `gunbc.recurring_failure_mode` `accepted_source_emits_uncompilable_target`\n".to_string()), " /// at that row's own filed FIRST instance, which the row records was never committed to this\n".to_string()), " /// repository as a runnable file. It is committed here as one. When the wall climbs -- type\n".to_string()), " /// position resolution consulting the TYPE namespace alone -- the arm flips to SourceRefused\n".to_string()), " /// and is KEPT; what changes is this pair's expectation, not the fixture's existence.\n".to_string()), " ///\n".to_string()), " /// WHAT RUSTC ACTUALLY SAID, AND WHY IT IS RECORDED HERE. The emitted red module carries BOTH\n".to_string()), " /// an `Alpha` type and a `Marker::Alpha` variant: the field annotation binds the former, the\n".to_string()), " /// declared return wants the latter, and the refusal lands at the parent boundary as E0308,\n".to_string()), " /// `expected Marker, found Alpha`. E0573 was predicted from the ceiling row and did NOT\n".to_string()), " /// reproduce -- both arms declare their markers LOCALLY, so neither exercises the\n".to_string()), " /// imported-marker construction where those classifiers diverge, and the prediction was\n".to_string()), " /// mis-scoped from the start. The expectation is the route's adjudicated class. See\n".to_string()), " /// `run_phantom_marker_identity_discrimination` for the full diagnostic and for what is\n".to_string()), " /// deliberately not claimed from one construction.\n".to_string()), " ///\n".to_string()), " /// #[ignore] AND WHY, on the same terms as the three pairs beside it: this arm spawns cargo\n".to_string()), " /// and compiles two emitted crates, which is minutes rather than milliseconds. It is ENROLLED\n".to_string()), " /// AND OPT-IN -- `cargo test --release -p v1-compiler --lib\n".to_string()), " /// phantom_marker_identity_fixture_closure_discrimination -- --ignored`. An #[ignore] is a\n".to_string()), " /// cost decision and NOT a rung: nothing here may be cited as coverage that executes on the\n".to_string()), " /// merge path, and the phantom-marker ceiling carrier may not be flipped to\n".to_string()), " /// MeaningDiscriminatorEnrolled on the strength of it.\n".to_string()), " #[test]\n".to_string()), " #[ignore]\n".to_string()), " fn phantom_marker_identity_fixture_closure_discrimination() {\n".to_string()), " let probe_root = crate::cli_run::local_emit_compile_probe_root().unwrap();\n".to_string()), " let pair = crate::cli_run::run_phantom_marker_identity_discrimination(&probe_root);\n".to_string()), " for line in crate::cli_run::fixture_discrimination_report(&pair) {\n".to_string()), " eprintln!(\"phantom-marker-identity {}\", line);\n".to_string()), " }\n".to_string()), " assert!(\n".to_string()), " crate::cli_run::fixture_closure_reached_rustc(&pair.red),\n".to_string()), " \"the red arm never reached a rustc verdict, so nothing about the emitted bytes was measured: {}\",\n".to_string()), " crate::cli_run::fixture_closure_summary(&pair.red)\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " crate::cli_run::fixture_discrimination_passed(&pair),\n".to_string()), " \"the applied-marker fixture must COMPILE, and the non-applied-field-plus-parent-return fixture must reach rustc and be refused in its own emitted module with the attributed E0308 this pair claims; control={} red={} attribution={:?} diagnostic={:?}\",\n".to_string()), " crate::cli_run::fixture_closure_summary(&pair.green),\n".to_string()), " crate::cli_run::fixture_closure_summary(&pair.red),\n".to_string()), " crate::cli_run::fixture_closure_attributed_line(&pair.red),\n".to_string()), " crate::cli_run::fixture_closure_attributed_diagnostic(&pair.red)\n".to_string()), " );\n".to_string()), " }\n\n".to_string()) } @@ -398,5 +402,5 @@ pub fn ct_test_reference_orphan_row_test() -> String { } pub fn compiler_tests_source() -> String { - v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(ct_module_header(), ct_workspace_helpers()), ct_file_discovery_helpers()), ct_source_builders()), ct_tokenizer_tests()), ct_parse_tests()), ct_test_marker_item_kind_test()), ct_test_reference_wall_test()), ct_test_reference_import_all_test()), ct_test_reference_orphan_row_test()), ct_tco_tail_call_assigns_every_loop_slot_test()), ct_pipeline_test()), ct_entry_point_absent_refusal_test()), ct_import_lines_follow_resolved_binding_identity_test()), ct_pub_use_crate_lines_two_emission_byte_identity_test()), ct_overlapping_use_line_dedupe_permutation_test()), ct_fixture_closure_rustc_discrimination_test()), ct_evaluation_budget_consequence_falsifier_test()), ct_function_value_adapter_fixture_closure_discrimination_test()), ct_nested_refinement_cast_fixture_closure_discrimination_test()), ct_phantom_marker_identity_fixture_closure_discrimination_test()), ct_empty_map_turbofish_fixture_closure_discrimination_test()), ct_argv_word_list_splice_fixture_closure_discrimination_test()), ct_append_concat_form_fixture_closure_discrimination_test()), ct_shell_projection_arity_fixture_closure_discrimination_test()), ct_unlisted_import_use_witness_test()), ct_call_shape_wall_witness_test()), ct_call_deficit_red_witness_test()), ct_call_shape_duplicate_wall_witness_test()), ct_function_value_named_application_controls_witness_test()), ct_function_value_field_method_known_hole_probe_test()), ct_shell_service_output_projection_test()), ct_shell_service_unmodeled_output_key_refusal_test()), ct_shell_service_exit_error_arm_boxed_test()), ct_function_value_adapter_bound_alignment_control_test()), ct_rendered_leaf_occurrence_identity_test()), ct_rendered_leaf_occurrence_identity_pipeline_test()), ct_method_existence_wall_witness_test()), ct_declared_type_conformance_witness_test()), ct_direct_call_formal_authority_carrier_test()), ct_sole_constructor_test()), ct_constructor_call_admission_test()), ct_constructor_call_admission_same_module_sibling_test()), ct_constructor_call_admission_function_value_test()), ct_constructor_call_admission_zero_arity_test()), ct_constructor_call_admission_shadowing_test()), ct_constructor_call_admission_qualified_caller_test()), ct_sole_constructor_fieldless_witness_test()), ct_contracts_sidecar_witness_test()), ct_self_parse_all_test()), ct_self_resolve_test()), ct_self_compile_test()), ct_self_compile_cargo_check_test()), ct_type_size_test()), ct_coercion_tests()), ct_profile_helpers()), ct_profile_self_compile_test()), ct_profile_full_pipeline_test()), ct_profile_reconcile_test()), ct_module_footer()) + v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(ct_module_header(), ct_workspace_helpers()), ct_file_discovery_helpers()), ct_source_builders()), ct_tokenizer_tests()), ct_parse_tests()), ct_test_marker_item_kind_test()), ct_test_reference_wall_test()), ct_test_reference_import_all_test()), ct_test_reference_orphan_row_test()), ct_tco_tail_call_assigns_every_loop_slot_test()), ct_pipeline_test()), ct_entry_point_absent_refusal_test()), ct_import_lines_follow_resolved_binding_identity_test()), ct_pub_use_crate_lines_two_emission_byte_identity_test()), ct_overlapping_use_line_dedupe_permutation_test()), ct_fixture_closure_rustc_discrimination_test()), ct_evaluation_budget_consequence_falsifier_test()), ct_function_value_adapter_fixture_closure_discrimination_test()), ct_nested_refinement_cast_fixture_closure_discrimination_test()), ct_native_bool_variant_fixture_closure_discrimination_test()), ct_phantom_marker_identity_fixture_closure_discrimination_test()), ct_empty_map_turbofish_fixture_closure_discrimination_test()), ct_argv_word_list_splice_fixture_closure_discrimination_test()), ct_append_concat_form_fixture_closure_discrimination_test()), ct_shell_projection_arity_fixture_closure_discrimination_test()), ct_unlisted_import_use_witness_test()), ct_call_shape_wall_witness_test()), ct_call_deficit_red_witness_test()), ct_call_shape_duplicate_wall_witness_test()), ct_function_value_named_application_controls_witness_test()), ct_function_value_field_method_known_hole_probe_test()), ct_shell_service_output_projection_test()), ct_shell_service_unmodeled_output_key_refusal_test()), ct_shell_service_exit_error_arm_boxed_test()), ct_function_value_adapter_bound_alignment_control_test()), ct_rendered_leaf_occurrence_identity_test()), ct_rendered_leaf_occurrence_identity_pipeline_test()), ct_method_existence_wall_witness_test()), ct_declared_type_conformance_witness_test()), ct_direct_call_formal_authority_carrier_test()), ct_sole_constructor_test()), ct_constructor_call_admission_test()), ct_constructor_call_admission_same_module_sibling_test()), ct_constructor_call_admission_function_value_test()), ct_constructor_call_admission_zero_arity_test()), ct_constructor_call_admission_shadowing_test()), ct_constructor_call_admission_qualified_caller_test()), ct_sole_constructor_fieldless_witness_test()), ct_contracts_sidecar_witness_test()), ct_self_parse_all_test()), ct_self_resolve_test()), ct_self_compile_test()), ct_self_compile_cargo_check_test()), ct_type_size_test()), ct_coercion_tests()), ct_profile_helpers()), ct_profile_self_compile_test()), ct_profile_full_pipeline_test()), ct_profile_reconcile_test()), ct_module_footer()) } diff --git a/src/v1/stage0/src/v1_compiler_emit.rs b/src/v1/stage0/src/v1_compiler_emit.rs index 53709d150ce..2caf0ac7070 100644 --- a/src/v1/stage0/src/v1_compiler_emit.rs +++ b/src/v1/stage0/src/v1_compiler_emit.rs @@ -361,10 +361,7 @@ pub fn emit_simple_expr( binding_kind: bk, .. } => match bk.clone().as_deref().cloned() { Some(VarBindingKind::MatchBoundBinding) => false, - Some(VarBindingKind::VariantValueBinding { - parent_enum: _, - .. - }) => false, + Some(VarBindingKind::VariantValueBinding { .. }) => false, _ => true, }, _ => false, diff --git a/src/v1/stage0/src/v1_compiler_emit_rust.rs b/src/v1/stage0/src/v1_compiler_emit_rust.rs index 6111c1ee97c..dc6b4528df7 100644 --- a/src/v1/stage0/src/v1_compiler_emit_rust.rs +++ b/src/v1/stage0/src/v1_compiler_emit_rust.rs @@ -115,10 +115,18 @@ use crate::std_syntax::AlgebraFieldKind::*; use crate::std_syntax::BinOp::*; use crate::std_syntax::LiteralValue::*; pub use crate::std_syntax::{AlgebraFieldKind, BinOp, LiteralValue}; -pub use crate::std_target_representation::ExactBindingResolution; +pub use crate::std_target_representation::variant_value_realization_refusal_message; use crate::std_target_representation::ExactBindingResolution::{ ExactBindingAbsent, ExactBindingAmbiguous, ExactSourceIdentityUnavailable, ResolvedExactBinding, }; +use crate::std_target_representation::VariantParentIdentity::VariantParentUnrecovered; +use crate::std_target_representation::VariantValueRealization::{ + VariantParentIdentityUnavailable, VariantRealizesAsTargetValue, VariantRealizesStructurally, + VariantTargetValueAmbiguous, VariantTargetValueUnbound, +}; +pub use crate::std_target_representation::{ + ExactBindingResolution, VariantParentIdentity, VariantValueRealization, +}; pub use crate::std_types::SourceSpan; pub use crate::std_types::{container_template_algebra, is_container_type, is_kernel_type}; use crate::v1_compiler_artifact::RenderTarget::Rust; @@ -131,7 +139,8 @@ pub use crate::v1_compiler_closure_stub_v2_std_text_rust::closure_stub_v2_std_te pub use crate::v1_compiler_coercion::{ coerce_primitive_type, declaration_realization, declaration_realizes_natively_on_rust, is_copy, provenance_declares_structurally, realization_host_numeric_spelling, - realization_is_host_numeric, realized_checkpoint, rust_lookup_exact_binding, target_callable, + realization_is_host_numeric, realized_checkpoint, rust_lookup_exact_binding, + rust_variant_arm_is_bound_somewhere, rust_variant_value_realization, target_callable, type_realization_decision, type_reference_realization, }; pub use crate::v1_compiler_compiler_tests_rust::compiler_tests_source; @@ -20925,17 +20934,24 @@ pub fn emit_pattern( name: n, parent_enum, field_bindings: fbs, + parent_identity: identity, .. - } => emit_variant_pattern( - n.clone(), - parent_enum.clone(), - fbs.clone(), - path_prefix.clone(), - shared_types.clone(), - scrut_type.clone(), - source_indices.clone(), - emit_info.clone(), - ), + } => match rust_native_variant_spelling( + identity.clone(), + crate::v1_std_core::qualified_last_segment(n.clone()), + ) { + Some(native) => native.clone(), + std::option::Option::None => emit_variant_pattern( + n.clone(), + parent_enum.clone(), + fbs.clone(), + path_prefix.clone(), + shared_types.clone(), + scrut_type.clone(), + source_indices.clone(), + emit_info.clone(), + ), + }, MatchPattern::Wildcard => "_".to_string(), } } @@ -21738,18 +21754,25 @@ pub fn emit_pattern_rc_aware( name: n, parent_enum, field_bindings: fbs, + parent_identity: identity, .. - } => emit_variant_pattern_rc_aware( - n.clone(), - parent_enum.clone(), - fbs.clone(), - path_prefix.clone(), - rc_analysis.clone(), - shared_types.clone(), - scrut_type.clone(), - source_indices.clone(), - emit_info.clone(), - ), + } => match rust_native_variant_spelling( + identity.clone(), + crate::v1_std_core::qualified_last_segment(n.clone()), + ) { + Some(native) => native.clone(), + std::option::Option::None => emit_variant_pattern_rc_aware( + n.clone(), + parent_enum.clone(), + fbs.clone(), + path_prefix.clone(), + rc_analysis.clone(), + shared_types.clone(), + scrut_type.clone(), + source_indices.clone(), + emit_info.clone(), + ), + }, MatchPattern::Wildcard => "_".to_string(), } } @@ -22443,14 +22466,70 @@ pub fn is_simple_type_node( is_rust_value_type(n.clone(), source_indices.clone()) } -pub fn variant_parent_from_binding_kind( +pub fn rust_native_variant_spelling( + parent: Rc, + leaf_name: String, +) -> Option { + { + let r = crate::v1_compiler_coercion::rust_variant_value_realization( + parent.clone(), + leaf_name.clone(), + ); + match (*r.clone()).clone() { + VariantValueRealization::VariantRealizesAsTargetValue { + value_spelling: s, .. + } => Some(s.clone()), + VariantValueRealization::VariantRealizesStructurally => std::option::Option::None, + VariantValueRealization::VariantParentIdentityUnavailable { cause: _, .. } => { + if crate::v1_compiler_coercion::rust_variant_arm_is_bound_somewhere( + leaf_name.clone(), + ) { + match crate::std_target_representation::variant_value_realization_refusal_message(r.clone()) { + Some(m) => Some(emit_rust_compile_error_expr(m.clone())), + std::option::Option::None => std::option::Option::None, +} + } else { + std::option::Option::None + } + } + VariantValueRealization::VariantTargetValueUnbound { .. } => { + match crate::std_target_representation::variant_value_realization_refusal_message( + r.clone(), + ) { + Some(m) => Some(emit_rust_compile_error_expr(m.clone())), + std::option::Option::None => std::option::Option::None, + } + } + VariantValueRealization::VariantTargetValueAmbiguous { .. } => { + match crate::std_target_representation::variant_value_realization_refusal_message( + r.clone(), + ) { + Some(m) => Some(emit_rust_compile_error_expr(m.clone())), + std::option::Option::None => std::option::Option::None, + } + } + } + } +} + +pub fn rust_native_variant_spelling_of_binding( binding_kind: Option>, + leaf_name: String, ) -> Option { match binding_kind.clone().as_deref().cloned() { Some(VarBindingKind::VariantValueBinding { - parent_enum: parent_enum, + parent_identity: identity, .. - }) => Some(parent_enum.clone()), + }) => rust_native_variant_spelling(identity.clone(), leaf_name.clone()), + _ => std::option::Option::None, + } +} + +pub fn variant_parent_from_binding_kind( + binding_kind: Option>, +) -> Option { + match binding_kind.clone().as_deref().cloned() { + Some(VarBindingKind::VariantValueBinding { parent_enum, .. }) => Some(parent_enum.clone()), _ => std::option::Option::None, } } @@ -22707,112 +22786,128 @@ pub fn emit_var_ref( { crate::v1_compiler_emit::emit_keyword(leaf_name.clone(), RenderTarget::Rust) } else { + if (rust_native_variant_spelling_of_binding( + binding_kind.clone(), + leaf_name.clone(), + ) != std::option::Option::None) { - let moves_by_value = - v1_rt::set_contains(&emit_info.movable.clone(), resolved_name.clone()); - let sharing = - crate::v1_compiler_emit_core_support::language_spec(RenderTarget::Rust) - .sharing - .clone(); - let ref_str = match variant_parent.clone() { - Some(enum_name) => { - let body = if freemonoid_empty_from_variant_parent( - leaf_name.clone(), - enum_name.clone(), - ) { - emit_freemonoid_empty_variant_body() - } else { - if (is_optional_variant_name(leaf_name.clone()) - && is_optional_like_parent_name(enum_name.clone())) - { - rust_optional_variant_spelling(leaf_name.clone()) + match rust_native_variant_spelling_of_binding( + binding_kind.clone(), + leaf_name.clone(), + ) { + Some(s) => s.clone(), + std::option::Option::None => "".to_string(), + } + } else { + { + let moves_by_value = + v1_rt::set_contains(&emit_info.movable.clone(), resolved_name.clone()); + let sharing = + crate::v1_compiler_emit_core_support::language_spec(RenderTarget::Rust) + .sharing + .clone(); + let ref_str = match variant_parent.clone() { + Some(enum_name) => { + let body = if freemonoid_empty_from_variant_parent( + leaf_name.clone(), + enum_name.clone(), + ) { + emit_freemonoid_empty_variant_body() } else { - rust_variant_path(enum_name.clone(), leaf_name.clone()) + if (is_optional_variant_name(leaf_name.clone()) + && is_optional_like_parent_name(enum_name.clone())) + { + rust_optional_variant_spelling(leaf_name.clone()) + } else { + rust_variant_path(enum_name.clone(), leaf_name.clone()) + } + }; + if variant_ref_self_wraps( + leaf_name.clone(), + enum_name.clone(), + shared_types.clone(), + ) { + rust_shared_wrap_ctor(body.clone()) + } else { + body.clone() } - }; - if variant_ref_self_wraps( - leaf_name.clone(), - enum_name.clone(), - shared_types.clone(), - ) { - rust_shared_wrap_ctor(body.clone()) - } else { - body.clone() } - } - std::option::Option::None => match (*lookup_item_for_value_ref( - resolved_name.clone(), - module_name.clone(), - registry.clone(), - emit_info.clone(), - )) - .clone() - { - ItemLookup::ItemLeafAmbiguous { - leaf: ambiguous_leaf, - .. - } => ambiguous_leaf_refusal(ambiguous_leaf.clone()), - ItemLookup::ItemFound { info: info, .. } => { - let is_data = (info.kind.clone() == ItemKind::DataItem); - if is_data.clone() { - v1_rt::concat( - emit_value_ref_ident( - name.clone(), - module_name.clone(), - registry.clone(), - emit_info.clone(), - ), - "()".to_string(), - ) - } else { - { - let is_function_value = - match binding_kind.clone().as_deref().cloned() { - Some(VarBindingKind::FunctionValueBinding) => true, - _ => false, - }; - let ident = emit_value_ref_ident( - resolved_name.clone(), - module_name.clone(), - registry.clone(), - emit_info.clone(), - ); - let ident_str = if is_function_value.clone() { - ident.clone() - } else { - if moves_by_value.clone() { + std::option::Option::None => match (*lookup_item_for_value_ref( + resolved_name.clone(), + module_name.clone(), + registry.clone(), + emit_info.clone(), + )) + .clone() + { + ItemLookup::ItemLeafAmbiguous { + leaf: ambiguous_leaf, + .. + } => ambiguous_leaf_refusal(ambiguous_leaf.clone()), + ItemLookup::ItemFound { info: info, .. } => { + let is_data = (info.kind.clone() == ItemKind::DataItem); + if is_data.clone() { + v1_rt::concat( + emit_value_ref_ident( + name.clone(), + module_name.clone(), + registry.clone(), + emit_info.clone(), + ), + "()".to_string(), + ) + } else { + { + let is_function_value = + match binding_kind.clone().as_deref().cloned() { + Some(VarBindingKind::FunctionValueBinding) => { + true + } + _ => false, + }; + let ident = emit_value_ref_ident( + resolved_name.clone(), + module_name.clone(), + registry.clone(), + emit_info.clone(), + ); + let ident_str = if is_function_value.clone() { ident.clone() } else { - match resolved_type.clone() { + if moves_by_value.clone() { + ident.clone() + } else { + match resolved_type.clone() { Some(_) => crate::v1_compiler_emit_core_support::apply_type_template1(sharing.clone_value.clone(), ident.clone()), _ => ident.clone(), } - } - }; - ident_str.clone() + } + }; + ident_str.clone() + } } } - } - ItemLookup::ItemNotFound => { - let ident = emit_value_ref_ident( - resolved_name.clone(), - module_name.clone(), - registry.clone(), - emit_info.clone(), - ); - let ident_str = if moves_by_value.clone() { - ident.clone() - } else { - match resolved_type.clone() { + ItemLookup::ItemNotFound => { + let ident = emit_value_ref_ident( + resolved_name.clone(), + module_name.clone(), + registry.clone(), + emit_info.clone(), + ); + let ident_str = if moves_by_value.clone() { + ident.clone() + } else { + match resolved_type.clone() { Some(_) => crate::v1_compiler_emit_core_support::apply_type_template1(sharing.clone_value.clone(), ident.clone()), _ => ident.clone(), } - }; - ident_str.clone() - } - }, - }; - ref_str + }; + ident_str.clone() + } + }, + }; + ref_str + } } } } @@ -22854,80 +22949,91 @@ pub fn emit_typed_expr_base( { crate::v1_compiler_emit::emit_keyword(leaf_name.clone(), RenderTarget::Rust) } else { - match variant_parent.clone() { - Some(enum_name) => { - if freemonoid_empty_from_variant_parent( - leaf_name.clone(), - enum_name.clone(), - ) { - emit_freemonoid_empty_rc_value() - } else { - { - let qualified = - if (is_optional_variant_name(leaf_name.clone()) - && is_optional_like_parent_name(enum_name.clone())) + match rust_native_variant_spelling_of_binding( + binding_kind.clone(), + leaf_name.clone(), + ) { + Some(native) => native.clone(), + std::option::Option::None => match variant_parent.clone() { + Some(enum_name) => { + if freemonoid_empty_from_variant_parent( + leaf_name.clone(), + enum_name.clone(), + ) { + emit_freemonoid_empty_rc_value() + } else { + { + let qualified = + if (is_optional_variant_name(leaf_name.clone()) + && is_optional_like_parent_name( + enum_name.clone(), + )) + { + rust_optional_variant_spelling( + leaf_name.clone(), + ) + } else { + rust_variant_path( + enum_name.clone(), + leaf_name.clone(), + ) + }; + if v1_rt::set_contains(&shared_types, enum_name.clone()) { - rust_optional_variant_spelling(leaf_name.clone()) + rust_shared_wrap_ctor(qualified.clone()) } else { - rust_variant_path( - enum_name.clone(), - leaf_name.clone(), - ) - }; - if v1_rt::set_contains(&shared_types, enum_name.clone()) { - rust_shared_wrap_ctor(qualified.clone()) - } else { - qualified.clone() + qualified.clone() + } } } } - } - std::option::Option::None => { - let resolved_name = value_ref_normalize_self_module( - n.clone(), - scope.module_name.clone(), - ); - match (*lookup_item_for_value_ref( - resolved_name.clone(), - scope.module_name.clone(), - registry.clone(), - emit_info.clone(), - )) - .clone() - { - ItemLookup::ItemLeafAmbiguous { - leaf: ambiguous_leaf, - .. - } => ambiguous_leaf_refusal(ambiguous_leaf.clone()), - ItemLookup::ItemFound { info: info, .. } => { - let is_data = (info.kind.clone() == ItemKind::DataItem); - if is_data.clone() { - v1_rt::concat( + std::option::Option::None => { + let resolved_name = value_ref_normalize_self_module( + n.clone(), + scope.module_name.clone(), + ); + match (*lookup_item_for_value_ref( + resolved_name.clone(), + scope.module_name.clone(), + registry.clone(), + emit_info.clone(), + )) + .clone() + { + ItemLookup::ItemLeafAmbiguous { + leaf: ambiguous_leaf, + .. + } => ambiguous_leaf_refusal(ambiguous_leaf.clone()), + ItemLookup::ItemFound { info: info, .. } => { + let is_data = (info.kind.clone() == ItemKind::DataItem); + if is_data.clone() { + v1_rt::concat( + emit_value_ref_ident( + n.clone(), + scope.module_name.clone(), + registry.clone(), + emit_info.clone(), + ), + "()".to_string(), + ) + } else { emit_value_ref_ident( - n.clone(), + resolved_name.clone(), scope.module_name.clone(), registry.clone(), emit_info.clone(), - ), - "()".to_string(), - ) - } else { - emit_value_ref_ident( - resolved_name.clone(), - scope.module_name.clone(), - registry.clone(), - emit_info.clone(), - ) + ) + } } + ItemLookup::ItemNotFound => emit_value_ref_ident( + resolved_name.clone(), + scope.module_name.clone(), + registry.clone(), + emit_info.clone(), + ), } - ItemLookup::ItemNotFound => emit_value_ref_ident( - resolved_name.clone(), - scope.module_name.clone(), - registry.clone(), - emit_info.clone(), - ), } - } + }, } } } diff --git a/src/v1/stage0/src/v1_compiler_infer.rs b/src/v1/stage0/src/v1_compiler_infer.rs index d153b625c19..5fc4922be1b 100644 --- a/src/v1/stage0/src/v1_compiler_infer.rs +++ b/src/v1/stage0/src/v1_compiler_infer.rs @@ -18,9 +18,10 @@ pub use crate::gunbc_structural_realization_bindings::literal_homomorphism_rows; pub use crate::std_algebra::carrier_container_equality_rows; use crate::std_algebra::CollectionSizeEffect::ShrinkEffect; pub use crate::std_algebra::{CollectionSizeEffect, FreeMonoid}; -pub use crate::std_coercion::SubtractionRefinement; use crate::std_coercion::SubtractionRefinement::SubtractionRefinementAmbiguous; +use crate::std_coercion::TypeDeclarationProvenance::KernelMinted; pub use crate::std_coercion::{dag_can_cast, dag_cast_requires_proof, is_dag_cast_domain_type}; +pub use crate::std_coercion::{SubtractionRefinement, TypeDeclarationProvenance}; pub use crate::std_computation::ShrinkFactor; use crate::std_computation::ShrinkFactor::{ConstantShrink, ProportionalShrink, UnitShrink}; use crate::std_content_hash::ContentHash::*; @@ -48,6 +49,11 @@ pub use crate::std_induction::{InductiveField, RecursionShape, SubValueRelation} use crate::std_interface_summary::ExportKind::{ExportData, ExportFn, ExportService, ExportType}; pub use crate::std_interface_summary::{interface_summary_rollup, signature_contract}; pub use crate::std_interface_summary::{ExportEntry, ExportKind, InterfaceSummary}; +pub use crate::std_kernel_type_name::kernel_type_name; +pub use crate::std_kernel_type_name::KernelTypeNameAdmission; +use crate::std_kernel_type_name::KernelTypeNameAdmission::{ + KernelTypeNameAdmitted, NotAKernelTypeName, +}; use crate::std_literal_elaboration::LiteralElaborationOutcome::{ DirectLiteral, LiteralElaborationRefused, ViaHomomorphism, }; @@ -70,6 +76,13 @@ use crate::std_syntax::BinOp::{ use crate::std_syntax::LiteralValue::LitStr; use crate::std_syntax::LiteralValue::{LitBool, LitFloat, LitInt, LitNull}; pub use crate::std_syntax::{BinOp, LiteralValue}; +use crate::std_target_representation::VariantParentIdentity::{ + VariantParentIdentified, VariantParentUnrecovered, +}; +use crate::std_target_representation::VariantParentKey::{ + VariantParentDeclaration, VariantParentKernelType, +}; +pub use crate::std_target_representation::{VariantParentIdentity, VariantParentKey}; pub use crate::std_termination::PositiveDescentAmount; use crate::std_termination::PositiveDescentAmount::OneStep; pub use crate::std_termination::{ @@ -282,7 +295,7 @@ pub use crate::v1_std_core::{ admit_callers_entry_coords, admit_callers_entry_uninterpretable_spans, arg_name_at, arg_value, arm_body, arm_guard, arm_pattern, authored_name_at, binop_left, binop_right, bool_type, build_newline_index, call_semantics_target, callable_identity, cast_expr, cast_target, - container_expected_arity, decl_ref_coords_label, default_ident_span, + container_expected_arity, decl_ref_coords_label, declaration_provenance_of, default_ident_span, diagnostic_frontier_occurrence_key, diagnostic_to_span, empty_intern_table, error_type, expr_call_func_at, expr_has_non_tail_self_call, expr_has_self_call, expr_literal_int_optional, expr_literal_string_optional, expr_method_name_at, expr_var_name_at, field_access_base, @@ -1126,6 +1139,39 @@ pub fn variant_reference_inferred_node( } } +pub fn variant_parent_identity_of( + owner: Option>, + scope: Rc, +) -> Rc { + match owner.clone() { + std::option::Option::None => Rc::new(VariantParentIdentity::VariantParentUnrecovered { + cause: "no owning coproduct declaration was found for the variant".to_string(), +}), + Some(o) => match crate::v1_compiler_infer_env::type_reference_declaration(o.clone(), scope.type_env.clone().source_indices.clone(), scope.type_env.clone()) { + Some(od) => Rc::new(VariantParentIdentity::VariantParentIdentified { + key: Rc::new(VariantParentKey::VariantParentDeclaration { + declaration: od.declaration.clone(), +}), +}), + std::option::Option::None => match (*crate::v1_std_core::declaration_provenance_of(o.clone())).clone() { + TypeDeclarationProvenance::KernelMinted { minted_name: m, .. } => match (*crate::std_kernel_type_name::kernel_type_name(m.clone())).clone() { + KernelTypeNameAdmission::KernelTypeNameAdmitted { kernel_name: k, .. } => Rc::new(VariantParentIdentity::VariantParentIdentified { + key: Rc::new(VariantParentKey::VariantParentKernelType { + kernel_name: k.clone(), +}), +}), + KernelTypeNameAdmission::NotAKernelTypeName { name: _, .. } => Rc::new(VariantParentIdentity::VariantParentUnrecovered { + cause: "the owning coproduct is a kernel mint whose name is not a kernel type".to_string(), +}), +}, + _ => Rc::new(VariantParentIdentity::VariantParentUnrecovered { + cause: "the owning coproduct is neither an identified corpus declaration nor a kernel type (alias or unresolved)".to_string(), +}), +}, +}, +} +} + pub fn variant_owner_node(scope: Rc, name: String) -> Option> { if v1_rt::contains(name.clone(), ".".to_string()) { match crate::v1_compiler_infer_env::symbol_index_lookup( @@ -1349,6 +1395,10 @@ pub fn infer_var_binding_kind(scope: Rc, name: String) -> Rc Rc::new(VarBindingKind::VariantValueBinding { parent_enum: parent_enum.clone(), + parent_identity: variant_parent_identity_of( + variant_owner_node(scope.clone(), name.clone()), + scope.clone(), + ), }), std::option::Option::None => match v1_rt::map_get(&scope.locals.clone(), name.clone()) { Some(binding) => { @@ -9419,6 +9469,41 @@ pub fn annotate_pattern_parent_enums( PatternSubject::PatternLookupBlocked => std::option::Option::None, }; let annotated_variant_name = variant_name.clone(); + let wrapper_parent = match inferred_parent.clone() { + Some(p) => { + ((p.clone() == "Optional".to_string()) + || (p.clone() == "Witness".to_string())) + } + std::option::Option::None => false, + }; + let parent_identity = if wrapper_parent.clone() { + Rc::new(VariantParentIdentity::VariantParentUnrecovered { + cause: "the arm belongs to the optional or witness wrapper, not to the scrutinee's declared coproduct".to_string(), +}) + } else { + match (*resolved_scrut.clone()).clone() { + PatternSubject::PatternResolved { node: r, .. } => { + let scrutinee_is_coproduct = (r.connective.clone() == Connective::Disj); + if scrutinee_is_coproduct.clone() { + variant_parent_identity_of(Some(r.clone()), scope.clone()) + } else { + Rc::new(VariantParentIdentity::VariantParentUnrecovered { + cause: "the scrutinee's resolved type is not a coproduct declaration".to_string(), +}) + } + } + PatternSubject::PatternDynamic { span: _, .. } => { + Rc::new(VariantParentIdentity::VariantParentUnrecovered { + cause: "the scrutinee's type is dynamic".to_string(), + }) + } + PatternSubject::PatternLookupBlocked => { + Rc::new(VariantParentIdentity::VariantParentUnrecovered { + cause: "the scrutinee's type lookup was blocked".to_string(), + }) + } + } + }; let variant_lookup = crate::v1_compiler_infer_patterns::lookup_variant_in_type( resolved_scrut.clone(), variant_name.clone(), @@ -9470,11 +9555,13 @@ pub fn annotate_pattern_parent_enums( name: annotated_variant_name.clone(), parent_enum: Some(parent_name.clone()), field_bindings: annotated_bindings.clone(), + parent_identity: parent_identity.clone(), }), std::option::Option::None => Rc::new(MatchPattern::VariantPattern { name: variant_name.clone(), parent_enum: std::option::Option::None, field_bindings: annotated_bindings.clone(), + parent_identity: parent_identity.clone(), }), } } @@ -10754,6 +10841,7 @@ pub fn unfold_peano_image( succ: String, prev_field: String, parent: String, + parent_identity: Rc, destination_type: Rc, span: Rc, ) -> Rc { @@ -10764,6 +10852,7 @@ pub fn unfold_peano_image( Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new(VarBindingKind::VariantValueBinding { parent_enum: parent.clone(), + parent_identity: parent_identity.clone(), })), }), Rc::new(vec![]), @@ -10778,6 +10867,7 @@ pub fn unfold_peano_image( succ.clone(), prev_field.clone(), parent.clone(), + parent_identity.clone(), destination_type.clone(), span.clone(), ); @@ -10848,7 +10938,11 @@ pub fn unfold_literal_image( _ => crate::v1_std_core::make_expr_error_node(Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::InternalExprError, "literal elaboration: a Unicode-scalar-sequence unfolding row was selected for a non-string literal (gunbc.structural_realization_bindings keys the row on KernelStringLiteral, so this row is malformed)".to_string(), span.clone()), }, LiteralUnfolding::PeanoUnfold { zero, succ, prev_field, .. } => match (*lit.clone()).clone() { - LiteralValue::LitInt { value: n, .. } => unfold_peano_image(n.clone(), zero.decl_name.clone(), succ.decl_name.clone(), prev_field.clone(), elaboration.destination.clone().decl_name.clone(), destination_type.clone(), span.clone()), + LiteralValue::LitInt { value: n, .. } => unfold_peano_image(n.clone(), zero.decl_name.clone(), succ.decl_name.clone(), prev_field.clone(), elaboration.destination.clone().decl_name.clone(), Rc::new(VariantParentIdentity::VariantParentIdentified { + key: Rc::new(VariantParentKey::VariantParentDeclaration { + declaration: elaboration.destination.clone(), +}), +}), destination_type.clone(), span.clone()), _ => crate::v1_std_core::make_expr_error_node(Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::InternalExprError, "literal elaboration: a Peano unfolding row was selected for a non-integer literal (gunbc.structural_realization_bindings keys the row on KernelIntLiteral, so this row is malformed)".to_string(), span.clone()), }, LiteralUnfolding::BooleanUnfold { true_variant: t, false_variant: f, .. } => match (*lit.clone()).clone() { @@ -10859,6 +10953,11 @@ pub fn unfold_literal_image( }, Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new(VarBindingKind::VariantValueBinding { parent_enum: elaboration.destination.clone().decl_name.clone(), + parent_identity: Rc::new(VariantParentIdentity::VariantParentIdentified { + key: Rc::new(VariantParentKey::VariantParentDeclaration { + declaration: elaboration.destination.clone(), +}), +}), })), }), Rc::new(vec![]), destination_type.clone(), span.clone()), _ => crate::v1_std_core::make_expr_error_node(Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::InternalExprError, "literal elaboration: a Boolean unfolding row was selected for a non-boolean literal (gunbc.structural_realization_bindings keys the row on KernelBoolLiteral, so this row is malformed)".to_string(), span.clone()), @@ -11071,6 +11170,7 @@ match scope_parent.clone() { typed: crate::v1_std_core::make_named_expr_node(texpr.occurrence_identity.clone(), name.clone(), Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new(VarBindingKind::VariantValueBinding { parent_enum: scope_enum.clone(), + parent_identity: variant_parent_identity_of(variant_owner_node(scope.clone(), name.clone()), scope.clone()), })), }), Rc::new(vec![]), Some(Rc::new(InferredNode::Resolved { node: variant_reference_inferred_node(expected.clone(), name.clone(), scope_enum.clone(), scope.clone(), binding.resolved.clone()), @@ -11126,6 +11226,7 @@ match scope_parent.clone() { typed: crate::v1_std_core::make_named_expr_node(texpr.occurrence_identity.clone(), name.clone(), Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new(VarBindingKind::VariantValueBinding { parent_enum: scope_enum.clone(), + parent_identity: variant_parent_identity_of(variant_owner_node(scope.clone(), name.clone()), scope.clone()), })), }), Rc::new(vec![]), Some(Rc::new(InferredNode::Resolved { node: variant_reference_inferred_node(expected.clone(), name.clone(), scope_enum.clone(), scope.clone(), gbinding.resolved.clone()), @@ -11137,6 +11238,7 @@ match scope_parent.clone() { typed: crate::v1_std_core::make_named_expr_node(texpr.occurrence_identity.clone(), name.clone(), Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new(VarBindingKind::VariantValueBinding { parent_enum: crate::v1_std_core::authored_name_at(scope.type_env.clone().source_indices.clone(), exp_enum.clone()), + parent_identity: variant_parent_identity_of(Some(exp_enum.clone()), scope.clone()), })), }), Rc::new(vec![]), Some(Rc::new(InferredNode::Resolved { node: exp_enum.clone(), @@ -11178,6 +11280,7 @@ match expected_variant_enum.clone() { typed: crate::v1_std_core::make_named_expr_node(texpr.occurrence_identity.clone(), name.clone(), Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new(VarBindingKind::VariantValueBinding { parent_enum: crate::v1_std_core::authored_name_at(scope.type_env.clone().source_indices.clone(), exp_enum.clone()), + parent_identity: variant_parent_identity_of(Some(exp_enum.clone()), scope.clone()), })), }), Rc::new(vec![]), Some(Rc::new(InferredNode::Resolved { node: exp_enum.clone(), diff --git a/src/v1/stage0/src/v1_compiler_parse.rs b/src/v1/stage0/src/v1_compiler_parse.rs index 0bd671a7a8e..8fd8dcc9a62 100644 --- a/src/v1/stage0/src/v1_compiler_parse.rs +++ b/src/v1/stage0/src/v1_compiler_parse.rs @@ -50,6 +50,8 @@ pub use crate::std_syntax::{ BinOp, BodyKind, ItemForm, ItemFormKind, LiteralValue, OperatorSpec, ParseEnvironment, SyntaxSpec, }; +pub use crate::std_target_representation::VariantParentIdentity; +use crate::std_target_representation::VariantParentIdentity::VariantParentBeforeInference; pub use crate::std_types::{NonEmptyStr, SourceSpan}; use crate::v1_rt; use crate::v1_rt::{VecCompat, VecJoin}; @@ -3041,6 +3043,7 @@ pub fn stamp_parsed_pattern( name, parent_enum, field_bindings, + parent_identity, .. }) => { let stamped = stamp_parsed_node_list( @@ -3056,6 +3059,7 @@ pub fn stamp_parsed_pattern( name: name.clone(), parent_enum: parent_enum.clone(), field_bindings: stamped.nodes.clone(), + parent_identity: parent_identity.clone(), })), ctx: stamped.ctx.clone(), err: stamped.err.clone(), @@ -16078,6 +16082,9 @@ pub fn parse_variant_pattern( name: name.clone(), parent_enum: std::option::Option::None, field_bindings: r.field_bindings.clone(), + parent_identity: Rc::new( + VariantParentIdentity::VariantParentBeforeInference, + ), }), tokens: r2.tokens.clone(), ctx: r.ctx.clone(), @@ -16118,6 +16125,9 @@ pub fn parse_variant_pattern( name: name.clone(), parent_enum: std::option::Option::None, field_bindings: Rc::new(vec![fb.clone()]), + parent_identity: Rc::new( + VariantParentIdentity::VariantParentBeforeInference, + ), }), tokens: r2.tokens.clone(), ctx: minted.ctx.clone(), @@ -16130,6 +16140,9 @@ pub fn parse_variant_pattern( name: name.clone(), parent_enum: std::option::Option::None, field_bindings: Rc::new(vec![]), + parent_identity: Rc::new( + VariantParentIdentity::VariantParentBeforeInference, + ), }), tokens: tokens.clone(), ctx: ctx.clone(), diff --git a/src/v1/stage0/src/v1_std_core.rs b/src/v1/stage0/src/v1_std_core.rs index 972f58e607f..a2cc1c746cc 100644 --- a/src/v1/stage0/src/v1_std_core.rs +++ b/src/v1/stage0/src/v1_std_core.rs @@ -80,6 +80,8 @@ use crate::std_syntax::BinOp::{ }; use crate::std_syntax::LiteralValue::{LitBool, LitFloat, LitInt, LitNull, LitStr, LitSymbol}; pub use crate::std_syntax::{AlgebraFieldKind, BinOp, LiteralValue}; +pub use crate::std_target_representation::VariantParentIdentity; +use crate::std_target_representation::VariantParentIdentity::*; pub use crate::std_types::{ container_expected_arity, container_type_arity, is_container_type, is_kernel_type, kernel_type_set, @@ -265,7 +267,10 @@ pub fn has_inferred(n: Rc) -> bool { pub enum VarBindingKind { LocalValueBinding, FunctionValueBinding, - VariantValueBinding { parent_enum: String }, + VariantValueBinding { + parent_enum: String, + parent_identity: Rc, + }, MatchBoundBinding, ServiceValueBinding, } @@ -281,6 +286,18 @@ impl VarBindingKind { VarBindingKind::ServiceValueBinding => panic!("no parent_enum on unit variant"), } } + pub fn parent_identity(&self) -> Rc { + match self { + VarBindingKind::LocalValueBinding => panic!("no parent_identity on unit variant"), + VarBindingKind::FunctionValueBinding => panic!("no parent_identity on unit variant"), + VarBindingKind::VariantValueBinding { + parent_identity: __val, + .. + } => __val.clone(), + VarBindingKind::MatchBoundBinding => panic!("no parent_identity on unit variant"), + VarBindingKind::ServiceValueBinding => panic!("no parent_identity on unit variant"), + } + } } #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] @@ -475,6 +492,7 @@ pub enum MatchPattern { name: String, parent_enum: Option, field_bindings: Rc>>, + parent_identity: Rc, }, Wildcard, } diff --git a/src/v1/stage0_std_core/src/lib.rs b/src/v1/stage0_std_core/src/lib.rs index 39aaed21e0c..b44191b8790 100644 --- a/src/v1/stage0_std_core/src/lib.rs +++ b/src/v1/stage0_std_core/src/lib.rs @@ -129,6 +129,9 @@ pub mod std_occurrence_identity; #[path = "../../stage0/src/std_source_annotation.rs"] pub mod std_source_annotation; #[rustfmt::skip] +#[path = "../../stage0/src/std_kernel_type_name.rs"] +pub mod std_kernel_type_name; +#[rustfmt::skip] #[path = "../../stage0/src/std_target_representation.rs"] pub mod std_target_representation; #[rustfmt::skip] diff --git a/src/v2/workflow/rust_crate_partition.dag b/src/v2/workflow/rust_crate_partition.dag index 689130b78bd..e3e447b91cb 100644 --- a/src/v2/workflow/rust_crate_partition.dag +++ b/src/v2/workflow/rust_crate_partition.dag @@ -340,6 +340,7 @@ fn stage0_std_core_modules() -> List { "extdeps_units_iso_80000_3", "std_occurrence_identity", "std_source_annotation", + "std_kernel_type_name", "std_target_representation", "std_literal_elaboration", "std_operator_realization", From c63819ee93c293fe7bfb7ba71677e59f3abbee55 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Mon, 28 Sep 2026 19:03:47 +0000 Subject: [PATCH 13/21] stage0 regen after restack onto #12547 head Co-Authored-By: Claude Opus 5.5 (1M context) --- .../src/gunbc_rust_source_type_bindings.rs | 76 ++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/src/v1/stage0/src/gunbc_rust_source_type_bindings.rs b/src/v1/stage0/src/gunbc_rust_source_type_bindings.rs index cf75eef61de..eb5686bbff1 100644 --- a/src/v1/stage0/src/gunbc_rust_source_type_bindings.rs +++ b/src/v1/stage0/src/gunbc_rust_source_type_bindings.rs @@ -5,13 +5,25 @@ pub use crate::extdeps_languages_rust_representation::RustRepresentation; use crate::extdeps_languages_rust_representation::RustRepresentation::{ RustBool, RustI64, RustSerdeJsonValue, RustStdString, RustUnit, RustVecU8, }; +pub use crate::extdeps_languages_rust_representation::{ + rust_bool_false_value, rust_bool_true_value, +}; pub use crate::std_decl_ref::decl_ref; pub use crate::std_decl_ref::DeclarationRef; +pub use crate::std_kernel_type_name::kernel_type_name; +pub use crate::std_kernel_type_name::KernelTypeNameAdmission; +use crate::std_kernel_type_name::KernelTypeNameAdmission::{ + KernelTypeNameAdmitted, NotAKernelTypeName, +}; use crate::std_target_representation::CheckpointRowDisposition::{ MigratedToExactBinding, ProvenUniqueKernelBinding, StillBareNameDebt, }; +use crate::std_target_representation::VariantParentKey::{ + VariantParentDeclaration, VariantParentKernelType, +}; pub use crate::std_target_representation::{ - CheckpointRowDisposition, CheckpointRowMigration, SourceTypeTargetBinding, + CheckpointRowDisposition, CheckpointRowMigration, RepresentationValue, SourceTypeTargetBinding, + SourceVariantTargetValue, VariantParentKey, }; use crate::std_types::Bool::*; pub use crate::std_types::{Bool, List, NonEmptyStr}; @@ -43,6 +55,68 @@ pub fn rust_source_type_binding_rows() -> Rc>>>| c.clone()) } +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct BoolArmValue { + pub variant: NonEmptyStr, + pub value: Rc>, +} + +pub fn rust_bool_arm_values() -> Rc>> { + thread_local! { + static CACHED: Rc>> = { + Rc::new(vec![Rc::new(BoolArmValue { + variant: "True".to_string(), + value: rust_bool_true_value(), + }), Rc::new(BoolArmValue { + variant: "False".to_string(), + value: rust_bool_false_value(), + })]) + }; + } + CACHED.with(|c: &Rc>>| c.clone()) +} + +pub fn rust_bool_variant_rows( + parent: Rc, +) -> Rc>>> { + Rc::new({ + let mut __result = Vec::new(); + for a in rust_bool_arm_values().iter().cloned() { + __result.push(Rc::new(SourceVariantTargetValue { + parent: parent.clone(), + variant: a.variant.clone(), + value: a.value.clone(), + _phantom: std::marker::PhantomData, + })); + } + __result + }) +} + +pub fn rust_bool_kernel_variant_rows() -> Rc>>> +{ + match (*crate::std_kernel_type_name::kernel_type_name("Bool".to_string())).clone() { + KernelTypeNameAdmission::KernelTypeNameAdmitted { kernel_name: k, .. } => { + rust_bool_variant_rows(Rc::new(VariantParentKey::VariantParentKernelType { + kernel_name: k.clone(), + })) + } + KernelTypeNameAdmission::NotAKernelTypeName { name: _, .. } => Rc::new(vec![]), + } +} + +pub fn rust_source_variant_value_rows() -> Rc>>> +{ + thread_local! { + static CACHED: Rc>>> = { + v1_rt::concat(rust_bool_variant_rows(Rc::new(VariantParentKey::VariantParentDeclaration { + declaration: crate::std_decl_ref::decl_ref("std.types".to_string(), "Bool".to_string()), + })), rust_bool_kernel_variant_rows()) + }; + } + CACHED.with(|c: &Rc>>>| c.clone()) +} + pub fn rust_bound_declaration_refs() -> Rc>> { Rc::new({ let mut __result = Vec::new(); From 331e5f9781fe9b88d75771c6b78a7703fd74f1ce Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Mon, 28 Sep 2026 20:53:43 +0000 Subject: [PATCH 14/21] Wrapper-ness decided in the same branch as the parent label (review 72323); BeforeInference always refuses at emission Co-Authored-By: Claude Opus 5.5 (1M context) --- ...ative_variant_realization_witness_test.dag | 1 + src/v1/04_infer.dag | 44 +++++----- src/v1/05_emit_rust.dag | 11 ++- src/v1/stage0/src/v1_compiler_emit_rust.rs | 14 ++- src/v1/stage0/src/v1_compiler_infer.rs | 88 ++++++++++--------- 5 files changed, 91 insertions(+), 67 deletions(-) diff --git a/dag/test/claim/native_variant_realization_witness_test.dag b/dag/test/claim/native_variant_realization_witness_test.dag index 29f4b91f580..d06bd40a1f6 100644 --- a/dag/test/claim/native_variant_realization_witness_test.dag +++ b/dag/test/claim/native_variant_realization_witness_test.dag @@ -34,3 +34,4 @@ test fn local_coproduct_with_true_false_arms_keeps_its_enum() -> Bool { ["true => ", "false => "] ) } + diff --git a/src/v1/04_infer.dag b/src/v1/04_infer.dag index 945da6a0bc2..1833319d097 100644 --- a/src/v1/04_infer.dag +++ b/src/v1/04_infer.dag @@ -6392,47 +6392,43 @@ fn resolve_pattern_subject(scope: InferScope, scrutinee_subject: PatternSubject) } } +// WHICH PARENT A VARIANT PATTERN WAS READ AGAINST, decided ONCE: the label the emitter spells +// (parent_enum) and the identity the realization rows are keyed on come out of the same branch, so +// the wrapper arms (optional, witness) carry their own unrecovered cause and nothing downstream +// re-derives wrapper-ness by comparing the label as a string (review 72323). +type PatternParentReading { + parent_enum: String? + identity: VariantParentIdentity +} + fn annotate_pattern_parent_enums(pattern: MatchPattern, scrutinee_subject: PatternSubject, scope: InferScope) -> MatchPattern { match pattern { VariantPattern { name: variant_name, parent_enum: _, field_bindings: bindings, parent_identity: _ } => let resolved_scrut = resolve_pattern_subject(scope: scope, scrutinee_subject: scrutinee_subject) - let inferred_parent = match resolved_scrut { + let parent_reading = match resolved_scrut { PatternResolved { node: resolved_scrut_node } => let scrutinee_name = authored_name_at(source_indices: scope.type_env.source_indices, node: resolved_scrut_node) let optional_cardinality_subject = resolved_scrut_node.return_cardinality == CardOptional && scrutinee_name != "Optional" let optional_coproduct_subject = scrutinee_name == "Optional" && (variant_name == "Present" || variant_name == "Absent") let witness_container_subject = is_witness_type_name(name: scrutinee_name) && (variant_name == "Holds" || variant_name == "Violates") if (optional_cardinality_subject || optional_coproduct_subject) && (variant_name == "Present" || variant_name == "Absent") { - Present { value: "Optional" } + PatternParentReading { parent_enum: Present { value: "Optional" }, identity: VariantParentUnrecovered { cause: "the arm belongs to the optional wrapper, not to the scrutinee's declared coproduct" as NonEmptyStr } } } else if witness_container_subject { - Present { value: "Witness" } + PatternParentReading { parent_enum: Present { value: "Witness" }, identity: VariantParentUnrecovered { cause: "the arm belongs to the witness wrapper, not to the scrutinee's declared coproduct" as NonEmptyStr } } } else { let is_coproduct = resolved_scrut_node.connective == Disj if is_coproduct { - Present { value: scrutinee_name } - } else { none } + PatternParentReading { parent_enum: Present { value: scrutinee_name }, identity: variant_parent_identity_of(owner: Present { value: resolved_scrut_node }, scope: scope) } + } else { + PatternParentReading { parent_enum: none, identity: VariantParentUnrecovered { cause: "the scrutinee's resolved type is not a coproduct declaration" as NonEmptyStr } } + } } - PatternDynamic { span: _ } => none - PatternLookupBlocked => none + PatternDynamic { span: _ } => PatternParentReading { parent_enum: none, identity: VariantParentUnrecovered { cause: "the scrutinee's type is dynamic" as NonEmptyStr } } + PatternLookupBlocked => PatternParentReading { parent_enum: none, identity: VariantParentUnrecovered { cause: "the scrutinee's type lookup was blocked" as NonEmptyStr } } } + let inferred_parent = parent_reading.parent_enum + let parent_identity = parent_reading.identity let annotated_variant_name = variant_name - let wrapper_parent = match inferred_parent { - Present { value: p } => p == "Optional" || p == "Witness" - Absent => false - } - let parent_identity = if wrapper_parent { - VariantParentUnrecovered { cause: "the arm belongs to the optional or witness wrapper, not to the scrutinee's declared coproduct" as NonEmptyStr } - } else { match resolved_scrut { - PatternResolved { node: r } => - let scrutinee_is_coproduct = r.connective == Disj - if scrutinee_is_coproduct { - variant_parent_identity_of(owner: Present { value: r }, scope: scope) - } else { - VariantParentUnrecovered { cause: "the scrutinee's resolved type is not a coproduct declaration" as NonEmptyStr } - } - PatternDynamic { span: _ } => VariantParentUnrecovered { cause: "the scrutinee's type is dynamic" as NonEmptyStr } - PatternLookupBlocked => VariantParentUnrecovered { cause: "the scrutinee's type lookup was blocked" as NonEmptyStr } - } } let variant_lookup = lookup_variant_in_type(scrut: resolved_scrut, variant_name: variant_name, module_name: scope.module_name, env: scope.type_env, field_binding_count: bindings |> count) let variant_subject = lookup_result_subject(result: variant_lookup) let annotated_bindings = bindings |> map(binding => diff --git a/src/v1/05_emit_rust.dag b/src/v1/05_emit_rust.dag index 96d39cb9867..87894f31428 100644 --- a/src/v1/05_emit_rust.dag +++ b/src/v1/05_emit_rust.dag @@ -3,7 +3,7 @@ module v1.compiler.emit_rust import std.occurrence_identity { OccurrenceSynthetic } import std.decl_ref { decl_ref, DeclarationRef, WholeDeclaration } import std.target_representation { ResolvedExactBinding, ExactBindingAbsent, ExactBindingAmbiguous, ExactSourceIdentityUnavailable, - VariantParentIdentity, VariantParentUnrecovered, VariantRealizesAsTargetValue, VariantRealizesStructurally, VariantTargetValueUnbound, + VariantParentIdentity, VariantParentUnrecovered, VariantParentBeforeInference, VariantRealizesAsTargetValue, VariantRealizesStructurally, VariantTargetValueUnbound, VariantTargetValueAmbiguous, VariantParentIdentityUnavailable, variant_value_realization_refusal_message } import extdeps.languages.rust.representation { rust_exact_type_checkpoint } import std.repair_input_origin { @@ -10519,6 +10519,15 @@ fn is_simple_type_node(n: Node, source_indices: Map) -> Bo // carried; see rust_variant_arm_is_bound_somewhere for why an unidentified occurrence refuses only // when its arm is one a row binds. fn rust_native_variant_spelling(parent: VariantParentIdentity, leaf_name: String) -> String? { + match parent { + VariantParentBeforeInference => + Present { value: emit_rust_compile_error_expr(message: concat("variant realization: `", leaf_name, "` reached emission without inference having read which coproduct it belongs to (VariantParentBeforeInference); an unread occurrence is refused rather than rendered as either the native value or its enum path")) } + _ => rust_native_variant_spelling_of_read(parent: parent, leaf_name: leaf_name) + } +} + +// An occurrence inference has read: Identified, or Unrecovered with its cause. +fn rust_native_variant_spelling_of_read(parent: VariantParentIdentity, leaf_name: String) -> String? { let r = rust_variant_value_realization(parent: parent, variant: leaf_name) match r { VariantRealizesAsTargetValue { value_spelling: s } => Present { value: s as String } diff --git a/src/v1/stage0/src/v1_compiler_emit_rust.rs b/src/v1/stage0/src/v1_compiler_emit_rust.rs index dc6b4528df7..16344600191 100644 --- a/src/v1/stage0/src/v1_compiler_emit_rust.rs +++ b/src/v1/stage0/src/v1_compiler_emit_rust.rs @@ -119,7 +119,9 @@ pub use crate::std_target_representation::variant_value_realization_refusal_mess use crate::std_target_representation::ExactBindingResolution::{ ExactBindingAbsent, ExactBindingAmbiguous, ExactSourceIdentityUnavailable, ResolvedExactBinding, }; -use crate::std_target_representation::VariantParentIdentity::VariantParentUnrecovered; +use crate::std_target_representation::VariantParentIdentity::{ + VariantParentBeforeInference, VariantParentUnrecovered, +}; use crate::std_target_representation::VariantValueRealization::{ VariantParentIdentityUnavailable, VariantRealizesAsTargetValue, VariantRealizesStructurally, VariantTargetValueAmbiguous, VariantTargetValueUnbound, @@ -22469,6 +22471,16 @@ pub fn is_simple_type_node( pub fn rust_native_variant_spelling( parent: Rc, leaf_name: String, +) -> Option { + match (*parent.clone()).clone() { + VariantParentIdentity::VariantParentBeforeInference => Some(emit_rust_compile_error_expr(v1_rt::concat(v1_rt::concat("variant realization: `".to_string(), leaf_name.clone()), "` reached emission without inference having read which coproduct it belongs to (VariantParentBeforeInference); an unread occurrence is refused rather than rendered as either the native value or its enum path".to_string()))), + _ => rust_native_variant_spelling_of_read(parent.clone(), leaf_name.clone()), +} +} + +pub fn rust_native_variant_spelling_of_read( + parent: Rc, + leaf_name: String, ) -> Option { { let r = crate::v1_compiler_coercion::rust_variant_value_realization( diff --git a/src/v1/stage0/src/v1_compiler_infer.rs b/src/v1/stage0/src/v1_compiler_infer.rs index 5fc4922be1b..b7d580e7ea2 100644 --- a/src/v1/stage0/src/v1_compiler_infer.rs +++ b/src/v1/stage0/src/v1_compiler_infer.rs @@ -9408,6 +9408,12 @@ pub fn resolve_pattern_subject( } } +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct PatternParentReading { + pub parent_enum: Option, + pub identity: Rc, +} + pub fn annotate_pattern_parent_enums( pattern: Rc, scrutinee_subject: Rc, @@ -9422,7 +9428,7 @@ pub fn annotate_pattern_parent_enums( } => { let resolved_scrut = resolve_pattern_subject(scope.clone(), scrutinee_subject.clone()); - let inferred_parent = match (*resolved_scrut.clone()).clone() { + let parent_reading = match (*resolved_scrut.clone()).clone() { PatternSubject::PatternResolved { node: resolved_scrut_node, .. @@ -9448,62 +9454,62 @@ pub fn annotate_pattern_parent_enums( && ((variant_name.clone() == "Present".to_string()) || (variant_name.clone() == "Absent".to_string()))) { - Some("Optional".to_string()) + Rc::new(PatternParentReading { + parent_enum: Some("Optional".to_string()), + identity: Rc::new(VariantParentIdentity::VariantParentUnrecovered { + cause: "the arm belongs to the optional wrapper, not to the scrutinee's declared coproduct".to_string(), +}), +}) } else { if witness_container_subject.clone() { - Some("Witness".to_string()) + Rc::new(PatternParentReading { + parent_enum: Some("Witness".to_string()), + identity: Rc::new(VariantParentIdentity::VariantParentUnrecovered { + cause: "the arm belongs to the witness wrapper, not to the scrutinee's declared coproduct".to_string(), +}), +}) } else { { let is_coproduct = (resolved_scrut_node.connective.clone() == Connective::Disj); if is_coproduct.clone() { - Some(scrutinee_name.clone()) + Rc::new(PatternParentReading { + parent_enum: Some(scrutinee_name.clone()), + identity: variant_parent_identity_of( + Some(resolved_scrut_node.clone()), + scope.clone(), + ), + }) } else { - std::option::Option::None + Rc::new(PatternParentReading { + parent_enum: std::option::Option::None, + identity: Rc::new(VariantParentIdentity::VariantParentUnrecovered { + cause: "the scrutinee's resolved type is not a coproduct declaration".to_string(), +}), +}) } } } } } - PatternSubject::PatternDynamic { span: _, .. } => std::option::Option::None, - PatternSubject::PatternLookupBlocked => std::option::Option::None, - }; - let annotated_variant_name = variant_name.clone(); - let wrapper_parent = match inferred_parent.clone() { - Some(p) => { - ((p.clone() == "Optional".to_string()) - || (p.clone() == "Witness".to_string())) - } - std::option::Option::None => false, - }; - let parent_identity = if wrapper_parent.clone() { - Rc::new(VariantParentIdentity::VariantParentUnrecovered { - cause: "the arm belongs to the optional or witness wrapper, not to the scrutinee's declared coproduct".to_string(), -}) - } else { - match (*resolved_scrut.clone()).clone() { - PatternSubject::PatternResolved { node: r, .. } => { - let scrutinee_is_coproduct = (r.connective.clone() == Connective::Disj); - if scrutinee_is_coproduct.clone() { - variant_parent_identity_of(Some(r.clone()), scope.clone()) - } else { - Rc::new(VariantParentIdentity::VariantParentUnrecovered { - cause: "the scrutinee's resolved type is not a coproduct declaration".to_string(), -}) - } - } - PatternSubject::PatternDynamic { span: _, .. } => { - Rc::new(VariantParentIdentity::VariantParentUnrecovered { + PatternSubject::PatternDynamic { span: _, .. } => { + Rc::new(PatternParentReading { + parent_enum: std::option::Option::None, + identity: Rc::new(VariantParentIdentity::VariantParentUnrecovered { cause: "the scrutinee's type is dynamic".to_string(), - }) - } - PatternSubject::PatternLookupBlocked => { - Rc::new(VariantParentIdentity::VariantParentUnrecovered { - cause: "the scrutinee's type lookup was blocked".to_string(), - }) - } + }), + }) } + PatternSubject::PatternLookupBlocked => Rc::new(PatternParentReading { + parent_enum: std::option::Option::None, + identity: Rc::new(VariantParentIdentity::VariantParentUnrecovered { + cause: "the scrutinee's type lookup was blocked".to_string(), + }), + }), }; + let inferred_parent = parent_reading.parent_enum.clone(); + let parent_identity = parent_reading.identity.clone(); + let annotated_variant_name = variant_name.clone(); let variant_lookup = crate::v1_compiler_infer_patterns::lookup_variant_in_type( resolved_scrut.clone(), variant_name.clone(), From 2e9c5737a4f8330a9b85938df0a7c4b281714155 Mon Sep 17 00:00:00 2001 From: "gunbai-bot[bot]" <289086189+gunbai-bot[bot]@users.noreply.github.com> Date: Fri, 2 Oct 2026 01:32:39 -0400 Subject: [PATCH 15/21] Interpreter: std.types Bool arms realize as host bool from the same identity-keyed rows; undecidable arm refuses (Bool de-fork PR-1b) (#12567) Co-authored-by: Brian Searls Co-authored-by: Claude Opus 5.5 (1M context) --- dag/gunbc/observation_ci_render.dag | 2 + src/v1/stage0/src/cli_run.rs | 3 + src/v1/stage0/src/v1_interpreter.rs | 101 +++++++++++++++++- .../native_bool_arm_interpretation_test.dag | 30 ++++++ .../test/fixture/local_verdict_coproduct.dag | 25 +++++ 5 files changed, 158 insertions(+), 3 deletions(-) create mode 100644 src/v2/test/claim/logic/native_bool_arm_interpretation_test.dag create mode 100644 src/v2/test/fixture/local_verdict_coproduct.dag diff --git a/dag/gunbc/observation_ci_render.dag b/dag/gunbc/observation_ci_render.dag index f7ca45253fc..6aedd079980 100644 --- a/dag/gunbc/observation_ci_render.dag +++ b/dag/gunbc/observation_ci_render.dag @@ -896,6 +896,7 @@ type CiWitnessRuntimeCause | WitnessCauseTypeError | WitnessCauseCrossRepresentationEquality | WitnessCauseStringRealizationStraddle + | WitnessCauseVariantRealizationRefused | WitnessCausePoolRootContributesNothing | WitnessCausePatternMatchFailure | WitnessCauseDivisionByZero @@ -925,6 +926,7 @@ fn ci_witness_runtime_cause_token(cause: CiWitnessRuntimeCause) -> String { WitnessCauseTypeError => "type-error" WitnessCauseCrossRepresentationEquality => "cross-representation-equality" WitnessCauseStringRealizationStraddle => "string-realization-straddle" + WitnessCauseVariantRealizationRefused => "variant-realization-refused" WitnessCausePoolRootContributesNothing => "pool-root-contributes-nothing" WitnessCausePatternMatchFailure => "pattern-match-failure" WitnessCauseDivisionByZero => "division-by-zero" diff --git a/src/v1/stage0/src/cli_run.rs b/src/v1/stage0/src/cli_run.rs index b31d4d8ce57..03102c3fce6 100644 --- a/src/v1/stage0/src/cli_run.rs +++ b/src/v1/stage0/src/cli_run.rs @@ -11139,6 +11139,7 @@ pub enum WitnessRuntimeCause { TypeError, CrossRepresentationEquality, StringRealizationStraddle, + VariantRealizationRefused, PoolRootContributesNothing, PatternMatchFailure, /// A REST response value did not inhabit its declared coproduct (see @@ -11177,6 +11178,7 @@ impl WitnessRuntimeCause { WitnessRuntimeCause::TypeError => "type-error", WitnessRuntimeCause::CrossRepresentationEquality => "cross-representation-equality", WitnessRuntimeCause::StringRealizationStraddle => "string-realization-straddle", + WitnessRuntimeCause::VariantRealizationRefused => "variant-realization-refused", WitnessRuntimeCause::PoolRootContributesNothing => "pool-root-contributes-nothing", WitnessRuntimeCause::PatternMatchFailure => "pattern-match-failure", WitnessRuntimeCause::RestResponseUndecodable => "rest-response-undecodable", @@ -11213,6 +11215,7 @@ impl WitnessRuntimeCause { WitnessRuntimeCause::CrossRepresentationEquality } E::StringRealizationStraddle { .. } => WitnessRuntimeCause::StringRealizationStraddle, + E::VariantRealizationRefused { .. } => WitnessRuntimeCause::VariantRealizationRefused, E::PoolRootContributesNothing { .. } => WitnessRuntimeCause::PoolRootContributesNothing, E::PatternMatchFailure { .. } => WitnessRuntimeCause::PatternMatchFailure, E::RestResponseUndecodable { .. } => WitnessRuntimeCause::RestResponseUndecodable, diff --git a/src/v1/stage0/src/v1_interpreter.rs b/src/v1/stage0/src/v1_interpreter.rs index 0510848e393..eaf32810c0f 100644 --- a/src/v1/stage0/src/v1_interpreter.rs +++ b/src/v1/stage0/src/v1_interpreter.rs @@ -1156,6 +1156,14 @@ pub enum InterpError { PatternMatchFailure { value: String, }, + /// A variant occurrence of a natively realized coproduct (std.types Bool over the host `bool`) + /// whose realization could not be decided -- its owning coproduct was not recovered, or the + /// row set refused -- so it is refused rather than matched or constructed by its arm NAME. + /// The decision is `v1.compiler.coercion` `rust_variant_value_realization`, the same one the + /// Rust emitter consumes. + VariantRealizationRefused { + detail: String, + }, /// A REST response value did not inhabit the coproduct its declared output type names. /// Raised by `decode_json_by_declared_type`; see `RestResponseDecodeRefusal`. RestResponseUndecodable { @@ -1394,6 +1402,9 @@ impl fmt::Display for InterpError { InterpError::StringRealizationStraddle { detail } => { write!(f, "string realization straddle: {}", detail) } + InterpError::VariantRealizationRefused { detail } => { + write!(f, "{}", detail) + } InterpError::PoolRootContributesNothing { caller, declared, @@ -5073,6 +5084,11 @@ pub struct InterpContext { // eval goes straight to env.lookup(sym), materializing the String only on the registry slow path. var_sym_cache: std::cell::RefCell>, var_sym_cache_keepalive: std::cell::RefCell>>, + /// A refusal raised inside `match_pattern` (which answers match / no-match as an `Option`), + /// taken by the one caller that owns the match and turned into + /// `InterpError::VariantRealizationRefused` -- so an undecidable native arm stops the match + /// instead of falling through to the next arm. + variant_realization_refusal: std::cell::RefCell>, // Same chokepoint, ExprCall callee name: eval_call re-sliced the callee name from its source // span (expr_call_func_at -> authored_name_at) on every call. Memoize the decoded name per // call node — keyed by node pointer, kept alive via call_func_name_cache_keepalive as above. @@ -5508,6 +5524,7 @@ impl InterpContext { param_name_cache_keepalive: std::cell::RefCell::new(Vec::new()), var_sym_cache: std::cell::RefCell::new(HashMap::new()), var_sym_cache_keepalive: std::cell::RefCell::new(Vec::new()), + variant_realization_refusal: std::cell::RefCell::new(None), call_func_name_cache: std::cell::RefCell::new(HashMap::new()), call_func_name_cache_keepalive: std::cell::RefCell::new(Vec::new()), cast_kernel_cache: std::cell::RefCell::new(HashMap::new()), @@ -6845,7 +6862,25 @@ fn eval_var( } }; - if let Some(VarBindingKind::VariantValueBinding { parent_enum, .. }) = binding_kind { + if let Some(VarBindingKind::VariantValueBinding { + parent_enum, + parent_identity, + }) = binding_kind + { + let arm_spelling = ctx.resolve(sym); + let arm = arm_spelling.rsplit('.').next().unwrap_or(&arm_spelling); + match native_variant_reading(parent_identity, arm) { + NativeVariantReading::HostBool(b) => return Ok(Value::Bool(b)), + NativeVariantReading::Structural => {} + NativeVariantReading::Refused(detail) => { + // A value construction refuses only for an arm a native row could have claimed; + // an unrecovered owner whose arm no row mentions is structural, as in emission. + if crate::v1_compiler_coercion::rust_variant_arm_is_bound_somewhere(arm.to_string()) + { + return Err(InterpError::VariantRealizationRefused { detail }); + } + } + } // Bounded residual: Nat's intentional native representation is still selected by the // arm lexeme because the seed binding carrier lacks exact owner declaration identity. // The executable shorthand test and GuaranteeStall keep that silent-wrongness path @@ -7663,7 +7698,11 @@ fn eval_match(node: &Rc, env: &Rc, ctx: &InterpContext) -> InterpResu } else { scrutinee_val.clone() }; - if let Some(bindings) = match_pattern(&pattern, &arm_value, ctx) { + let matched = match_pattern(&pattern, &arm_value, ctx); + if let Some(detail) = ctx.variant_realization_refusal.borrow_mut().take() { + return Err(InterpError::VariantRealizationRefused { detail }); + } + if let Some(bindings) = matched { let arm_env = Env::extend(env, bindings); return eval_expr(&arm_body(arm.clone()), &arm_env, ctx); } @@ -8576,6 +8615,41 @@ fn try_witness_evaluation_dispatch( } } +/// THE INTERPRETER'S HALF OF THE NATIVE-VARIANT LOWERING. The interpreter is a Rust-hosted +/// realization whose `Value::Bool` holds a Rust `bool`, so it asks the SAME identity-keyed decision +/// the Rust emitter asks (`v1.compiler.coercion` `rust_variant_value_realization`, over +/// `gunbc.rust_source_type_bindings` `rust_source_variant_value_rows`) and reads the row's value +/// with Rust's own `bool` parse -- the projection of that row onto this host, not a second table. +enum NativeVariantReading { + HostBool(bool), + Structural, + Refused(String), +} + +fn native_variant_reading( + parent: &Rc, + arm: &str, +) -> NativeVariantReading { + use crate::std_target_representation::VariantValueRealization as R; + let r = crate::v1_compiler_coercion::rust_variant_value_realization( + parent.clone(), + arm.to_string(), + ); + match &*r { + R::VariantRealizesAsTargetValue { value_spelling } => match value_spelling.parse::() { + Ok(b) => NativeVariantReading::HostBool(b), + Err(_) => NativeVariantReading::Refused(format!( + "variant realization: arm `{arm}` realizes as the target value `{value_spelling}`, which the interpreter's host bool cannot hold" + )), + }, + R::VariantRealizesStructurally => NativeVariantReading::Structural, + _ => NativeVariantReading::Refused( + crate::std_target_representation::variant_value_realization_refusal_message(r.clone()) + .unwrap_or_else(|| format!("variant realization: arm `{arm}` was refused")), + ), + } +} + fn match_pattern( pattern: &MatchPattern, value: &Value, @@ -8603,8 +8677,29 @@ fn match_pattern( name, parent_enum, field_bindings, - .. + parent_identity, } => { + // A variant pattern against a HOST bool is a native arm or nothing: the identity + // inference carried decides which value it denotes, and an undecidable one refuses. + // Variant values (a module-local coproduct whose arms happen to be spelled True/False) + // never reach this branch and keep their structural match below. + if let Value::Bool(held) = value { + let arm = name.rsplit('.').next().unwrap_or(name); + return match native_variant_reading(parent_identity, arm) { + NativeVariantReading::HostBool(b) => { + if *held == b { + Some(HashMap::new()) + } else { + None + } + } + NativeVariantReading::Structural => None, + NativeVariantReading::Refused(detail) => { + *ctx.variant_realization_refusal.borrow_mut() = Some(detail); + None + } + }; + } // A qualified pattern spelling (`module.Variant`) resolves the arm name to its // containment path, but values are constructed with the bare last segment (the // short-name normalization at value construction). Every name-vs-literal diff --git a/src/v2/test/claim/logic/native_bool_arm_interpretation_test.dag b/src/v2/test/claim/logic/native_bool_arm_interpretation_test.dag new file mode 100644 index 00000000000..222e7a8f79f --- /dev/null +++ b/src/v2/test/claim/logic/native_bool_arm_interpretation_test.dag @@ -0,0 +1,30 @@ +module v2.test.claim.logic.native_bool_arm_interpretation_test + +import v2.test.fixture.local_verdict_coproduct { verdict_top, verdict_negate, verdict_is_top } + +// THE INTERPRETER'S HALF OF THE NATIVE-VARIANT LOWERING, through the real interpreter route. The +// arms of std.types Bool (the kernel Bool every module's `Bool` resolves to) realize as the host +// bool: a `True`/`False` pattern matches the host values and a constructed `True` IS host true. +// Before the lowering the interpreter matched variant patterns by name against a host bool and +// failed (PatternMatchFailure { value: "true" }). +// +// The patterns are the subject here, so the arm bodies return host values. A bare `True`/`False` +// VALUE in this corpus still resolves to v2.std.logic's structural Bool until the Bool de-fork +// deletes it; the constructed-arm claim therefore lives with that cut, where the one Bool is the +// only thing a bare arm can mean. +fn negate_by_arms(b: Bool) -> Bool { + match b { + True => false + False => true + } +} + +test fn bool_arms_match_the_host_values() -> Bool { + negate_by_arms(b: true) == false && negate_by_arms(b: false) == true +} + +// THE IDENTITY CONTROL: a module-local coproduct whose arms are spelled True/False keeps being its +// own coproduct in the interpreter -- constructed as its variant, matched as its variant. +test fn a_local_coproduct_with_true_false_arms_stays_its_own_variants() -> Bool { + verdict_is_top(v: verdict_top()) && !verdict_is_top(v: verdict_negate(v: verdict_top())) +} diff --git a/src/v2/test/fixture/local_verdict_coproduct.dag b/src/v2/test/fixture/local_verdict_coproduct.dag new file mode 100644 index 00000000000..f7829349423 --- /dev/null +++ b/src/v2/test/fixture/local_verdict_coproduct.dag @@ -0,0 +1,25 @@ +module v2.test.fixture.local_verdict_coproduct + +// A MODULE-LOCAL COPRODUCT WHOSE ARMS ARE SPELLED True/False, for the identity control in +// v2.test.claim.logic.native_bool_arm_interpretation_test. It has no row in +// gunbc.rust_source_type_bindings, so the interpreter must construct and match it as its own +// variants, never as the host bool its arm spellings resemble. +type Verdict = True | False + +fn verdict_top() -> Verdict { + True +} + +fn verdict_negate(v: Verdict) -> Verdict { + match v { + True => False + False => True + } +} + +fn verdict_is_top(v: Verdict) -> Bool { + match v { + True => true + False => false + } +} From 6b25196ae411a0125694dc8d27bf5585811d687b Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Fri, 2 Oct 2026 05:52:20 +0000 Subject: [PATCH 16/21] Merge: union the std_kernel_type_name partition row with main's clock_gettime row Co-Authored-By: Claude Opus 5.5 (1M context) --- dag/gunbc/stage0/stage0_crate_partition_generated.dag | 1 + 1 file changed, 1 insertion(+) diff --git a/dag/gunbc/stage0/stage0_crate_partition_generated.dag b/dag/gunbc/stage0/stage0_crate_partition_generated.dag index dbfaa480e16..dc78d940300 100644 --- a/dag/gunbc/stage0/stage0_crate_partition_generated.dag +++ b/dag/gunbc/stage0/stage0_crate_partition_generated.dag @@ -73,6 +73,7 @@ data generated_partition_crate_rows: List = [ "extdeps_units_iso_80000_3", "std_occurrence_identity", "std_source_annotation", + "std_kernel_type_name", "std_target_representation", "std_literal_elaboration", "std_operator_realization", From def1adc62fea5f8578cb2e5df933488a5ee4ae11 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Fri, 2 Oct 2026 06:08:16 +0000 Subject: [PATCH 17/21] Merge: three-way merge of hand-authored v1_interpreter.rs and compiler_tests.rs (not mirrors) Co-Authored-By: Claude Opus 5.5 (1M context) --- src/v1/stage0/src/compiler_tests.rs | 49 ++++++++++++++ src/v1/stage0/src/v1_interpreter.rs | 100 +++++++++++++++++++++++++++- 2 files changed, 147 insertions(+), 2 deletions(-) diff --git a/src/v1/stage0/src/compiler_tests.rs b/src/v1/stage0/src/compiler_tests.rs index 20316402c11..ad78aaeba41 100644 --- a/src/v1/stage0/src/compiler_tests.rs +++ b/src/v1/stage0/src/compiler_tests.rs @@ -1360,6 +1360,55 @@ mod compiler_tests { ); } + /// THE ARMS OF A NATIVELY REALIZED COPRODUCT, JUDGED BY RUSTC, AND THE IDENTITY CONTROL BESIDE IT. + /// + /// The subject is `v1.compiler.emit_rust` `rust_native_variant_spelling`: an arm of a + /// coproduct that realizes natively (std.types Bool over Rust `bool`) is spelled as the + /// carrier value its declaration-keyed row names, in value, pattern and nested-pattern + /// position. The first pair's control is that fixture and must COMPILE; before the rows it + /// emitted `Bool::True` against a `bool` and rustc refused it. The second pair's control is a + /// module-local coproduct whose arms are spelled True/False, which has no row and must keep its own enum -- the + /// evidence that the rows are keyed on identity rather than on the spelling. Both reds are + /// the route's own adjudicated red. + /// + /// #[ignore] AND WHY, on the same terms as the pairs beside it: each pair spawns cargo and + /// compiles two emitted crates. It is RUNNABLE ON DEMAND -- `cargo test --release -p + /// v1-compiler --lib native_bool_variant_fixture_closure_discrimination -- --ignored`. No CI + /// path invokes it (gunbc.rung_drop rust_unit_tests_off_the_merge_path); the emitted-bytes + /// half that does run on the floor is test.claim.native_variant_realization_witness_test. + #[test] + #[ignore] + fn native_bool_variant_fixture_closure_discrimination() { + let probe_root = crate::cli_run::local_emit_compile_probe_root().unwrap(); + for (label, pair) in [ + ( + "native-bool-variant", + crate::cli_run::run_native_bool_variant_discrimination(&probe_root), + ), + ( + "local-true-false-coproduct", + crate::cli_run::run_local_true_false_coproduct_discrimination(&probe_root), + ), + ] { + for line in crate::cli_run::fixture_discrimination_report(&pair) { + eprintln!("{} {}", label, line); + } + assert!( + crate::cli_run::fixture_closure_reached_rustc(&pair.red), + "{}: the red arm never reached a rustc verdict: {}", + label, + crate::cli_run::fixture_closure_summary(&pair.red) + ); + assert!( + crate::cli_run::fixture_discrimination_passed(&pair), + "{}: the control must COMPILE and the route red must still be refused by rustc in its own module; control={} red={}", + label, + crate::cli_run::fixture_closure_summary(&pair.green), + crate::cli_run::fixture_closure_summary(&pair.red) + ); + } + } + /// THE PHANTOM-MARKER POSITION PAIR, JUDGED BY RUSTC, THROUGH THE FIXTURE-CLOSURE ROUTE. /// /// NOT THE BROAD-VERSUS-POSITIONAL CLASSIFIER DISCRIMINATOR. That one's arms are two diff --git a/src/v1/stage0/src/v1_interpreter.rs b/src/v1/stage0/src/v1_interpreter.rs index 4f48e01d4d4..f6fc9fb2b54 100644 --- a/src/v1/stage0/src/v1_interpreter.rs +++ b/src/v1/stage0/src/v1_interpreter.rs @@ -1258,6 +1258,14 @@ pub enum InterpError { at: String, found: String, }, + /// A variant occurrence of a natively realized coproduct (std.types Bool over the host `bool`) + /// whose realization could not be decided -- its owning coproduct was not recovered, or the + /// row set refused -- so it is refused rather than matched or constructed by its arm NAME. + /// The decision is `v1.compiler.coercion` `rust_variant_value_realization`, the same one the + /// Rust emitter consumes. + VariantRealizationRefused { + detail: String, + }, /// A REST response value did not inhabit the coproduct its declared output type names. /// Raised by `decode_json_by_declared_type`; see `RestResponseDecodeRefusal`. RestResponseUndecodable { @@ -1496,6 +1504,9 @@ impl fmt::Display for InterpError { InterpError::StringRealizationStraddle { detail } => { write!(f, "string realization straddle: {}", detail) } + InterpError::VariantRealizationRefused { detail } => { + write!(f, "{}", detail) + } InterpError::PoolRootContributesNothing { caller, declared, @@ -5306,6 +5317,11 @@ pub struct InterpContext { // eval goes straight to env.lookup(sym), materializing the String only on the registry slow path. var_sym_cache: std::cell::RefCell>, var_sym_cache_keepalive: std::cell::RefCell>>, + /// A refusal raised inside `match_pattern` (which answers match / no-match as an `Option`), + /// taken by the one caller that owns the match and turned into + /// `InterpError::VariantRealizationRefused` -- so an undecidable native arm stops the match + /// instead of falling through to the next arm. + variant_realization_refusal: std::cell::RefCell>, // Same chokepoint, ExprCall callee name: eval_call re-sliced the callee name from its source // span (expr_call_func_at -> authored_name_at) on every call. Memoize the decoded name per // call node — keyed by node pointer, kept alive via call_func_name_cache_keepalive as above. @@ -5739,6 +5755,7 @@ impl InterpContext { param_name_cache_keepalive: std::cell::RefCell::new(Vec::new()), var_sym_cache: std::cell::RefCell::new(HashMap::new()), var_sym_cache_keepalive: std::cell::RefCell::new(Vec::new()), + variant_realization_refusal: std::cell::RefCell::new(None), call_func_name_cache: std::cell::RefCell::new(HashMap::new()), call_func_name_cache_keepalive: std::cell::RefCell::new(Vec::new()), cast_kernel_cache: std::cell::RefCell::new(HashMap::new()), @@ -7098,7 +7115,25 @@ fn eval_var( } }; - if let Some(VarBindingKind::VariantValueBinding { parent_enum }) = binding_kind { + if let Some(VarBindingKind::VariantValueBinding { + parent_enum, + parent_identity, + }) = binding_kind + { + let arm_spelling = ctx.resolve(sym); + let arm = arm_spelling.rsplit('.').next().unwrap_or(&arm_spelling); + match native_variant_reading(parent_identity, arm) { + NativeVariantReading::HostBool(b) => return Ok(Value::Bool(b)), + NativeVariantReading::Structural => {} + NativeVariantReading::Refused(detail) => { + // A value construction refuses only for an arm a native row could have claimed; + // an unrecovered owner whose arm no row mentions is structural, as in emission. + if crate::v1_compiler_coercion::rust_variant_arm_is_bound_somewhere(arm.to_string()) + { + return Err(InterpError::VariantRealizationRefused { detail }); + } + } + } // Bounded residual: Nat's intentional native representation is still selected by the // arm lexeme because the seed binding carrier lacks exact owner declaration identity. // The executable shorthand test and GuaranteeStall keep that silent-wrongness path @@ -7915,7 +7950,11 @@ fn eval_match(node: &Rc, env: &Rc, ctx: &InterpContext) -> InterpResu } else { scrutinee_val.clone() }; - if let Some(bindings) = match_pattern(&pattern, &arm_value, ctx) { + let matched = match_pattern(&pattern, &arm_value, ctx); + if let Some(detail) = ctx.variant_realization_refusal.borrow_mut().take() { + return Err(InterpError::VariantRealizationRefused { detail }); + } + if let Some(bindings) = matched { let arm_env = Env::extend(env, bindings); // A guard is part of the arm's admission, evaluated in the arm's bindings: a false // guard falls through to the next arm, exactly as the emitted `pat if guard =>` does. @@ -8991,6 +9030,41 @@ fn try_witness_evaluation_dispatch( } } +/// THE INTERPRETER'S HALF OF THE NATIVE-VARIANT LOWERING. The interpreter is a Rust-hosted +/// realization whose `Value::Bool` holds a Rust `bool`, so it asks the SAME identity-keyed decision +/// the Rust emitter asks (`v1.compiler.coercion` `rust_variant_value_realization`, over +/// `gunbc.rust_source_type_bindings` `rust_source_variant_value_rows`) and reads the row's value +/// with Rust's own `bool` parse -- the projection of that row onto this host, not a second table. +enum NativeVariantReading { + HostBool(bool), + Structural, + Refused(String), +} + +fn native_variant_reading( + parent: &Rc, + arm: &str, +) -> NativeVariantReading { + use crate::std_target_representation::VariantValueRealization as R; + let r = crate::v1_compiler_coercion::rust_variant_value_realization( + parent.clone(), + arm.to_string(), + ); + match &*r { + R::VariantRealizesAsTargetValue { value_spelling } => match value_spelling.parse::() { + Ok(b) => NativeVariantReading::HostBool(b), + Err(_) => NativeVariantReading::Refused(format!( + "variant realization: arm `{arm}` realizes as the target value `{value_spelling}`, which the interpreter's host bool cannot hold" + )), + }, + R::VariantRealizesStructurally => NativeVariantReading::Structural, + _ => NativeVariantReading::Refused( + crate::std_target_representation::variant_value_realization_refusal_message(r.clone()) + .unwrap_or_else(|| format!("variant realization: arm `{arm}` was refused")), + ), + } +} + fn match_pattern( pattern: &MatchPattern, value: &Value, @@ -9019,7 +9093,29 @@ fn match_pattern( name, parent_enum, field_bindings, + parent_identity, } => { + // A variant pattern against a HOST bool is a native arm or nothing: the identity + // inference carried decides which value it denotes, and an undecidable one refuses. + // Variant values (a module-local coproduct whose arms happen to be spelled True/False) + // never reach this branch and keep their structural match below. + if let Value::Bool(held) = value { + let arm = name.rsplit('.').next().unwrap_or(name); + return match native_variant_reading(parent_identity, arm) { + NativeVariantReading::HostBool(b) => { + if *held == b { + Some(HashMap::new()) + } else { + None + } + } + NativeVariantReading::Structural => None, + NativeVariantReading::Refused(detail) => { + *ctx.variant_realization_refusal.borrow_mut() = Some(detail); + None + } + }; + } // A qualified pattern spelling (`module.Variant`) resolves the arm name to its // containment path, but values are constructed with the bare last segment (the // short-name normalization at value construction). Every name-vs-literal From bb5f22922381fe66a1b37956edfa42fcc73a8bf3 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Fri, 2 Oct 2026 06:23:41 +0000 Subject: [PATCH 18/21] census_heads: carry VariantPattern parent_identity through the occurrence projection Co-Authored-By: Claude Opus 5.5 (1M context) --- src/v1/stage0/src/cli_run/census_heads.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/v1/stage0/src/cli_run/census_heads.rs b/src/v1/stage0/src/cli_run/census_heads.rs index cf966b39dda..d492ad4088d 100644 --- a/src/v1/stage0/src/cli_run/census_heads.rs +++ b/src/v1/stage0/src/cli_run/census_heads.rs @@ -406,10 +406,12 @@ fn project_node(n: &Rc, base: i64, relabel: &[i64]) -> Result, St name, parent_enum, field_bindings, + parent_identity, }) => Some(Rc::new(MatchPattern::VariantPattern { name: name.clone(), parent_enum: parent_enum.clone(), field_bindings: list(field_bindings)?, + parent_identity: parent_identity.clone(), })), Some(MatchPattern::LitPattern { value: _ }) | Some(MatchPattern::Wildcard) => { match_pattern.clone() From dbca6a26a362a03166e696d562d50361d72206a6 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Fri, 2 Oct 2026 06:57:40 +0000 Subject: [PATCH 19/21] Regenerate stage0 mirrors to the fixed point after merging main (claim_executor --required-regen, round 2 first_generation_equal=true) Co-Authored-By: Claude Opus 5.5 (1M context) --- src/v1/stage0/src/emitted_population.rs | 1 + .../src/gunbc_rust_source_type_bindings.rs | 76 ++- .../gunbc_stage0_crate_partition_generated.rs | 2 +- src/v1/stage0/src/v1_compiler_compile.rs | 25 +- .../src/v1_compiler_compiler_tests_rust.rs | 6 +- src/v1/stage0/src/v1_compiler_emit.rs | 5 +- src/v1/stage0/src/v1_compiler_emit_rust.rs | 478 +++++++++++------- src/v1/stage0/src/v1_compiler_infer.rs | 130 ++++- src/v1/stage0/src/v1_compiler_parse.rs | 13 + src/v1/stage0/src/v1_std_core.rs | 20 +- 10 files changed, 544 insertions(+), 212 deletions(-) diff --git a/src/v1/stage0/src/emitted_population.rs b/src/v1/stage0/src/emitted_population.rs index 0183a2a8d2c..0438b0a3b7d 100644 --- a/src/v1/stage0/src/emitted_population.rs +++ b/src/v1/stage0/src/emitted_population.rs @@ -68,6 +68,7 @@ // src/std_induction.rs // src/std_integer.rs // src/std_interface_summary.rs +// src/std_kernel_type_name.rs // src/std_keyed_roster.rs // src/std_keyed_row.rs // src/std_literal_elaboration.rs diff --git a/src/v1/stage0/src/gunbc_rust_source_type_bindings.rs b/src/v1/stage0/src/gunbc_rust_source_type_bindings.rs index 43be126976a..2aea0720b08 100644 --- a/src/v1/stage0/src/gunbc_rust_source_type_bindings.rs +++ b/src/v1/stage0/src/gunbc_rust_source_type_bindings.rs @@ -5,13 +5,25 @@ pub use crate::extdeps_languages_rust_representation::RustRepresentation; use crate::extdeps_languages_rust_representation::RustRepresentation::{ RustBool, RustI64, RustSerdeJsonValue, RustStdString, RustUnit, RustVecU8, }; +pub use crate::extdeps_languages_rust_representation::{ + rust_bool_false_value, rust_bool_true_value, +}; pub use crate::std_decl_ref::decl_ref; pub use crate::std_decl_ref::DeclarationRef; +pub use crate::std_kernel_type_name::kernel_type_name; +pub use crate::std_kernel_type_name::KernelTypeNameAdmission; +use crate::std_kernel_type_name::KernelTypeNameAdmission::{ + KernelTypeNameAdmitted, NotAKernelTypeName, +}; use crate::std_target_representation::CheckpointRowDisposition::{ MigratedToExactBinding, ProvenUniqueKernelBinding, StillBareNameDebt, }; +use crate::std_target_representation::VariantParentKey::{ + VariantParentDeclaration, VariantParentKernelType, +}; pub use crate::std_target_representation::{ - CheckpointRowDisposition, CheckpointRowMigration, SourceTypeTargetBinding, + CheckpointRowDisposition, CheckpointRowMigration, RepresentationValue, SourceTypeTargetBinding, + SourceVariantTargetValue, VariantParentKey, }; use crate::std_types::Bool::*; pub use crate::std_types::{Bool, List, NonEmptyStr}; @@ -43,6 +55,68 @@ pub fn rust_source_type_binding_rows() -> Rc>>>| c.clone()) } +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct BoolArmValue { + pub variant: NonEmptyStr, + pub value: Rc>, +} + +pub fn rust_bool_arm_values() -> Rc>> { + thread_local! { + static CACHED: Rc>> = { + Rc::new(vec![Rc::new(BoolArmValue { + variant: "True".to_string(), + value: rust_bool_true_value(), + }), Rc::new(BoolArmValue { + variant: "False".to_string(), + value: rust_bool_false_value(), + })]) + }; + } + CACHED.with(|c: &Rc>>| c.clone()) +} + +pub fn rust_bool_variant_rows( + parent: Rc, +) -> Rc>>> { + Rc::new({ + let mut __result = Vec::new(); + for a in rust_bool_arm_values().iter().cloned() { + __result.push(Rc::new(SourceVariantTargetValue { + parent: parent.clone(), + variant: a.variant.clone(), + value: a.value.clone(), + _phantom: std::marker::PhantomData, + })); + } + __result + }) +} + +pub fn rust_bool_kernel_variant_rows() -> Rc>>> +{ + match (*crate::std_kernel_type_name::kernel_type_name("Bool".to_string())).clone() { + KernelTypeNameAdmission::KernelTypeNameAdmitted { kernel_name: k, .. } => { + rust_bool_variant_rows(Rc::new(VariantParentKey::VariantParentKernelType { + kernel_name: k.clone(), + })) + } + KernelTypeNameAdmission::NotAKernelTypeName { name: _, .. } => Rc::new(vec![]), + } +} + +pub fn rust_source_variant_value_rows() -> Rc>>> +{ + thread_local! { + static CACHED: Rc>>> = { + v1_rt::concat(rust_bool_variant_rows(Rc::new(VariantParentKey::VariantParentDeclaration { + declaration: crate::std_decl_ref::decl_ref("std.types".to_string(), "Bool".to_string()), + })), rust_bool_kernel_variant_rows()) + }; + } + CACHED.with(|c: &Rc>>>| c.clone()) +} + pub fn rust_bound_declaration_refs() -> Rc>> { Rc::new({ let mut __result = Vec::new(); diff --git a/src/v1/stage0/src/gunbc_stage0_crate_partition_generated.rs b/src/v1/stage0/src/gunbc_stage0_crate_partition_generated.rs index 13bc6d23fdc..cc1d4931371 100644 --- a/src/v1/stage0/src/gunbc_stage0_crate_partition_generated.rs +++ b/src/v1/stage0/src/gunbc_stage0_crate_partition_generated.rs @@ -54,7 +54,7 @@ pub fn generated_partition_crate_rows() -> Rc package_name: "v1-stage0-std-core".to_string(), crate_dir: "src/v1/stage0_std_core".to_string(), kind: GeneratedPartitionCrateKind::GeneratedLayeredCoreCrate, - modules: Rc::new(vec!["std_content_hash".to_string(), "std_coercion".to_string(), "extdeps_currency_currency".to_string(), "std_decl_ref".to_string(), "std_keyed_row".to_string(), "std_keyed_roster".to_string(), "std_roster_frontier".to_string(), "std_dissolution".to_string(), "std_disposition".to_string(), "std_error_primitives".to_string(), "std_emit_model".to_string(), "std_magnitude".to_string(), "std_measure".to_string(), "std_types".to_string(), "std_unicode_types".to_string(), "std_algebra".to_string(), "std_nat".to_string(), "std_node".to_string(), "std_syntax".to_string(), "std_computation".to_string(), "std_termination".to_string(), "std_checked_arithmetic".to_string(), "std_induction".to_string(), "std_graph".to_string(), "extdeps_uri".to_string(), "extdeps_external_authority".to_string(), "extdeps_posix_clock_gettime".to_string(), "extdeps_ietf_http_semantics".to_string(), "std_process_termination".to_string(), "std_primitive_projection".to_string(), "extdeps_container_oci_digest".to_string(), "extdeps_units_dimensionless".to_string(), "extdeps_units_iec_80000_13".to_string(), "extdeps_units_iso8601".to_string(), "extdeps_units_iso_80000_3".to_string(), "std_occurrence_identity".to_string(), "std_source_annotation".to_string(), "std_target_representation".to_string(), "std_literal_elaboration".to_string(), "std_operator_realization".to_string(), "std_import".to_string(), "v1_std_core".to_string(), "gunbc_rust_emitted_edge".to_string()]), + modules: Rc::new(vec!["std_content_hash".to_string(), "std_coercion".to_string(), "extdeps_currency_currency".to_string(), "std_decl_ref".to_string(), "std_keyed_row".to_string(), "std_keyed_roster".to_string(), "std_roster_frontier".to_string(), "std_dissolution".to_string(), "std_disposition".to_string(), "std_error_primitives".to_string(), "std_emit_model".to_string(), "std_magnitude".to_string(), "std_measure".to_string(), "std_types".to_string(), "std_unicode_types".to_string(), "std_algebra".to_string(), "std_nat".to_string(), "std_node".to_string(), "std_syntax".to_string(), "std_computation".to_string(), "std_termination".to_string(), "std_checked_arithmetic".to_string(), "std_induction".to_string(), "std_graph".to_string(), "extdeps_uri".to_string(), "extdeps_external_authority".to_string(), "extdeps_posix_clock_gettime".to_string(), "extdeps_ietf_http_semantics".to_string(), "std_process_termination".to_string(), "std_primitive_projection".to_string(), "extdeps_container_oci_digest".to_string(), "extdeps_units_dimensionless".to_string(), "extdeps_units_iec_80000_13".to_string(), "extdeps_units_iso8601".to_string(), "extdeps_units_iso_80000_3".to_string(), "std_occurrence_identity".to_string(), "std_source_annotation".to_string(), "std_kernel_type_name".to_string(), "std_target_representation".to_string(), "std_literal_elaboration".to_string(), "std_operator_realization".to_string(), "std_import".to_string(), "v1_std_core".to_string(), "gunbc_rust_emitted_edge".to_string()]), reexport_packages: Rc::new(vec!["v1-stage0-runtime".to_string()]), carries_non_empty_wrappers: false, }), Rc::new(GeneratedPartitionCrateRow { diff --git a/src/v1/stage0/src/v1_compiler_compile.rs b/src/v1/stage0/src/v1_compiler_compile.rs index 2b28faad886..329df798988 100644 --- a/src/v1/stage0/src/v1_compiler_compile.rs +++ b/src/v1/stage0/src/v1_compiler_compile.rs @@ -682,9 +682,7 @@ pub fn function_value_target( crate::v1_std_core::authored_name_at(source_indices.clone(), texpr.clone()), ), VarBindingKind::LocalValueBinding => std::option::Option::None, - VarBindingKind::VariantValueBinding { parent_enum: _, .. } => { - std::option::Option::None - } + VarBindingKind::VariantValueBinding { .. } => std::option::Option::None, VarBindingKind::MatchBoundBinding => std::option::Option::None, VarBindingKind::ServiceValueBinding => std::option::Option::None, }, @@ -1692,9 +1690,7 @@ pub fn var_binding_kind_name(value: Rc) -> String { match (*value.clone()).clone() { VarBindingKind::LocalValueBinding => "LocalValueBinding".to_string(), VarBindingKind::FunctionValueBinding => "FunctionValueBinding".to_string(), - VarBindingKind::VariantValueBinding { parent_enum: _, .. } => { - "VariantValueBinding".to_string() - } + VarBindingKind::VariantValueBinding { .. } => "VariantValueBinding".to_string(), VarBindingKind::MatchBoundBinding => "MatchBoundBinding".to_string(), VarBindingKind::ServiceValueBinding => "ServiceValueBinding".to_string(), } @@ -2480,15 +2476,14 @@ pub fn serialize_expr_data( ), ), match (*inner.clone()).clone() { - VarBindingKind::VariantValueBinding { - parent_enum: parent_enum, - .. - } => v1_rt::concat( - ", \"parent_enum\": ".to_string(), - crate::v1_compiler_dag_collect_support::json_quote( - parent_enum.clone(), - ), - ), + VarBindingKind::VariantValueBinding { parent_enum, .. } => { + v1_rt::concat( + ", \"parent_enum\": ".to_string(), + crate::v1_compiler_dag_collect_support::json_quote( + parent_enum.clone(), + ), + ) + } _ => "".to_string(), }, ), diff --git a/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs b/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs index 808c97852f0..27625c96a93 100644 --- a/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs +++ b/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs @@ -64,6 +64,10 @@ pub fn ct_nested_refinement_cast_fixture_closure_discrimination_test() -> String v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(" /// REPRESENTATION-IDENTICAL REFINEMENT AND BRAND CASTS, JUDGED BY RUSTC (gunbc#10266).\n".to_string(), " ///\n".to_string()), " /// The subject is `v1.compiler.emit` `cast_representation_identical`: a cast whose source and\n".to_string()), " /// target are ONE host carrier reached through transparent refinement, alias and brand edges\n".to_string()), " /// asks the target for no operation, so the emission must be the operand unchanged. The\n".to_string()), " /// fixture exercises six such casts across three aliases in BOTH directions, plus one genuine\n".to_string()), " /// numeric conversion that must still go through the target cast syntax.\n".to_string()), " ///\n".to_string()), " /// WHY THIS SUBJECT NEEDS RUSTC AND NOT A SUBSTRING. `test.claim`\n".to_string()), " /// `emitter_nested_refinement_cast_witness_test` asserts the ABSENCE of the fabricated\n".to_string()), " /// unsupported-cast text, and absence is all a spelling oracle can honestly assert here:\n".to_string()), " /// asserting the presence of a particular replacement would pin one rendering of \"the operand\n".to_string()), " /// unchanged\". Whether the replacement TYPE-CHECKS as the declared return is a meaning-level\n".to_string()), " /// question, and the never type is exactly what let the defective form pass a type check.\n".to_string()), " ///\n".to_string()), " /// THE RED ARM IS THE ROUTE'S OWN, so this pair proves the route can still fail using the\n".to_string()), " /// discrimination already adjudicated for it rather than a fresh unadjudicated arm.\n".to_string()), " ///\n".to_string()), " /// #[ignore] AND WHY, on the same terms as the two pairs beside it: this arm spawns cargo and\n".to_string()), " /// compiles two emitted crates, which is minutes rather than milliseconds. It is ENROLLED AND\n".to_string()), " /// OPT-IN -- `cargo test --release -p v1-compiler --lib\n".to_string()), " /// nested_refinement_cast_fixture_closure_discrimination -- --ignored`. An #[ignore] is a cost\n".to_string()), " /// decision and NOT a rung: nothing here may be cited as coverage that executes on the merge\n".to_string()), " /// path.\n".to_string()), " #[test]\n".to_string()), " #[ignore]\n".to_string()), " fn nested_refinement_cast_fixture_closure_discrimination() {\n".to_string()), " let probe_root = crate::cli_run::local_emit_compile_probe_root().unwrap();\n".to_string()), " let pair = crate::cli_run::run_nested_refinement_cast_discrimination(&probe_root);\n".to_string()), " for line in crate::cli_run::fixture_discrimination_report(&pair) {\n".to_string()), " eprintln!(\"nested-refinement-cast {}\", line);\n".to_string()), " }\n".to_string()), " assert!(\n".to_string()), " crate::cli_run::fixture_closure_reached_rustc(&pair.red),\n".to_string()), " \"the red arm never reached a rustc verdict, so nothing about the emitted bytes was measured: {}\",\n".to_string()), " crate::cli_run::fixture_closure_summary(&pair.red)\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " crate::cli_run::fixture_discrimination_passed(&pair),\n".to_string()), " \"the representation-identical cast control must COMPILE -- an unsupported-cast panic emitted for any of its six casts is a type error at the declared return -- and the route red must still be refused by rustc in its own emitted module with the claimed error class; control={} red={} attribution={:?} diagnostic={:?}\",\n".to_string()), " crate::cli_run::fixture_closure_summary(&pair.green),\n".to_string()), " crate::cli_run::fixture_closure_summary(&pair.red),\n".to_string()), " crate::cli_run::fixture_closure_attributed_line(&pair.red),\n".to_string()), " crate::cli_run::fixture_closure_attributed_diagnostic(&pair.red)\n".to_string()), " );\n".to_string()), " }\n\n".to_string()) } +pub fn ct_native_bool_variant_fixture_closure_discrimination_test() -> String { + v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(" /// THE ARMS OF A NATIVELY REALIZED COPRODUCT, JUDGED BY RUSTC, AND THE IDENTITY CONTROL BESIDE IT.\n".to_string(), " ///\n".to_string()), " /// The subject is `v1.compiler.emit_rust` `rust_native_variant_spelling`: an arm of a\n".to_string()), " /// coproduct that realizes natively (std.types Bool over Rust `bool`) is spelled as the\n".to_string()), " /// carrier value its declaration-keyed row names, in value, pattern and nested-pattern\n".to_string()), " /// position. The first pair's control is that fixture and must COMPILE; before the rows it\n".to_string()), " /// emitted `Bool::True` against a `bool` and rustc refused it. The second pair's control is a\n".to_string()), " /// module-local coproduct whose arms are spelled True/False, which has no row and must keep its own enum -- the\n".to_string()), " /// evidence that the rows are keyed on identity rather than on the spelling. Both reds are\n".to_string()), " /// the route's own adjudicated red.\n".to_string()), " ///\n".to_string()), " /// #[ignore] AND WHY, on the same terms as the pairs beside it: each pair spawns cargo and\n".to_string()), " /// compiles two emitted crates. It is RUNNABLE ON DEMAND -- `cargo test --release -p\n".to_string()), " /// v1-compiler --lib native_bool_variant_fixture_closure_discrimination -- --ignored`. No CI\n".to_string()), " /// path invokes it (gunbc.rung_drop rust_unit_tests_off_the_merge_path); the emitted-bytes\n".to_string()), " /// half that does run on the floor is test.claim.native_variant_realization_witness_test.\n".to_string()), " #[test]\n".to_string()), " #[ignore]\n".to_string()), " fn native_bool_variant_fixture_closure_discrimination() {\n".to_string()), " let probe_root = crate::cli_run::local_emit_compile_probe_root().unwrap();\n".to_string()), " for (label, pair) in [\n".to_string()), " (\"native-bool-variant\", crate::cli_run::run_native_bool_variant_discrimination(&probe_root)),\n".to_string()), " (\"local-true-false-coproduct\", crate::cli_run::run_local_true_false_coproduct_discrimination(&probe_root)),\n".to_string()), " ] {\n".to_string()), " for line in crate::cli_run::fixture_discrimination_report(&pair) {\n".to_string()), " eprintln!(\"{} {}\", label, line);\n".to_string()), " }\n".to_string()), " assert!(\n".to_string()), " crate::cli_run::fixture_closure_reached_rustc(&pair.red),\n".to_string()), " \"{}: the red arm never reached a rustc verdict: {}\",\n".to_string()), " label,\n".to_string()), " crate::cli_run::fixture_closure_summary(&pair.red)\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " crate::cli_run::fixture_discrimination_passed(&pair),\n".to_string()), " \"{}: the control must COMPILE and the route red must still be refused by rustc in its own module; control={} red={}\",\n".to_string()), " label,\n".to_string()), " crate::cli_run::fixture_closure_summary(&pair.green),\n".to_string()), " crate::cli_run::fixture_closure_summary(&pair.red)\n".to_string()), " );\n".to_string()), " }\n".to_string()), " }\n\n".to_string()) +} + pub fn ct_phantom_marker_identity_fixture_closure_discrimination_test() -> String { v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(" /// THE PHANTOM-MARKER POSITION PAIR, JUDGED BY RUSTC, THROUGH THE FIXTURE-CLOSURE ROUTE.\n".to_string(), " ///\n".to_string()), " /// NOT THE BROAD-VERSUS-POSITIONAL CLASSIFIER DISCRIMINATOR. That one's arms are two\n".to_string()), " /// COMPILER behaviours over ONE source, and no pair of fixture FILES can be those arms --\n".to_string()), " /// files vary the source and hold the compiler fixed. This does not discharge that ceiling\n".to_string()), " /// row, which stays at MeaningDiscriminatorExecutedNotEnrolled (codex review 60742).\n".to_string()), " ///\n".to_string()), " /// The subject is `v1.compiler.emit_rust` `rust_type_arg_identity_spelling`: a type argument's\n".to_string()), " /// Rust identity is decided from the declaration visible in the module, never from the\n".to_string()), " /// syntactic position that happened to render it. `test.claim`\n".to_string()), " /// `phantom_marker_type_argument_identity_witness` already adjudicates the SPELLING half of\n".to_string()), " /// that decision across every outer renderer and STAYS ENROLLED (DESIGN 4b(4): a climb deletes\n".to_string()), " /// lower-rung production machinery, never the evidence). This arm is the half that witness\n".to_string()), " /// declares it cannot reach -- `compile_dag_rust_emit_check` stops at emitted TEXT and never\n".to_string()), " /// invokes rustc, which is what pinned that class at SourceToEmittedTextHonestyOnly.\n".to_string()), " ///\n".to_string()), " /// WHAT THE TWO ARMS ARE, AND WHAT THEY DO NOT ISOLATE. Both declare the same coproduct\n".to_string()), " /// `Marker = Alpha | Beta`. The control puts `Alpha` and `Beta` in the RULED POSITION --\n".to_string()), " /// arguments of an applied type node -- where they become distinct zero-sized markers, and\n".to_string()), " /// its emitted crate COMPILES. The red puts `Alpha` in a NON-APPLIED position, a record\n".to_string()), " /// field, and returns that `Alpha`-typed field from a function declared to return `Marker`;\n".to_string()), " /// its emitted crate is REFUSED at that return. So a green here is not \"some crate compiled\"\n".to_string()), " /// and the red is not \"something in the tree is broken\".\n".to_string()), " ///\n".to_string()), " /// THE PAIR DOES NOT ISOLATE POSITION AS THE SOLE CAUSE, and an earlier revision of this\n".to_string()), " /// description claimed it did (native comment review 5120541804). The arms also differ in\n".to_string()), " /// their RETURN CONTRACT -- the control returns an `Int` read through a wrapper -- and the\n".to_string()), " /// measured E0308 lands AT the return, so the return contract is load-bearing for the refusal\n".to_string()), " /// rather than incidental. What the pair characterizes is two CONCRETE CONSTRUCTIONS, not a\n".to_string()), " /// single-variable experiment over position.\n".to_string()), " ///\n".to_string()), " /// THE RED IS A KNOWN HOLE, NOT A WALL WORKING, and it is named as one so nobody reads its red\n".to_string()), " /// as coverage. It is `gunbc.recurring_failure_mode` `accepted_source_emits_uncompilable_target`\n".to_string()), " /// at that row's own filed FIRST instance, which the row records was never committed to this\n".to_string()), " /// repository as a runnable file. It is committed here as one. When the wall climbs -- type\n".to_string()), " /// position resolution consulting the TYPE namespace alone -- the arm flips to SourceRefused\n".to_string()), " /// and is KEPT; what changes is this pair's expectation, not the fixture's existence.\n".to_string()), " ///\n".to_string()), " /// WHAT RUSTC ACTUALLY SAID, AND WHY IT IS RECORDED HERE. The emitted red module carries BOTH\n".to_string()), " /// an `Alpha` type and a `Marker::Alpha` variant: the field annotation binds the former, the\n".to_string()), " /// declared return wants the latter, and the refusal lands at the parent boundary as E0308,\n".to_string()), " /// `expected Marker, found Alpha`. E0573 was predicted from the ceiling row and did NOT\n".to_string()), " /// reproduce -- both arms declare their markers LOCALLY, so neither exercises the\n".to_string()), " /// imported-marker construction where those classifiers diverge, and the prediction was\n".to_string()), " /// mis-scoped from the start. The expectation is the route's adjudicated class. See\n".to_string()), " /// `run_phantom_marker_identity_discrimination` for the full diagnostic and for what is\n".to_string()), " /// deliberately not claimed from one construction.\n".to_string()), " ///\n".to_string()), " /// #[ignore] AND WHY, on the same terms as the three pairs beside it: this arm spawns cargo\n".to_string()), " /// and compiles two emitted crates, which is minutes rather than milliseconds. It is ENROLLED\n".to_string()), " /// AND OPT-IN -- `cargo test --release -p v1-compiler --lib\n".to_string()), " /// phantom_marker_identity_fixture_closure_discrimination -- --ignored`. An #[ignore] is a\n".to_string()), " /// cost decision and NOT a rung: nothing here may be cited as coverage that executes on the\n".to_string()), " /// merge path, and the phantom-marker ceiling carrier may not be flipped to\n".to_string()), " /// MeaningDiscriminatorEnrolled on the strength of it.\n".to_string()), " #[test]\n".to_string()), " #[ignore]\n".to_string()), " fn phantom_marker_identity_fixture_closure_discrimination() {\n".to_string()), " let probe_root = crate::cli_run::local_emit_compile_probe_root().unwrap();\n".to_string()), " let pair = crate::cli_run::run_phantom_marker_identity_discrimination(&probe_root);\n".to_string()), " for line in crate::cli_run::fixture_discrimination_report(&pair) {\n".to_string()), " eprintln!(\"phantom-marker-identity {}\", line);\n".to_string()), " }\n".to_string()), " assert!(\n".to_string()), " crate::cli_run::fixture_closure_reached_rustc(&pair.red),\n".to_string()), " \"the red arm never reached a rustc verdict, so nothing about the emitted bytes was measured: {}\",\n".to_string()), " crate::cli_run::fixture_closure_summary(&pair.red)\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " crate::cli_run::fixture_discrimination_passed(&pair),\n".to_string()), " \"the applied-marker fixture must COMPILE, and the non-applied-field-plus-parent-return fixture must reach rustc and be refused in its own emitted module with the attributed E0308 this pair claims; control={} red={} attribution={:?} diagnostic={:?}\",\n".to_string()), " crate::cli_run::fixture_closure_summary(&pair.green),\n".to_string()), " crate::cli_run::fixture_closure_summary(&pair.red),\n".to_string()), " crate::cli_run::fixture_closure_attributed_line(&pair.red),\n".to_string()), " crate::cli_run::fixture_closure_attributed_diagnostic(&pair.red)\n".to_string()), " );\n".to_string()), " }\n\n".to_string()) } @@ -418,5 +422,5 @@ pub fn ct_test_reference_orphan_row_test() -> String { } pub fn compiler_tests_source() -> String { - v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(ct_module_header(), ct_workspace_helpers()), ct_file_discovery_helpers()), ct_source_builders()), ct_tokenizer_tests()), ct_parse_tests()), ct_test_marker_item_kind_test()), ct_test_reference_wall_test()), ct_test_reference_import_all_test()), ct_test_reference_orphan_row_test()), ct_tco_tail_call_assigns_every_loop_slot_test()), ct_pipeline_test()), ct_entry_point_absent_refusal_test()), ct_import_lines_follow_resolved_binding_identity_test()), ct_generic_optional_over_a_type_application_keeps_the_optional_test()), ct_pub_use_crate_lines_two_emission_byte_identity_test()), ct_overlapping_use_line_dedupe_permutation_test()), ct_fixture_closure_rustc_discrimination_test()), ct_evaluation_budget_consequence_falsifier_test()), ct_function_value_adapter_fixture_closure_discrimination_test()), ct_nested_refinement_cast_fixture_closure_discrimination_test()), ct_phantom_marker_identity_fixture_closure_discrimination_test()), ct_empty_map_turbofish_fixture_closure_discrimination_test()), ct_argv_word_list_splice_fixture_closure_discrimination_test()), ct_append_concat_form_fixture_closure_discrimination_test()), ct_shell_projection_arity_fixture_closure_discrimination_test()), ct_unlisted_import_use_witness_test()), ct_call_shape_wall_witness_test()), ct_call_deficit_red_witness_test()), ct_call_shape_duplicate_wall_witness_test()), ct_function_value_named_application_controls_witness_test()), ct_effect_summary_refusals_carry_their_call_site_test()), ct_function_value_field_method_known_hole_probe_test()), ct_shell_service_output_projection_test()), ct_shell_service_unmodeled_output_key_refusal_test()), ct_shell_service_exit_error_arm_boxed_test()), ct_function_value_adapter_bound_alignment_control_test()), ct_rendered_leaf_occurrence_identity_test()), ct_rendered_leaf_occurrence_identity_pipeline_test()), ct_method_existence_wall_witness_test()), ct_declared_type_conformance_witness_test()), ct_direct_call_formal_authority_carrier_test()), ct_sole_constructor_test()), ct_constructor_call_admission_test()), ct_constructor_call_admission_same_module_sibling_test()), ct_constructor_call_admission_function_value_test()), ct_constructor_call_admission_zero_arity_test()), ct_constructor_call_admission_shadowing_test()), ct_constructor_call_admission_qualified_caller_test()), ct_sole_constructor_fieldless_witness_test()), ct_contracts_sidecar_witness_test()), ct_self_parse_all_test()), ct_self_resolve_test()), ct_self_compile_test()), ct_self_compile_cargo_check_test()), ct_type_size_test()), ct_coercion_tests()), ct_profile_helpers()), ct_profile_self_compile_test()), ct_profile_full_pipeline_test()), ct_profile_reconcile_test()), ct_module_footer()) + v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(ct_module_header(), ct_workspace_helpers()), ct_file_discovery_helpers()), ct_source_builders()), ct_tokenizer_tests()), ct_parse_tests()), ct_test_marker_item_kind_test()), ct_test_reference_wall_test()), ct_test_reference_import_all_test()), ct_test_reference_orphan_row_test()), ct_tco_tail_call_assigns_every_loop_slot_test()), ct_pipeline_test()), ct_entry_point_absent_refusal_test()), ct_import_lines_follow_resolved_binding_identity_test()), ct_generic_optional_over_a_type_application_keeps_the_optional_test()), ct_pub_use_crate_lines_two_emission_byte_identity_test()), ct_overlapping_use_line_dedupe_permutation_test()), ct_fixture_closure_rustc_discrimination_test()), ct_evaluation_budget_consequence_falsifier_test()), ct_function_value_adapter_fixture_closure_discrimination_test()), ct_nested_refinement_cast_fixture_closure_discrimination_test()), ct_native_bool_variant_fixture_closure_discrimination_test()), ct_phantom_marker_identity_fixture_closure_discrimination_test()), ct_empty_map_turbofish_fixture_closure_discrimination_test()), ct_argv_word_list_splice_fixture_closure_discrimination_test()), ct_append_concat_form_fixture_closure_discrimination_test()), ct_shell_projection_arity_fixture_closure_discrimination_test()), ct_unlisted_import_use_witness_test()), ct_call_shape_wall_witness_test()), ct_call_deficit_red_witness_test()), ct_call_shape_duplicate_wall_witness_test()), ct_function_value_named_application_controls_witness_test()), ct_effect_summary_refusals_carry_their_call_site_test()), ct_function_value_field_method_known_hole_probe_test()), ct_shell_service_output_projection_test()), ct_shell_service_unmodeled_output_key_refusal_test()), ct_shell_service_exit_error_arm_boxed_test()), ct_function_value_adapter_bound_alignment_control_test()), ct_rendered_leaf_occurrence_identity_test()), ct_rendered_leaf_occurrence_identity_pipeline_test()), ct_method_existence_wall_witness_test()), ct_declared_type_conformance_witness_test()), ct_direct_call_formal_authority_carrier_test()), ct_sole_constructor_test()), ct_constructor_call_admission_test()), ct_constructor_call_admission_same_module_sibling_test()), ct_constructor_call_admission_function_value_test()), ct_constructor_call_admission_zero_arity_test()), ct_constructor_call_admission_shadowing_test()), ct_constructor_call_admission_qualified_caller_test()), ct_sole_constructor_fieldless_witness_test()), ct_contracts_sidecar_witness_test()), ct_self_parse_all_test()), ct_self_resolve_test()), ct_self_compile_test()), ct_self_compile_cargo_check_test()), ct_type_size_test()), ct_coercion_tests()), ct_profile_helpers()), ct_profile_self_compile_test()), ct_profile_full_pipeline_test()), ct_profile_reconcile_test()), ct_module_footer()) } diff --git a/src/v1/stage0/src/v1_compiler_emit.rs b/src/v1/stage0/src/v1_compiler_emit.rs index fa107e671cb..4e688234cee 100644 --- a/src/v1/stage0/src/v1_compiler_emit.rs +++ b/src/v1/stage0/src/v1_compiler_emit.rs @@ -361,10 +361,7 @@ pub fn emit_simple_expr( binding_kind: bk, .. } => match bk.clone().as_deref().cloned() { Some(VarBindingKind::MatchBoundBinding) => false, - Some(VarBindingKind::VariantValueBinding { - parent_enum: _, - .. - }) => false, + Some(VarBindingKind::VariantValueBinding { .. }) => false, _ => true, }, _ => false, diff --git a/src/v1/stage0/src/v1_compiler_emit_rust.rs b/src/v1/stage0/src/v1_compiler_emit_rust.rs index a5c5a21c1a4..b0401ada791 100644 --- a/src/v1/stage0/src/v1_compiler_emit_rust.rs +++ b/src/v1/stage0/src/v1_compiler_emit_rust.rs @@ -115,10 +115,20 @@ use crate::std_syntax::AlgebraFieldKind::*; use crate::std_syntax::BinOp::*; use crate::std_syntax::LiteralValue::*; pub use crate::std_syntax::{AlgebraFieldKind, BinOp, LiteralValue}; -pub use crate::std_target_representation::ExactBindingResolution; +pub use crate::std_target_representation::variant_value_realization_refusal_message; use crate::std_target_representation::ExactBindingResolution::{ ExactBindingAbsent, ExactBindingAmbiguous, ExactSourceIdentityUnavailable, ResolvedExactBinding, }; +use crate::std_target_representation::VariantParentIdentity::{ + VariantParentBeforeInference, VariantParentUnrecovered, +}; +use crate::std_target_representation::VariantValueRealization::{ + VariantParentIdentityUnavailable, VariantRealizesAsTargetValue, VariantRealizesStructurally, + VariantTargetValueAmbiguous, VariantTargetValueUnbound, +}; +pub use crate::std_target_representation::{ + ExactBindingResolution, VariantParentIdentity, VariantValueRealization, +}; pub use crate::std_types::SourceSpan; pub use crate::std_types::{container_template_algebra, is_container_type, is_kernel_type}; use crate::v1_compiler_artifact::RenderTarget::Rust; @@ -131,7 +141,8 @@ pub use crate::v1_compiler_closure_stub_v2_std_text_rust::closure_stub_v2_std_te pub use crate::v1_compiler_coercion::{ coerce_primitive_type, declaration_realization, declaration_realizes_natively_on_rust, is_copy, provenance_declares_structurally, realization_host_numeric_spelling, - realization_is_host_numeric, realized_checkpoint, rust_lookup_exact_binding, target_callable, + realization_is_host_numeric, realized_checkpoint, rust_lookup_exact_binding, + rust_variant_arm_is_bound_somewhere, rust_variant_value_realization, target_callable, type_realization_decision, type_reference_realization, }; pub use crate::v1_compiler_compiler_tests_rust::compiler_tests_source; @@ -20953,17 +20964,24 @@ pub fn emit_pattern( name: n, parent_enum, field_bindings: fbs, + parent_identity: identity, .. - } => emit_variant_pattern( - n.clone(), - parent_enum.clone(), - fbs.clone(), - path_prefix.clone(), - shared_types.clone(), - scrut_type.clone(), - source_indices.clone(), - emit_info.clone(), - ), + } => match rust_native_variant_spelling( + identity.clone(), + crate::v1_std_core::qualified_last_segment(n.clone()), + ) { + Some(native) => native.clone(), + std::option::Option::None => emit_variant_pattern( + n.clone(), + parent_enum.clone(), + fbs.clone(), + path_prefix.clone(), + shared_types.clone(), + scrut_type.clone(), + source_indices.clone(), + emit_info.clone(), + ), + }, MatchPattern::Wildcard => "_".to_string(), } } @@ -21853,18 +21871,25 @@ pub fn emit_pattern_rc_aware( name: n, parent_enum, field_bindings: fbs, + parent_identity: identity, .. - } => emit_variant_pattern_rc_aware( - n.clone(), - parent_enum.clone(), - fbs.clone(), - path_prefix.clone(), - rc_analysis.clone(), - shared_types.clone(), - scrut_type.clone(), - source_indices.clone(), - emit_info.clone(), - ), + } => match rust_native_variant_spelling( + identity.clone(), + crate::v1_std_core::qualified_last_segment(n.clone()), + ) { + Some(native) => native.clone(), + std::option::Option::None => emit_variant_pattern_rc_aware( + n.clone(), + parent_enum.clone(), + fbs.clone(), + path_prefix.clone(), + rc_analysis.clone(), + shared_types.clone(), + scrut_type.clone(), + source_indices.clone(), + emit_info.clone(), + ), + }, MatchPattern::Wildcard => "_".to_string(), } } @@ -22608,14 +22633,80 @@ pub fn is_simple_type_node( is_rust_value_type(n.clone(), source_indices.clone()) } -pub fn variant_parent_from_binding_kind( +pub fn rust_native_variant_spelling( + parent: Rc, + leaf_name: String, +) -> Option { + match (*parent.clone()).clone() { + VariantParentIdentity::VariantParentBeforeInference => Some(emit_rust_compile_error_expr(v1_rt::concat(v1_rt::concat("variant realization: `".to_string(), leaf_name.clone()), "` reached emission without inference having read which coproduct it belongs to (VariantParentBeforeInference); an unread occurrence is refused rather than rendered as either the native value or its enum path".to_string()))), + _ => rust_native_variant_spelling_of_read(parent.clone(), leaf_name.clone()), +} +} + +pub fn rust_native_variant_spelling_of_read( + parent: Rc, + leaf_name: String, +) -> Option { + { + let r = crate::v1_compiler_coercion::rust_variant_value_realization( + parent.clone(), + leaf_name.clone(), + ); + match (*r.clone()).clone() { + VariantValueRealization::VariantRealizesAsTargetValue { + value_spelling: s, .. + } => Some(s.clone()), + VariantValueRealization::VariantRealizesStructurally => std::option::Option::None, + VariantValueRealization::VariantParentIdentityUnavailable { cause: _, .. } => { + if crate::v1_compiler_coercion::rust_variant_arm_is_bound_somewhere( + leaf_name.clone(), + ) { + match crate::std_target_representation::variant_value_realization_refusal_message(r.clone()) { + Some(m) => Some(emit_rust_compile_error_expr(m.clone())), + std::option::Option::None => std::option::Option::None, +} + } else { + std::option::Option::None + } + } + VariantValueRealization::VariantTargetValueUnbound { .. } => { + match crate::std_target_representation::variant_value_realization_refusal_message( + r.clone(), + ) { + Some(m) => Some(emit_rust_compile_error_expr(m.clone())), + std::option::Option::None => std::option::Option::None, + } + } + VariantValueRealization::VariantTargetValueAmbiguous { .. } => { + match crate::std_target_representation::variant_value_realization_refusal_message( + r.clone(), + ) { + Some(m) => Some(emit_rust_compile_error_expr(m.clone())), + std::option::Option::None => std::option::Option::None, + } + } + } + } +} + +pub fn rust_native_variant_spelling_of_binding( binding_kind: Option>, + leaf_name: String, ) -> Option { match binding_kind.clone().as_deref().cloned() { Some(VarBindingKind::VariantValueBinding { - parent_enum: parent_enum, + parent_identity: identity, .. - }) => Some(parent_enum.clone()), + }) => rust_native_variant_spelling(identity.clone(), leaf_name.clone()), + _ => std::option::Option::None, + } +} + +pub fn variant_parent_from_binding_kind( + binding_kind: Option>, +) -> Option { + match binding_kind.clone().as_deref().cloned() { + Some(VarBindingKind::VariantValueBinding { parent_enum, .. }) => Some(parent_enum.clone()), _ => std::option::Option::None, } } @@ -22872,112 +22963,128 @@ pub fn emit_var_ref( { crate::v1_compiler_emit::emit_keyword(leaf_name.clone(), RenderTarget::Rust) } else { + if (rust_native_variant_spelling_of_binding( + binding_kind.clone(), + leaf_name.clone(), + ) != std::option::Option::None) { - let moves_by_value = - v1_rt::set_contains(&emit_info.movable.clone(), resolved_name.clone()); - let sharing = - crate::v1_compiler_emit_core_support::language_spec(RenderTarget::Rust) - .sharing - .clone(); - let ref_str = match variant_parent.clone() { - Some(enum_name) => { - let body = if freemonoid_empty_from_variant_parent( - leaf_name.clone(), - enum_name.clone(), - ) { - emit_freemonoid_empty_variant_body() - } else { - if (is_optional_variant_name(leaf_name.clone()) - && is_optional_like_parent_name(enum_name.clone())) - { - rust_optional_variant_spelling(leaf_name.clone()) + match rust_native_variant_spelling_of_binding( + binding_kind.clone(), + leaf_name.clone(), + ) { + Some(s) => s.clone(), + std::option::Option::None => "".to_string(), + } + } else { + { + let moves_by_value = + v1_rt::set_contains(&emit_info.movable.clone(), resolved_name.clone()); + let sharing = + crate::v1_compiler_emit_core_support::language_spec(RenderTarget::Rust) + .sharing + .clone(); + let ref_str = match variant_parent.clone() { + Some(enum_name) => { + let body = if freemonoid_empty_from_variant_parent( + leaf_name.clone(), + enum_name.clone(), + ) { + emit_freemonoid_empty_variant_body() } else { - rust_variant_path(enum_name.clone(), leaf_name.clone()) + if (is_optional_variant_name(leaf_name.clone()) + && is_optional_like_parent_name(enum_name.clone())) + { + rust_optional_variant_spelling(leaf_name.clone()) + } else { + rust_variant_path(enum_name.clone(), leaf_name.clone()) + } + }; + if variant_ref_self_wraps( + leaf_name.clone(), + enum_name.clone(), + shared_types.clone(), + ) { + rust_shared_wrap_ctor(body.clone()) + } else { + body.clone() } - }; - if variant_ref_self_wraps( - leaf_name.clone(), - enum_name.clone(), - shared_types.clone(), - ) { - rust_shared_wrap_ctor(body.clone()) - } else { - body.clone() } - } - std::option::Option::None => match (*lookup_item_for_value_ref( - resolved_name.clone(), - module_name.clone(), - registry.clone(), - emit_info.clone(), - )) - .clone() - { - ItemLookup::ItemLeafAmbiguous { - leaf: ambiguous_leaf, - .. - } => ambiguous_leaf_refusal(ambiguous_leaf.clone()), - ItemLookup::ItemFound { info: info, .. } => { - let is_data = (info.kind.clone() == ItemKind::DataItem); - if is_data.clone() { - v1_rt::concat( - emit_value_ref_ident( - name.clone(), - module_name.clone(), - registry.clone(), - emit_info.clone(), - ), - "()".to_string(), - ) - } else { - { - let is_function_value = - match binding_kind.clone().as_deref().cloned() { - Some(VarBindingKind::FunctionValueBinding) => true, - _ => false, - }; - let ident = emit_value_ref_ident( - resolved_name.clone(), - module_name.clone(), - registry.clone(), - emit_info.clone(), - ); - let ident_str = if is_function_value.clone() { - ident.clone() - } else { - if moves_by_value.clone() { + std::option::Option::None => match (*lookup_item_for_value_ref( + resolved_name.clone(), + module_name.clone(), + registry.clone(), + emit_info.clone(), + )) + .clone() + { + ItemLookup::ItemLeafAmbiguous { + leaf: ambiguous_leaf, + .. + } => ambiguous_leaf_refusal(ambiguous_leaf.clone()), + ItemLookup::ItemFound { info: info, .. } => { + let is_data = (info.kind.clone() == ItemKind::DataItem); + if is_data.clone() { + v1_rt::concat( + emit_value_ref_ident( + name.clone(), + module_name.clone(), + registry.clone(), + emit_info.clone(), + ), + "()".to_string(), + ) + } else { + { + let is_function_value = + match binding_kind.clone().as_deref().cloned() { + Some(VarBindingKind::FunctionValueBinding) => { + true + } + _ => false, + }; + let ident = emit_value_ref_ident( + resolved_name.clone(), + module_name.clone(), + registry.clone(), + emit_info.clone(), + ); + let ident_str = if is_function_value.clone() { ident.clone() } else { - match resolved_type.clone() { + if moves_by_value.clone() { + ident.clone() + } else { + match resolved_type.clone() { Some(_) => crate::v1_compiler_emit_core_support::apply_type_template1(sharing.clone_value.clone(), ident.clone()), _ => ident.clone(), } - } - }; - ident_str.clone() + } + }; + ident_str.clone() + } } } - } - ItemLookup::ItemNotFound => { - let ident = emit_value_ref_ident( - resolved_name.clone(), - module_name.clone(), - registry.clone(), - emit_info.clone(), - ); - let ident_str = if moves_by_value.clone() { - ident.clone() - } else { - match resolved_type.clone() { + ItemLookup::ItemNotFound => { + let ident = emit_value_ref_ident( + resolved_name.clone(), + module_name.clone(), + registry.clone(), + emit_info.clone(), + ); + let ident_str = if moves_by_value.clone() { + ident.clone() + } else { + match resolved_type.clone() { Some(_) => crate::v1_compiler_emit_core_support::apply_type_template1(sharing.clone_value.clone(), ident.clone()), _ => ident.clone(), } - }; - ident_str.clone() - } - }, - }; - ref_str + }; + ident_str.clone() + } + }, + }; + ref_str + } } } } @@ -23019,80 +23126,91 @@ pub fn emit_typed_expr_base( { crate::v1_compiler_emit::emit_keyword(leaf_name.clone(), RenderTarget::Rust) } else { - match variant_parent.clone() { - Some(enum_name) => { - if freemonoid_empty_from_variant_parent( - leaf_name.clone(), - enum_name.clone(), - ) { - emit_freemonoid_empty_rc_value() - } else { - { - let qualified = - if (is_optional_variant_name(leaf_name.clone()) - && is_optional_like_parent_name(enum_name.clone())) + match rust_native_variant_spelling_of_binding( + binding_kind.clone(), + leaf_name.clone(), + ) { + Some(native) => native.clone(), + std::option::Option::None => match variant_parent.clone() { + Some(enum_name) => { + if freemonoid_empty_from_variant_parent( + leaf_name.clone(), + enum_name.clone(), + ) { + emit_freemonoid_empty_rc_value() + } else { + { + let qualified = + if (is_optional_variant_name(leaf_name.clone()) + && is_optional_like_parent_name( + enum_name.clone(), + )) + { + rust_optional_variant_spelling( + leaf_name.clone(), + ) + } else { + rust_variant_path( + enum_name.clone(), + leaf_name.clone(), + ) + }; + if v1_rt::set_contains(&shared_types, enum_name.clone()) { - rust_optional_variant_spelling(leaf_name.clone()) + rust_shared_wrap_ctor(qualified.clone()) } else { - rust_variant_path( - enum_name.clone(), - leaf_name.clone(), - ) - }; - if v1_rt::set_contains(&shared_types, enum_name.clone()) { - rust_shared_wrap_ctor(qualified.clone()) - } else { - qualified.clone() + qualified.clone() + } } } } - } - std::option::Option::None => { - let resolved_name = value_ref_normalize_self_module( - n.clone(), - scope.module_name.clone(), - ); - match (*lookup_item_for_value_ref( - resolved_name.clone(), - scope.module_name.clone(), - registry.clone(), - emit_info.clone(), - )) - .clone() - { - ItemLookup::ItemLeafAmbiguous { - leaf: ambiguous_leaf, - .. - } => ambiguous_leaf_refusal(ambiguous_leaf.clone()), - ItemLookup::ItemFound { info: info, .. } => { - let is_data = (info.kind.clone() == ItemKind::DataItem); - if is_data.clone() { - v1_rt::concat( + std::option::Option::None => { + let resolved_name = value_ref_normalize_self_module( + n.clone(), + scope.module_name.clone(), + ); + match (*lookup_item_for_value_ref( + resolved_name.clone(), + scope.module_name.clone(), + registry.clone(), + emit_info.clone(), + )) + .clone() + { + ItemLookup::ItemLeafAmbiguous { + leaf: ambiguous_leaf, + .. + } => ambiguous_leaf_refusal(ambiguous_leaf.clone()), + ItemLookup::ItemFound { info: info, .. } => { + let is_data = (info.kind.clone() == ItemKind::DataItem); + if is_data.clone() { + v1_rt::concat( + emit_value_ref_ident( + n.clone(), + scope.module_name.clone(), + registry.clone(), + emit_info.clone(), + ), + "()".to_string(), + ) + } else { emit_value_ref_ident( - n.clone(), + resolved_name.clone(), scope.module_name.clone(), registry.clone(), emit_info.clone(), - ), - "()".to_string(), - ) - } else { - emit_value_ref_ident( - resolved_name.clone(), - scope.module_name.clone(), - registry.clone(), - emit_info.clone(), - ) + ) + } } + ItemLookup::ItemNotFound => emit_value_ref_ident( + resolved_name.clone(), + scope.module_name.clone(), + registry.clone(), + emit_info.clone(), + ), } - ItemLookup::ItemNotFound => emit_value_ref_ident( - resolved_name.clone(), - scope.module_name.clone(), - registry.clone(), - emit_info.clone(), - ), } - } + }, } } } diff --git a/src/v1/stage0/src/v1_compiler_infer.rs b/src/v1/stage0/src/v1_compiler_infer.rs index 7ae45e5660b..ec8c8dcd1d9 100644 --- a/src/v1/stage0/src/v1_compiler_infer.rs +++ b/src/v1/stage0/src/v1_compiler_infer.rs @@ -52,6 +52,11 @@ pub use crate::std_induction::{InductiveField, RecursionShape, SubValueRelation} use crate::std_interface_summary::ExportKind::{ExportData, ExportFn, ExportService, ExportType}; pub use crate::std_interface_summary::{interface_summary_rollup, signature_contract}; pub use crate::std_interface_summary::{ExportEntry, ExportKind, InterfaceSummary}; +pub use crate::std_kernel_type_name::kernel_type_name; +pub use crate::std_kernel_type_name::KernelTypeNameAdmission; +use crate::std_kernel_type_name::KernelTypeNameAdmission::{ + KernelTypeNameAdmitted, NotAKernelTypeName, +}; use crate::std_literal_elaboration::LiteralElaborationOutcome::{ DirectLiteral, LiteralElaborationRefused, ViaHomomorphism, }; @@ -74,6 +79,13 @@ use crate::std_syntax::BinOp::{ use crate::std_syntax::LiteralValue::LitStr; use crate::std_syntax::LiteralValue::{LitBool, LitFloat, LitInt, LitNull}; pub use crate::std_syntax::{BinOp, LiteralValue}; +use crate::std_target_representation::VariantParentIdentity::{ + VariantParentIdentified, VariantParentUnrecovered, +}; +use crate::std_target_representation::VariantParentKey::{ + VariantParentDeclaration, VariantParentKernelType, +}; +pub use crate::std_target_representation::{VariantParentIdentity, VariantParentKey}; pub use crate::std_termination::PositiveDescentAmount; use crate::std_termination::PositiveDescentAmount::OneStep; pub use crate::std_termination::{ @@ -288,7 +300,7 @@ pub use crate::v1_std_core::{ admit_callers_entry_coords, admit_callers_entry_uninterpretable_spans, arg_name_at, arg_value, arm_body, arm_guard, arm_pattern, authored_name_at, binop_left, binop_right, bool_type, build_newline_index, call_semantics_target, callable_identity, cast_expr, cast_target, - container_expected_arity, decl_ref_coords_label, default_ident_span, + container_expected_arity, decl_ref_coords_label, declaration_provenance_of, default_ident_span, diagnostic_frontier_occurrence_key, diagnostic_to_span, empty_intern_table, error_type, expr_call_func_at, expr_has_non_tail_self_call, expr_has_self_call, expr_literal_int_optional, expr_literal_string_optional, expr_method_name_at, expr_var_name_at, field_access_base, @@ -1137,6 +1149,39 @@ pub fn variant_reference_inferred_node( } } +pub fn variant_parent_identity_of( + owner: Option>, + scope: Rc, +) -> Rc { + match owner.clone() { + std::option::Option::None => Rc::new(VariantParentIdentity::VariantParentUnrecovered { + cause: "no owning coproduct declaration was found for the variant".to_string(), +}), + Some(o) => match crate::v1_compiler_infer_env::type_reference_declaration(o.clone(), scope.type_env.clone().source_indices.clone(), scope.type_env.clone()) { + Some(od) => Rc::new(VariantParentIdentity::VariantParentIdentified { + key: Rc::new(VariantParentKey::VariantParentDeclaration { + declaration: od.declaration.clone(), +}), +}), + std::option::Option::None => match (*crate::v1_std_core::declaration_provenance_of(o.clone())).clone() { + TypeDeclarationProvenance::KernelMinted { minted_name: m, .. } => match (*crate::std_kernel_type_name::kernel_type_name(m.clone())).clone() { + KernelTypeNameAdmission::KernelTypeNameAdmitted { kernel_name: k, .. } => Rc::new(VariantParentIdentity::VariantParentIdentified { + key: Rc::new(VariantParentKey::VariantParentKernelType { + kernel_name: k.clone(), +}), +}), + KernelTypeNameAdmission::NotAKernelTypeName { name: _, .. } => Rc::new(VariantParentIdentity::VariantParentUnrecovered { + cause: "the owning coproduct is a kernel mint whose name is not a kernel type".to_string(), +}), +}, + _ => Rc::new(VariantParentIdentity::VariantParentUnrecovered { + cause: "the owning coproduct is neither an identified corpus declaration nor a kernel type (alias or unresolved)".to_string(), +}), +}, +}, +} +} + pub fn expected_decided_variant_value( texpr: Rc, name: String, @@ -1156,6 +1201,10 @@ pub fn expected_decided_variant_value( Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new(VarBindingKind::VariantValueBinding { parent_enum: decided_name.clone(), + parent_identity: variant_parent_identity_of( + Some(decided.clone()), + scope.clone(), + ), })), }), Rc::new(vec![]), @@ -1476,6 +1525,10 @@ pub fn infer_var_binding_kind(scope: Rc, name: String) -> Rc Rc::new(VarBindingKind::VariantValueBinding { parent_enum: parent_enum.clone(), + parent_identity: variant_parent_identity_of( + variant_owner_node(scope.clone(), name.clone()), + scope.clone(), + ), }), std::option::Option::None => match v1_rt::map_get(&scope.locals.clone(), name.clone()) { Some(binding) => { @@ -10122,6 +10175,12 @@ pub fn resolve_pattern_subject( } } +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct PatternParentReading { + pub parent_enum: Option, + pub identity: Rc, +} + pub fn annotate_pattern_parent_enums( pattern: Rc, scrutinee_subject: Rc, @@ -10137,7 +10196,7 @@ pub fn annotate_pattern_parent_enums( } => { let resolved_scrut = resolve_pattern_subject(scope.clone(), scrutinee_subject.clone()); - let inferred_parent = match (*resolved_scrut.clone()).clone() { + let parent_reading = match (*resolved_scrut.clone()).clone() { PatternSubject::PatternResolved { node: resolved_scrut_node, .. @@ -10163,26 +10222,61 @@ pub fn annotate_pattern_parent_enums( && ((variant_name.clone() == "Present".to_string()) || (variant_name.clone() == "Absent".to_string()))) { - Some("Optional".to_string()) + Rc::new(PatternParentReading { + parent_enum: Some("Optional".to_string()), + identity: Rc::new(VariantParentIdentity::VariantParentUnrecovered { + cause: "the arm belongs to the optional wrapper, not to the scrutinee's declared coproduct".to_string(), +}), +}) } else { if witness_container_subject.clone() { - Some("Witness".to_string()) + Rc::new(PatternParentReading { + parent_enum: Some("Witness".to_string()), + identity: Rc::new(VariantParentIdentity::VariantParentUnrecovered { + cause: "the arm belongs to the witness wrapper, not to the scrutinee's declared coproduct".to_string(), +}), +}) } else { { let is_coproduct = (resolved_scrut_node.connective.clone() == Connective::Disj); if is_coproduct.clone() { - Some(scrutinee_name.clone()) + Rc::new(PatternParentReading { + parent_enum: Some(scrutinee_name.clone()), + identity: variant_parent_identity_of( + Some(resolved_scrut_node.clone()), + scope.clone(), + ), + }) } else { - std::option::Option::None + Rc::new(PatternParentReading { + parent_enum: std::option::Option::None, + identity: Rc::new(VariantParentIdentity::VariantParentUnrecovered { + cause: "the scrutinee's resolved type is not a coproduct declaration".to_string(), +}), +}) } } } } } - PatternSubject::PatternDynamic { span: _, .. } => std::option::Option::None, - PatternSubject::PatternLookupBlocked => std::option::Option::None, + PatternSubject::PatternDynamic { span: _, .. } => { + Rc::new(PatternParentReading { + parent_enum: std::option::Option::None, + identity: Rc::new(VariantParentIdentity::VariantParentUnrecovered { + cause: "the scrutinee's type is dynamic".to_string(), + }), + }) + } + PatternSubject::PatternLookupBlocked => Rc::new(PatternParentReading { + parent_enum: std::option::Option::None, + identity: Rc::new(VariantParentIdentity::VariantParentUnrecovered { + cause: "the scrutinee's type lookup was blocked".to_string(), + }), + }), }; + let inferred_parent = parent_reading.parent_enum.clone(); + let parent_identity = parent_reading.identity.clone(); let annotated_variant_name = variant_name.clone(); let variant_lookup = crate::v1_compiler_infer_patterns::lookup_variant_in_type( resolved_scrut.clone(), @@ -10237,11 +10331,13 @@ pub fn annotate_pattern_parent_enums( name: annotated_variant_name.clone(), parent_enum: Some(parent_name.clone()), field_bindings: annotated_bindings.clone(), + parent_identity: parent_identity.clone(), }), std::option::Option::None => Rc::new(MatchPattern::VariantPattern { name: variant_name.clone(), parent_enum: std::option::Option::None, field_bindings: annotated_bindings.clone(), + parent_identity: parent_identity.clone(), }), } } @@ -11538,6 +11634,7 @@ pub fn unfold_peano_image( succ: String, prev_field: String, parent: String, + parent_identity: Rc, destination_type: Rc, span: Rc, ) -> Rc { @@ -11548,6 +11645,7 @@ pub fn unfold_peano_image( Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new(VarBindingKind::VariantValueBinding { parent_enum: parent.clone(), + parent_identity: parent_identity.clone(), })), }), Rc::new(vec![]), @@ -11562,6 +11660,7 @@ pub fn unfold_peano_image( succ.clone(), prev_field.clone(), parent.clone(), + parent_identity.clone(), destination_type.clone(), span.clone(), ); @@ -11632,7 +11731,11 @@ pub fn unfold_literal_image( _ => crate::v1_std_core::make_expr_error_node(Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::InternalExprError, "literal elaboration: a Unicode-scalar-sequence unfolding row was selected for a non-string literal (gunbc.structural_realization_bindings keys the row on KernelStringLiteral, so this row is malformed)".to_string(), span.clone()), }, LiteralUnfolding::PeanoUnfold { zero, succ, prev_field, .. } => match (*lit.clone()).clone() { - LiteralValue::LitInt { value: n, .. } => unfold_peano_image(n.clone(), zero.decl_name.clone(), succ.decl_name.clone(), prev_field.clone(), elaboration.destination.clone().decl_name.clone(), destination_type.clone(), span.clone()), + LiteralValue::LitInt { value: n, .. } => unfold_peano_image(n.clone(), zero.decl_name.clone(), succ.decl_name.clone(), prev_field.clone(), elaboration.destination.clone().decl_name.clone(), Rc::new(VariantParentIdentity::VariantParentIdentified { + key: Rc::new(VariantParentKey::VariantParentDeclaration { + declaration: elaboration.destination.clone(), +}), +}), destination_type.clone(), span.clone()), _ => crate::v1_std_core::make_expr_error_node(Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::InternalExprError, "literal elaboration: a Peano unfolding row was selected for a non-integer literal (gunbc.structural_realization_bindings keys the row on KernelIntLiteral, so this row is malformed)".to_string(), span.clone()), }, LiteralUnfolding::BooleanUnfold { true_variant: t, false_variant: f, .. } => match (*lit.clone()).clone() { @@ -11643,6 +11746,11 @@ pub fn unfold_literal_image( }, Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new(VarBindingKind::VariantValueBinding { parent_enum: elaboration.destination.clone().decl_name.clone(), + parent_identity: Rc::new(VariantParentIdentity::VariantParentIdentified { + key: Rc::new(VariantParentKey::VariantParentDeclaration { + declaration: elaboration.destination.clone(), +}), +}), })), }), Rc::new(vec![]), destination_type.clone(), span.clone()), _ => crate::v1_std_core::make_expr_error_node(Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::InternalExprError, "literal elaboration: a Boolean unfolding row was selected for a non-boolean literal (gunbc.structural_realization_bindings keys the row on KernelBoolLiteral, so this row is malformed)".to_string(), span.clone()), @@ -11883,6 +11991,7 @@ match scope_parent.clone() { typed: crate::v1_std_core::make_named_expr_node(texpr.occurrence_identity.clone(), name.clone(), Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new(VarBindingKind::VariantValueBinding { parent_enum: scope_enum.clone(), + parent_identity: variant_parent_identity_of(variant_owner_node(scope.clone(), name.clone()), scope.clone()), })), }), Rc::new(vec![]), Some(Rc::new(InferredNode::Resolved { node: variant_reference_inferred_node(expected.clone(), name.clone(), scope_enum.clone(), scope.clone(), binding.resolved.clone()), @@ -11938,6 +12047,7 @@ match scope_parent.clone() { typed: crate::v1_std_core::make_named_expr_node(texpr.occurrence_identity.clone(), name.clone(), Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new(VarBindingKind::VariantValueBinding { parent_enum: scope_enum.clone(), + parent_identity: variant_parent_identity_of(variant_owner_node(scope.clone(), name.clone()), scope.clone()), })), }), Rc::new(vec![]), Some(Rc::new(InferredNode::Resolved { node: variant_reference_inferred_node(expected.clone(), name.clone(), scope_enum.clone(), scope.clone(), gbinding.resolved.clone()), @@ -11949,6 +12059,7 @@ match scope_parent.clone() { typed: crate::v1_std_core::make_named_expr_node(texpr.occurrence_identity.clone(), name.clone(), Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new(VarBindingKind::VariantValueBinding { parent_enum: crate::v1_std_core::authored_name_at(scope.type_env.clone().source_indices.clone(), exp_enum.clone()), + parent_identity: variant_parent_identity_of(Some(exp_enum.clone()), scope.clone()), })), }), Rc::new(vec![]), Some(Rc::new(InferredNode::Resolved { node: exp_enum.clone(), @@ -11994,6 +12105,7 @@ match expected_variant_enum.clone() { typed: crate::v1_std_core::make_named_expr_node(texpr.occurrence_identity.clone(), name.clone(), Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new(VarBindingKind::VariantValueBinding { parent_enum: crate::v1_std_core::authored_name_at(scope.type_env.clone().source_indices.clone(), exp_enum.clone()), + parent_identity: variant_parent_identity_of(Some(exp_enum.clone()), scope.clone()), })), }), Rc::new(vec![]), Some(Rc::new(InferredNode::Resolved { node: exp_enum.clone(), diff --git a/src/v1/stage0/src/v1_compiler_parse.rs b/src/v1/stage0/src/v1_compiler_parse.rs index b2d60f0ac62..0e333433843 100644 --- a/src/v1/stage0/src/v1_compiler_parse.rs +++ b/src/v1/stage0/src/v1_compiler_parse.rs @@ -51,6 +51,8 @@ pub use crate::std_syntax::{ BinOp, BodyKind, ItemForm, ItemFormKind, LiteralValue, OperatorSpec, ParseEnvironment, SyntaxSpec, }; +pub use crate::std_target_representation::VariantParentIdentity; +use crate::std_target_representation::VariantParentIdentity::VariantParentBeforeInference; pub use crate::std_types::{NonEmptyStr, SourceSpan}; use crate::v1_rt; use crate::v1_rt::{VecCompat, VecJoin}; @@ -3048,6 +3050,7 @@ pub fn stamp_parsed_pattern( name, parent_enum, field_bindings, + parent_identity, .. }) => { let stamped = stamp_parsed_node_list( @@ -3063,6 +3066,7 @@ pub fn stamp_parsed_pattern( name: name.clone(), parent_enum: parent_enum.clone(), field_bindings: stamped.nodes.clone(), + parent_identity: parent_identity.clone(), })), ctx: stamped.ctx.clone(), err: stamped.err.clone(), @@ -16428,6 +16432,9 @@ pub fn parse_variant_pattern( name: name.clone(), parent_enum: std::option::Option::None, field_bindings: r.field_bindings.clone(), + parent_identity: Rc::new( + VariantParentIdentity::VariantParentBeforeInference, + ), }), tokens: r2.tokens.clone(), ctx: r.ctx.clone(), @@ -16468,6 +16475,9 @@ pub fn parse_variant_pattern( name: name.clone(), parent_enum: std::option::Option::None, field_bindings: Rc::new(vec![fb.clone()]), + parent_identity: Rc::new( + VariantParentIdentity::VariantParentBeforeInference, + ), }), tokens: r2.tokens.clone(), ctx: minted.ctx.clone(), @@ -16480,6 +16490,9 @@ pub fn parse_variant_pattern( name: name.clone(), parent_enum: std::option::Option::None, field_bindings: Rc::new(vec![]), + parent_identity: Rc::new( + VariantParentIdentity::VariantParentBeforeInference, + ), }), tokens: tokens.clone(), ctx: ctx.clone(), diff --git a/src/v1/stage0/src/v1_std_core.rs b/src/v1/stage0/src/v1_std_core.rs index 15858fd71ca..90cd7e699c1 100644 --- a/src/v1/stage0/src/v1_std_core.rs +++ b/src/v1/stage0/src/v1_std_core.rs @@ -81,6 +81,8 @@ use crate::std_syntax::BinOp::{ }; use crate::std_syntax::LiteralValue::{LitBool, LitFloat, LitInt, LitNull, LitStr, LitSymbol}; pub use crate::std_syntax::{AlgebraFieldKind, BinOp, LiteralValue}; +pub use crate::std_target_representation::VariantParentIdentity; +use crate::std_target_representation::VariantParentIdentity::*; pub use crate::std_types::{ container_expected_arity, container_type_arity, is_container_type, is_kernel_type, kernel_type_set, @@ -267,7 +269,10 @@ pub fn has_inferred(n: Rc) -> bool { pub enum VarBindingKind { LocalValueBinding, FunctionValueBinding, - VariantValueBinding { parent_enum: String }, + VariantValueBinding { + parent_enum: String, + parent_identity: Rc, + }, MatchBoundBinding, ServiceValueBinding, } @@ -283,6 +288,18 @@ impl VarBindingKind { VarBindingKind::ServiceValueBinding => panic!("no parent_enum on unit variant"), } } + pub fn parent_identity(&self) -> Rc { + match self { + VarBindingKind::LocalValueBinding => panic!("no parent_identity on unit variant"), + VarBindingKind::FunctionValueBinding => panic!("no parent_identity on unit variant"), + VarBindingKind::VariantValueBinding { + parent_identity: __val, + .. + } => __val.clone(), + VarBindingKind::MatchBoundBinding => panic!("no parent_identity on unit variant"), + VarBindingKind::ServiceValueBinding => panic!("no parent_identity on unit variant"), + } + } } #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] @@ -477,6 +494,7 @@ pub enum MatchPattern { name: String, parent_enum: Option, field_bindings: Rc>>, + parent_identity: Rc, }, Wildcard, } From 02faba972de66460be946c5a0f2ae6800b0840d5 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Fri, 2 Oct 2026 07:26:47 +0000 Subject: [PATCH 20/21] infer_semantics_witness: pre-inference VariantPattern fixtures carry VariantParentBeforeInference Co-Authored-By: Claude Opus 5.5 (1M context) --- src/v1/stage0/src/bin/infer_semantics_witness.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/v1/stage0/src/bin/infer_semantics_witness.rs b/src/v1/stage0/src/bin/infer_semantics_witness.rs index 606d9fd4019..832692293ea 100644 --- a/src/v1/stage0/src/bin/infer_semantics_witness.rs +++ b/src/v1/stage0/src/bin/infer_semantics_witness.rs @@ -413,6 +413,9 @@ fn variant_arm(name: &str) -> Rc { name: name.to_string(), parent_enum: None, field_bindings: Rc::new(vec![]), + parent_identity: Rc::new( + v1_compiler::std_target_representation::VariantParentIdentity::VariantParentBeforeInference, + ), }), None, unit_expr(), @@ -932,6 +935,9 @@ fn optional_present_absent_patterns_keep_canonical_names() { name: "Present".to_string(), parent_enum: None, field_bindings: Rc::new(vec![]), + parent_identity: Rc::new( + v1_compiler::std_target_representation::VariantParentIdentity::VariantParentBeforeInference, + ), }), subject.clone(), zero_span(), @@ -942,6 +948,9 @@ fn optional_present_absent_patterns_keep_canonical_names() { name: "Absent".to_string(), parent_enum: None, field_bindings: Rc::new(vec![]), + parent_identity: Rc::new( + v1_compiler::std_target_representation::VariantParentIdentity::VariantParentBeforeInference, + ), }), subject, zero_span(), @@ -1090,6 +1099,9 @@ fn real_optional_coproduct_preserves_present_absent_pattern_names() { name: "Present".to_string(), parent_enum: None, field_bindings: Rc::new(vec![]), + parent_identity: Rc::new( + v1_compiler::std_target_representation::VariantParentIdentity::VariantParentBeforeInference, + ), }), subject, zero_span(), From 0c0a5ee0ea59259d0b58b7ced643921958c391cf Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Fri, 2 Oct 2026 18:25:18 +0000 Subject: [PATCH 21/21] Regenerate stage0 mirrors to the fixed point after merging main (round 2 first_generation_equal=true) Co-Authored-By: Claude Opus 5.5 (1M context) --- src/v1/stage0/src/compiler_tests.rs | 2 +- src/v1/stage0/src/v1_compiler_compile.rs | 14 +++++++------- .../stage0/src/v1_compiler_compiler_tests_rust.rs | 2 +- src/v1/stage0/src/v1_compiler_infer.rs | 10 +++++----- src/v1/stage0/src/v1_compiler_parse.rs | 4 ++-- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/v1/stage0/src/compiler_tests.rs b/src/v1/stage0/src/compiler_tests.rs index ad78aaeba41..75c0370295b 100644 --- a/src/v1/stage0/src/compiler_tests.rs +++ b/src/v1/stage0/src/compiler_tests.rs @@ -2835,7 +2835,7 @@ mod compiler_tests { // that only proves the refusal stopped is indistinguishable from // deleting the wall. let peel_src = |call: &str| { - format!("module peel\ntype Tight = String where non_empty\nfn f(s: Tight) -> Int {{ s |> {} }}\n", call) + format!("module peel\ntype Tight = String where string_non_empty\nfn f(s: Tight) -> Int {{ s |> {} }}\n", call) }; let peel_green = compile_one("peel_green.dag", peel_src("count")); assert!( diff --git a/src/v1/stage0/src/v1_compiler_compile.rs b/src/v1/stage0/src/v1_compiler_compile.rs index 329df798988..5463fdd4572 100644 --- a/src/v1/stage0/src/v1_compiler_compile.rs +++ b/src/v1/stage0/src/v1_compiler_compile.rs @@ -479,13 +479,13 @@ pub fn test_reference_row( pub fn test_reference_debt() -> Rc>> { Rc::new(vec![Rc::new(TestReferenceDebtRow { - module_name: "wall.fixture.paid_down".to_string(), - referrer: "reader".to_string(), - target: "wall.fixture.paid_down.leaf".to_string(), - occurrences: 1, - scope: TestReferenceRowScope::FixtureControlRow, - dissolution: test_reference_debt_dissolution(), -}), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "".to_string(), "test.claim.climbing_hold_catalog_witness.witness_absent_shape_refuses_silhouette".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "".to_string(), "test.claim.climbing_hold_catalog_witness.witness_catalog_evidence_cannot_buy_placement_clearance".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "".to_string(), "test.claim.climbing_hold_catalog_witness.witness_evidence_spendability_discriminates".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "".to_string(), "test.claim.climbing_hold_catalog_witness.witness_mounting_axis_needs_no_shape_or_envelope".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "".to_string(), "test.claim.climbing_hold_catalog_witness.witness_naming_is_alias_with_sku_unread".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "".to_string(), "test.claim.climbing_hold_catalog_witness.witness_proof_load_receipt_is_load_bearing".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "".to_string(), "test.claim.climbing_hold_catalog_witness.witness_real_row_axis_is_not_yet_locatable".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "".to_string(), "test.claim.climbing_hold_catalog_witness.witness_real_row_refuses_lift_role_on_axis".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "".to_string(), "test.claim.climbing_hold_catalog_witness.witness_relayed_reading_makes_envelope_spendable".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "".to_string(), "test.claim.climbing_hold_catalog_witness.witness_search_summary_envelope_is_not_spendable".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "".to_string(), "test.claim.climbing_hold_catalog_witness.witness_source_reading_survives_conversion".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "climbing_hold_witness_outcomes".to_string(), "test.claim.climbing_hold_catalog_witness.witness_absent_shape_refuses_silhouette".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "climbing_hold_witness_outcomes".to_string(), "test.claim.climbing_hold_catalog_witness.witness_catalog_evidence_cannot_buy_placement_clearance".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "climbing_hold_witness_outcomes".to_string(), "test.claim.climbing_hold_catalog_witness.witness_evidence_spendability_discriminates".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "climbing_hold_witness_outcomes".to_string(), "test.claim.climbing_hold_catalog_witness.witness_mounting_axis_needs_no_shape_or_envelope".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "climbing_hold_witness_outcomes".to_string(), "test.claim.climbing_hold_catalog_witness.witness_naming_is_alias_with_sku_unread".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "climbing_hold_witness_outcomes".to_string(), "test.claim.climbing_hold_catalog_witness.witness_proof_load_receipt_is_load_bearing".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "climbing_hold_witness_outcomes".to_string(), "test.claim.climbing_hold_catalog_witness.witness_real_row_axis_is_not_yet_locatable".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "climbing_hold_witness_outcomes".to_string(), "test.claim.climbing_hold_catalog_witness.witness_real_row_refuses_lift_role_on_axis".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "climbing_hold_witness_outcomes".to_string(), "test.claim.climbing_hold_catalog_witness.witness_relayed_reading_makes_envelope_spendable".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "climbing_hold_witness_outcomes".to_string(), "test.claim.climbing_hold_catalog_witness.witness_search_summary_envelope_is_not_spendable".to_string(), 1), test_reference_row("test.claim.climbing_hold_witness_roster".to_string(), "climbing_hold_witness_outcomes".to_string(), "test.claim.climbing_hold_catalog_witness.witness_source_reading_survives_conversion".to_string(), 1), test_reference_row("test.claim.materialization_provider_consumer_hand_rust_witness".to_string(), "".to_string(), "test.claim.materialization_provider_witness.incomplete_v1_shape_artifact_refuses_naming_the_diagnostic_union".to_string(), 1), test_reference_row("test.claim.materialization_provider_consumer_hand_rust_witness".to_string(), "".to_string(), "test.claim.materialization_provider_witness.red_declared_input_miss_stale_artifact_refuses_as_wrong_artifact".to_string(), 1), test_reference_row("test.claim.materialization_provider_consumer_hand_rust_witness".to_string(), "witness_model_refusal_controls_remain_distinct".to_string(), "test.claim.materialization_provider_witness.incomplete_v1_shape_artifact_refuses_naming_the_diagnostic_union".to_string(), 1), test_reference_row("test.claim.materialization_provider_consumer_hand_rust_witness".to_string(), "witness_model_refusal_controls_remain_distinct".to_string(), "test.claim.materialization_provider_witness.red_declared_input_miss_stale_artifact_refuses_as_wrong_artifact".to_string(), 1), test_reference_row("test.claim.native_witness_transition_receipt_witness".to_string(), "".to_string(), "v2.test.execution.native_selected_witness_bundle.native_selected_witness_bundle_cutover_evidence_holds".to_string(), 1), test_reference_row("test.claim.native_witness_transition_receipt_witness".to_string(), "cited_evidence_declaration_is_an_executing_witness".to_string(), "v2.test.execution.native_selected_witness_bundle.native_selected_witness_bundle_cutover_evidence_holds".to_string(), 1)]) + module_name: "wall.fixture.paid_down".to_string(), + referrer: "reader".to_string(), + target: "wall.fixture.paid_down.leaf".to_string(), + occurrences: 1, + scope: TestReferenceRowScope::FixtureControlRow, + dissolution: test_reference_debt_dissolution(), + })]) } pub fn test_reference_import_referrer() -> String { diff --git a/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs b/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs index 27625c96a93..d3919286864 100644 --- a/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs +++ b/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs @@ -374,7 +374,7 @@ pub fn ct_function_value_field_method_known_hole_probe_test() -> String { } pub fn ct_method_existence_wall_witness_test() -> String { - v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(" #[test]\n".to_string(), " fn method_existence_wall_witness() {\n".to_string()), " // DISCRIMINATING RED for method_existence_wall_note. Before the wall an\n".to_string()), " // unresolved method inherited the RECEIVER's type with no diagnostic, so\n".to_string()), " // `xs |> filter_map(..)` on List typed as List, compiled clean, and\n".to_string()), " // died at InterpError::Unimplemented in live dispatch (#7479, HTTP 500).\n".to_string()), " let result = std::thread::Builder::new()\n".to_string()), " .stack_size(8 * 1024 * 1024)\n".to_string()), " .spawn(|| {\n".to_string()), " let red = std::rc::Rc::new(crate::v1_compiler_compile::SourceFile {\n".to_string()), " path: \"red.dag\".to_string(),\n".to_string()), " content: \"module red\\nfn f(xs: List) -> List { xs |> filter_map(x => x) }\\nfn g(xs: List) -> Bool { xs |> starts_with(\\\"x\\\") }\\nfn h(xs: List) -> String { xs |> to_upper() }\\n\".to_string(),\n".to_string()), " });\n".to_string()), " let red_result = crate::v1_compiler_compile::compile_sources(\n".to_string()), " std::rc::Rc::new(im::vector![red]),\n".to_string()), " crate::v1_compiler_artifact::RenderTarget::Rust,\n".to_string()), " );\n".to_string()), " let missing: Vec<_> = red_result.diagnostics.iter()\n".to_string()), " .filter(|d| matches!(*d.diagnostic, crate::v1_std_core::CompilerDiagnostic::MethodNotFound { .. }))\n".to_string()), " .collect();\n".to_string()), " assert!(\n".to_string()), " missing.len() >= 3,\n".to_string()), " \"expected MethodNotFound for the unresolved method AND for rostered names on a receiver that does not offer them (starts_with / to_upper on List — codex review 45327: a name-grain predicate admitted these), got: {:?}\",\n".to_string()), " red_result.diagnostics\n".to_string()), " );\n".to_string()), " // POSITIVE CONTROLS the wall must not touch: algebra method templates\n".to_string()), " // resolve at tier0, and `count` is in the declared std.methods roster\n".to_string()), " // even though free_monoid_scalar_templates omits it (the measured fork).\n".to_string()), " let green = std::rc::Rc::new(crate::v1_compiler_compile::SourceFile {\n".to_string()), " path: \"green.dag\".to_string(),\n".to_string()), " content: \"module green\\nfn p(xs: List) -> List { xs |> filter(x => x > 1) |> map(x => x + 1) }\\nfn q(xs: List) -> Int { xs |> fold(0, (a, x) => a + x) }\\nfn r(s: String) -> Int { s |> count }\\n\".to_string(),\n".to_string()), " });\n".to_string()), " let green_result = crate::v1_compiler_compile::compile_sources(\n".to_string()), " std::rc::Rc::new(im::vector![green]),\n".to_string()), " crate::v1_compiler_artifact::RenderTarget::Rust,\n".to_string()), " );\n".to_string()), " // The positive control asserts ZERO diagnostics, not merely no\n".to_string()), " // MethodNotFound. Filtering to the blocking variant let an ADVISORY\n".to_string()), " // MethodExistenceUndecided pass unnoticed, which is how `String |> count`\n".to_string()), " // was reported as a passing control while it was actually resolving\n".to_string()), " // through the non-blocking arm (codex review 45357).\n".to_string()), " assert!(\n".to_string()), " green_result.diagnostics.is_empty(),\n".to_string()), " \"legitimate methods must resolve with NO diagnostic of any severity — an advisory here means the call is not actually resolving, got: {:?}\",\n".to_string()), " green_result.diagnostics\n".to_string()), " );\n".to_string()), " // DISCRIMINATING RED for the declared frontier (codex reviews 45357,\n".to_string()), " // 45383). An undecided method existence must BLOCK, so the graph is\n".to_string()), " // never emitted on an unestablished judgment; the only non-blocking\n".to_string()), " // path is a DECLARED frontier row, which is countable and carries its\n".to_string()), " // own dissolution trigger. The two halves must be discriminated by\n".to_string()), " // MODULE NAME on otherwise identical source — an admission that fires\n".to_string()), " // for any module is an escape hatch, not a frontier.\n".to_string()), " let frontier_src = |module: &str, method: &str| {\n".to_string()), " format!(\"module {}\\ntype T {{ a: Int }}\\nfn f(t: T) -> Int {{ t |> {}(1) }}\\n\", module, method)\n".to_string()), " };\n".to_string()), " let compile_one = |path: &str, content: String| {\n".to_string()), " crate::v1_compiler_compile::compile_sources(\n".to_string()), " std::rc::Rc::new(im::vector![std::rc::Rc::new(\n".to_string()), " crate::v1_compiler_compile::SourceFile {\n".to_string()), " path: path.to_string(),\n".to_string()), " content,\n".to_string()), " }\n".to_string()), " )]),\n".to_string()), " crate::v1_compiler_artifact::RenderTarget::Rust,\n".to_string()), " )\n".to_string()), " };\n".to_string()), " let unlisted = compile_one(\"unlisted.dag\", frontier_src(\"unlisted.module\", \"list_push\"));\n".to_string()), " let undecided: Vec<_> = unlisted.diagnostics.iter()\n".to_string()), " .filter(|d| matches!(*d.diagnostic, crate::v1_std_core::CompilerDiagnostic::MethodExistenceUndecided { .. }))\n".to_string()), " .collect();\n".to_string()), " assert!(\n".to_string()), " !undecided.is_empty(),\n".to_string()), " \"a method whose existence is undecided in a module with NO declared frontier row must refuse, got: {:?}\",\n".to_string()), " unlisted.diagnostics\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " undecided.iter().all(|d| crate::v1_std_core::is_error_diagnostic(d.diagnostic.clone())\n".to_string()), " && crate::v1_std_core::is_interpreter_blocking_diagnostic(d.diagnostic.clone())),\n".to_string()), " \"MethodExistenceUndecided must BLOCK both typecheck and the interpreter — a non-blocking undecided judgment is exactly the fail-open the wall exists to close\"\n".to_string()), " );\n".to_string()), " // The SHAPE is part of the key, and this is the half that answers\n".to_string()), " // codex review 45398: the module and the method both match a declared\n".to_string()), " // row, and the call is STILL refused, because the receiver does not\n".to_string()), " // fail to resolve in the way the row was measured on. A (module, method)\n".to_string()), " // key passed this input; that is the fail-open the third component closes.\n".to_string()), " let listed_wrong_shape = compile_one(\"listed.dag\", frontier_src(\"extdeps.dns.domain_name\", \"list_push\"));\n".to_string()), " assert!(\n".to_string()), " listed_wrong_shape.diagnostics.iter().any(|d| matches!(*d.diagnostic, crate::v1_std_core::CompilerDiagnostic::MethodExistenceUndecided { .. })),\n".to_string()), " \"a declared row must NOT admit a new call in the same module on a receiver whose shape it was never measured on, got: {:?}\",\n".to_string()), " listed_wrong_shape.diagnostics\n".to_string()), " );\n".to_string()), " // The admission half, checked against the frontier data itself rather\n".to_string()), " // than a synthetic source, because the residual shapes (an unnamed\n".to_string()), " // lambda-parameter receiver, a coproduct payload typed as its variant)\n".to_string()), " // are upstream resolution defects that cannot be conjured on demand.\n".to_string()), " // Every declared row must be admitted by its own exact key, and\n".to_string()), " // perturbing ANY of the three components must withdraw the admission.\n".to_string()), " let rows = crate::v1_compiler_infer::unresolved_method_frontier();\n".to_string()), " assert!(!rows.is_empty(), \"the frontier must be a declared, countable roster\");\n".to_string()), " for r in rows.iter() {\n".to_string()), " assert!(\n".to_string()), " crate::v1_compiler_infer::unresolved_method_frontier_trigger(\n".to_string()), " r.module_name.clone(), r.method.clone(), r.receiver_shape.clone()).is_some(),\n".to_string()), " \"row {}/{}/{} must be admitted by its own key\", r.module_name, r.method, r.receiver_shape\n".to_string()), " );\n".to_string()), " for perturbed in [\n".to_string()), " (format!(\"{}.other\", r.module_name), r.method.clone(), r.receiver_shape.clone()),\n".to_string()), " (r.module_name.clone(), format!(\"{}_other\", r.method), r.receiver_shape.clone()),\n".to_string()), " (r.module_name.clone(), r.method.clone(), format!(\"Product(Other{})\", r.receiver_shape.len())),\n".to_string()), " ] {\n".to_string()), " assert!(\n".to_string()), " crate::v1_compiler_infer::unresolved_method_frontier_trigger(\n".to_string()), " perturbed.0.clone(), perturbed.1.clone(), perturbed.2.clone()).is_none(),\n".to_string()), " \"perturbing the key to {:?} must WITHDRAW the admission — each component is load-bearing\", perturbed\n".to_string()), " );\n".to_string()), " }\n".to_string()), " }\n".to_string()), " // DISCRIMINATING RED for where_refinement_receiver_peel_note. A\n".to_string()), " // where-refinement alias reached method lookup as Product()\n".to_string()), " // because resolve_method_receiver_type short-circuits on Conj, so the\n".to_string()), " // base's algebra profile was never consulted. The peel must make the\n".to_string()), " // receiver decidable in BOTH directions on the SAME alias — a green\n".to_string()), " // that only proves the refusal stopped is indistinguishable from\n".to_string()), " // deleting the wall.\n".to_string()), " let peel_src = |call: &str| {\n".to_string()), " format!(\"module peel\\ntype Tight = String where non_empty\\nfn f(s: Tight) -> Int {{ s |> {} }}\\n\", call)\n".to_string()), " };\n".to_string()), " let peel_green = compile_one(\"peel_green.dag\", peel_src(\"count\"));\n".to_string()), " assert!(\n".to_string()), " peel_green.diagnostics.is_empty(),\n".to_string()), " \"a method on the refinement's String base must RESOLVE once the base is peeled — no diagnostic of any severity, got: {:?}\",\n".to_string()), " peel_green.diagnostics\n".to_string()), " );\n".to_string()), " // DISCRIMINATING RED for the two special-case arms (codex review\n".to_string()), " // 45430). The wall was reached only from the FINAL else, so an\n".to_string()), " // unresolved map_keys / map_values still returned the RECEIVER type\n".to_string()), " // with an empty diagnostic list — the exact success-shaped fallback\n".to_string()), " // this PR deletes, surviving in the two branches that ran before it.\n".to_string()), " let special = compile_one(\"special.dag\",\n".to_string()), " \"module special\\nfn f(xs: List) -> List {{ xs |> map_keys }}\\nfn g(xs: List) -> List {{ xs |> map_values }}\\n\".replace(\"{{\", \"{\").replace(\"}}\", \"}\"));\n".to_string()), " let special_missing: Vec<_> = special.diagnostics.iter()\n".to_string()), " .filter(|d| matches!(*d.diagnostic, crate::v1_std_core::CompilerDiagnostic::MethodNotFound { .. }))\n".to_string()), " .collect();\n".to_string()), " assert!(\n".to_string()), " special_missing.len() >= 2,\n".to_string()), " \"map_keys and map_values must route through the SAME refusal as every other method when the receiver is not a keyed collection — a wall reachable only from the final else is not a wall, got: {:?}\",\n".to_string()), " special.diagnostics\n".to_string()), " );\n".to_string()), " // ReceiverTypeUnestablished CLASSIFICATION control. The behavioural\n".to_string()), " // evidence for this class is the corpus census, not a synthetic\n".to_string()), " // source: 18 sites whole-tree, counted as advisories with the gate at\n".to_string()), " // zero blocking diagnostics. A synthetic reproducer WAS attempted --\n".to_string()), " // an untyped lambda parameter inside a record-field fn, the shape the\n".to_string()), " // real sites have -- and it produced no diagnostic at all, so it did\n".to_string()), " // not reproduce the shape and is not asserted here as though it did.\n".to_string()), " // ADMISSION is roster-gated, not automatic: an anonymous receiver is\n".to_string()), " // admitted only where a declared row names (module, method,\n".to_string()), " // Primitive()), and the perturbation loop above proves that gate for\n".to_string()), " // every row. Admitting on the CAUSE alone was the earlier version and\n".to_string()), " // was an unbounded green path — sound about decidability, wrong about\n".to_string()), " // admission, since it made every future anonymous-receiver call pass\n".to_string()), " // including one whose method does not exist (codex review 45459).\n".to_string()), " // What THIS control pins is the remaining half, the classification of\n".to_string()), " // an admitted one: COUNTED and NON-BLOCKING. Blocking it fabricates a\n".to_string()), " // refusal over the 18 measured sites; dropping it restores #7479 silence.\n".to_string()), " let unestablished_diag = std::rc::Rc::new(\n".to_string()), " crate::v1_std_core::CompilerDiagnostic::ReceiverTypeUnestablished {\n".to_string()), " method: \"probe\".to_string(),\n".to_string()), " span: std::rc::Rc::new(crate::std_types::SourceSpan {\n".to_string()), " file: \"probe.dag\".to_string(), start: 0, end: 0,\n".to_string()), " }),\n".to_string()), " });\n".to_string()), " assert!(\n".to_string()), " !crate::v1_std_core::is_error_diagnostic(unestablished_diag.clone())\n".to_string()), " && !crate::v1_std_core::is_interpreter_blocking_diagnostic(unestablished_diag.clone()),\n".to_string()), " \"ReceiverTypeUnestablished must not block — the receiver's type is an upstream deficit, so refusing here fabricates a refusal over correct code\"\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " crate::v1_std_core::is_discovery_corpus_advisory_typecheck_diagnostic(unestablished_diag.clone()),\n".to_string()), " \"...and it must be a COUNTED advisory, never absent — an uncounted degradation is the absorbing fallback DESIGN §5 forbids\"\n".to_string()), " );\n".to_string()), " // DISCRIMINATING CONTROL for the occurrence ratchet (codex reviews\n".to_string()), " // 45464 and 45491). A (module, method, receiver_shape) key bounds\n".to_string()), " // WHERE an unresolved call may live but not HOW MANY, and the rows\n".to_string()), " // need not be singletons (the multi-occurrence rows this once named\n".to_string()), " // were deleted at zero observed — see frontier_occurrence_budget_note —\n".to_string()), " // so the control takes whichever row survives and counts against\n".to_string()), " // its declared receiver shape rather than against Primitive()).\n".to_string()), " // The comparison is EQUALITY, not a ceiling: a ceiling lets seven\n".to_string()), " // shrink to six and a seventh come back silently, which is a static\n".to_string()), " // limit rather than a ratchet. Equality is safe because the check runs\n".to_string()), " // per MODULE, and every occurrence in a module is present whenever\n".to_string()), " // that module is typechecked at all — a closure that omits the module\n".to_string()), " // never runs its rows. Exercised at the mechanism so the boundary is\n".to_string()), " // exact on both sides.\n".to_string()), " let budget_row = rows.iter()\n".to_string()), " .next()\n".to_string()), " .expect(\"the frontier must hold at least one row to bound\");\n".to_string()), " let probe_span = || std::rc::Rc::new(crate::std_types::SourceSpan {\n".to_string()), " file: \"probe.dag\".to_string(), start: 0, end: 0,\n".to_string()), " });\n".to_string()), " let unestablished_at = |n: usize| {\n".to_string()), " std::rc::Rc::new((0..n).map(|_| std::rc::Rc::new(crate::v1_std_core::ErrorNode {\n".to_string()), " diagnostic: std::rc::Rc::new(crate::v1_std_core::CompilerDiagnostic::MethodExistenceFrontierAdmitted {\n".to_string()), " method: budget_row.method.clone(),\n".to_string()), " receiver_type: budget_row.receiver_shape.clone(),\n".to_string()), " trigger: String::new(),\n".to_string()), " span: probe_span(),\n".to_string()), " }),\n".to_string()), " module_name: budget_row.module_name.clone(),\n".to_string()), " })).collect::>())\n".to_string()), " };\n".to_string()), " let budget_at = |n: usize| crate::v1_compiler_infer::frontier_occurrence_budget_diags(\n".to_string()), " budget_row.module_name.clone(), probe_span(), unestablished_at(n));\n".to_string()), " assert!(\n".to_string()), " budget_at(budget_row.occurrences as usize).is_empty(),\n".to_string()), " \"exactly the declared occurrence count must pass\"\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " budget_at(budget_row.occurrences as usize + 1).iter().any(|d| matches!(*d.diagnostic, crate::v1_std_core::CompilerDiagnostic::FrontierOccurrenceBudgetExceeded { .. })),\n".to_string()), " \"one MORE than the declared count must refuse — otherwise the row bounds where an unresolved call may live but not how many\"\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " budget_at(budget_row.occurrences as usize + 1).iter().all(|d| crate::v1_std_core::is_error_diagnostic(d.diagnostic.clone())),\n".to_string()), " \"...and that refusal must BLOCK, or the ratchet is decorative\"\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " budget_at(0).iter().any(|d| matches!(*d.diagnostic, crate::v1_std_core::CompilerDiagnostic::FrontierOccurrenceBudgetExceeded { .. })),\n".to_string()), " \"FEWER than declared must ALSO refuse, and this is the half that makes it a ratchet rather than a ceiling: fixing a call forces the declared count DOWN, so a later reintroduction has no headroom to slip back into (codex review 45491)\"\n".to_string()), " );\n".to_string()), " // DISCRIMINATING PAIR for the early-return walk. An early return is a\n".to_string()), " // second exit from the same declaration and must meet its declared\n".to_string()), " // type; a return inside a nested LAMBDA belongs to the lambda's own\n".to_string()), " // callable return, so checking it against the enclosing declaration\n".to_string()), " // fabricates a refusal — the mirror image of the hole the walk closes\n".to_string()), " // (codex reviews 45472 and 45481, both confirmed by execution).\n".to_string()), " let early_return = compile_one(\"early_return.dag\",\n".to_string()), " \"module early_return\\nfn f(cond: Bool) -> Int { if cond { return \\\"wrong\\\" } 1 }\\n\".to_string());\n".to_string()), " assert!(\n".to_string()), " early_return.diagnostics.iter().any(|d| matches!(*d.diagnostic, crate::v1_std_core::CompilerDiagnostic::TypeMismatch { .. })),\n".to_string()), " \"an early return of the wrong type must refuse — the trailing expression conforming says nothing about the other exit, got: {:?}\",\n".to_string()), " early_return.diagnostics\n".to_string()), " );\n".to_string()), " let lambda_return = compile_one(\"lambda_return.dag\",\n".to_string()), " \"module lambda_return\\nfn apply_it(g: fn(Int) -> String, v: Int) -> String { g(v) }\\nfn outer(v: Int) -> Int { apply_it(g: x => { return \\\"inner\\\" }, v: v) 1 }\\n\".to_string());\n".to_string()), " assert!(\n".to_string()), " lambda_return.diagnostics.iter().all(|d| !matches!(*d.diagnostic, crate::v1_std_core::CompilerDiagnostic::TypeMismatch { .. })),\n".to_string()), " \"a return inside a nested lambda belongs to the LAMBDA's declared return, not the enclosing function's — checking it here fabricates a refusal, got: {:?}\",\n".to_string()), " lambda_return.diagnostics\n".to_string()), " );\n".to_string()), " let peel_red = compile_one(\"peel_red.dag\", peel_src(\"filter_map(x => x)\"));\n".to_string()), " assert!(\n".to_string()), " peel_red.diagnostics.iter().any(|d| matches!(*d.diagnostic, crate::v1_std_core::CompilerDiagnostic::MethodNotFound { .. })),\n".to_string()), " \"peeling must make the receiver DECIDABLE, not merely quiet: a method absent from the peeled base must refuse as MethodNotFound rather than resting in the frontier, got: {:?}\",\n".to_string()), " peel_red.diagnostics\n".to_string()), " );\n".to_string()), " })\n".to_string()), " .expect(\"failed to spawn thread\")\n".to_string()), " .join();\n".to_string()), " result.expect(\"method_existence_wall_witness panicked\");\n".to_string()), " }\n\n".to_string()) + v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(" #[test]\n".to_string(), " fn method_existence_wall_witness() {\n".to_string()), " // DISCRIMINATING RED for method_existence_wall_note. Before the wall an\n".to_string()), " // unresolved method inherited the RECEIVER's type with no diagnostic, so\n".to_string()), " // `xs |> filter_map(..)` on List typed as List, compiled clean, and\n".to_string()), " // died at InterpError::Unimplemented in live dispatch (#7479, HTTP 500).\n".to_string()), " let result = std::thread::Builder::new()\n".to_string()), " .stack_size(8 * 1024 * 1024)\n".to_string()), " .spawn(|| {\n".to_string()), " let red = std::rc::Rc::new(crate::v1_compiler_compile::SourceFile {\n".to_string()), " path: \"red.dag\".to_string(),\n".to_string()), " content: \"module red\\nfn f(xs: List) -> List { xs |> filter_map(x => x) }\\nfn g(xs: List) -> Bool { xs |> starts_with(\\\"x\\\") }\\nfn h(xs: List) -> String { xs |> to_upper() }\\n\".to_string(),\n".to_string()), " });\n".to_string()), " let red_result = crate::v1_compiler_compile::compile_sources(\n".to_string()), " std::rc::Rc::new(im::vector![red]),\n".to_string()), " crate::v1_compiler_artifact::RenderTarget::Rust,\n".to_string()), " );\n".to_string()), " let missing: Vec<_> = red_result.diagnostics.iter()\n".to_string()), " .filter(|d| matches!(*d.diagnostic, crate::v1_std_core::CompilerDiagnostic::MethodNotFound { .. }))\n".to_string()), " .collect();\n".to_string()), " assert!(\n".to_string()), " missing.len() >= 3,\n".to_string()), " \"expected MethodNotFound for the unresolved method AND for rostered names on a receiver that does not offer them (starts_with / to_upper on List — codex review 45327: a name-grain predicate admitted these), got: {:?}\",\n".to_string()), " red_result.diagnostics\n".to_string()), " );\n".to_string()), " // POSITIVE CONTROLS the wall must not touch: algebra method templates\n".to_string()), " // resolve at tier0, and `count` is in the declared std.methods roster\n".to_string()), " // even though free_monoid_scalar_templates omits it (the measured fork).\n".to_string()), " let green = std::rc::Rc::new(crate::v1_compiler_compile::SourceFile {\n".to_string()), " path: \"green.dag\".to_string(),\n".to_string()), " content: \"module green\\nfn p(xs: List) -> List { xs |> filter(x => x > 1) |> map(x => x + 1) }\\nfn q(xs: List) -> Int { xs |> fold(0, (a, x) => a + x) }\\nfn r(s: String) -> Int { s |> count }\\n\".to_string(),\n".to_string()), " });\n".to_string()), " let green_result = crate::v1_compiler_compile::compile_sources(\n".to_string()), " std::rc::Rc::new(im::vector![green]),\n".to_string()), " crate::v1_compiler_artifact::RenderTarget::Rust,\n".to_string()), " );\n".to_string()), " // The positive control asserts ZERO diagnostics, not merely no\n".to_string()), " // MethodNotFound. Filtering to the blocking variant let an ADVISORY\n".to_string()), " // MethodExistenceUndecided pass unnoticed, which is how `String |> count`\n".to_string()), " // was reported as a passing control while it was actually resolving\n".to_string()), " // through the non-blocking arm (codex review 45357).\n".to_string()), " assert!(\n".to_string()), " green_result.diagnostics.is_empty(),\n".to_string()), " \"legitimate methods must resolve with NO diagnostic of any severity — an advisory here means the call is not actually resolving, got: {:?}\",\n".to_string()), " green_result.diagnostics\n".to_string()), " );\n".to_string()), " // DISCRIMINATING RED for the declared frontier (codex reviews 45357,\n".to_string()), " // 45383). An undecided method existence must BLOCK, so the graph is\n".to_string()), " // never emitted on an unestablished judgment; the only non-blocking\n".to_string()), " // path is a DECLARED frontier row, which is countable and carries its\n".to_string()), " // own dissolution trigger. The two halves must be discriminated by\n".to_string()), " // MODULE NAME on otherwise identical source — an admission that fires\n".to_string()), " // for any module is an escape hatch, not a frontier.\n".to_string()), " let frontier_src = |module: &str, method: &str| {\n".to_string()), " format!(\"module {}\\ntype T {{ a: Int }}\\nfn f(t: T) -> Int {{ t |> {}(1) }}\\n\", module, method)\n".to_string()), " };\n".to_string()), " let compile_one = |path: &str, content: String| {\n".to_string()), " crate::v1_compiler_compile::compile_sources(\n".to_string()), " std::rc::Rc::new(im::vector![std::rc::Rc::new(\n".to_string()), " crate::v1_compiler_compile::SourceFile {\n".to_string()), " path: path.to_string(),\n".to_string()), " content,\n".to_string()), " }\n".to_string()), " )]),\n".to_string()), " crate::v1_compiler_artifact::RenderTarget::Rust,\n".to_string()), " )\n".to_string()), " };\n".to_string()), " let unlisted = compile_one(\"unlisted.dag\", frontier_src(\"unlisted.module\", \"list_push\"));\n".to_string()), " let undecided: Vec<_> = unlisted.diagnostics.iter()\n".to_string()), " .filter(|d| matches!(*d.diagnostic, crate::v1_std_core::CompilerDiagnostic::MethodExistenceUndecided { .. }))\n".to_string()), " .collect();\n".to_string()), " assert!(\n".to_string()), " !undecided.is_empty(),\n".to_string()), " \"a method whose existence is undecided in a module with NO declared frontier row must refuse, got: {:?}\",\n".to_string()), " unlisted.diagnostics\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " undecided.iter().all(|d| crate::v1_std_core::is_error_diagnostic(d.diagnostic.clone())\n".to_string()), " && crate::v1_std_core::is_interpreter_blocking_diagnostic(d.diagnostic.clone())),\n".to_string()), " \"MethodExistenceUndecided must BLOCK both typecheck and the interpreter — a non-blocking undecided judgment is exactly the fail-open the wall exists to close\"\n".to_string()), " );\n".to_string()), " // The SHAPE is part of the key, and this is the half that answers\n".to_string()), " // codex review 45398: the module and the method both match a declared\n".to_string()), " // row, and the call is STILL refused, because the receiver does not\n".to_string()), " // fail to resolve in the way the row was measured on. A (module, method)\n".to_string()), " // key passed this input; that is the fail-open the third component closes.\n".to_string()), " let listed_wrong_shape = compile_one(\"listed.dag\", frontier_src(\"extdeps.dns.domain_name\", \"list_push\"));\n".to_string()), " assert!(\n".to_string()), " listed_wrong_shape.diagnostics.iter().any(|d| matches!(*d.diagnostic, crate::v1_std_core::CompilerDiagnostic::MethodExistenceUndecided { .. })),\n".to_string()), " \"a declared row must NOT admit a new call in the same module on a receiver whose shape it was never measured on, got: {:?}\",\n".to_string()), " listed_wrong_shape.diagnostics\n".to_string()), " );\n".to_string()), " // The admission half, checked against the frontier data itself rather\n".to_string()), " // than a synthetic source, because the residual shapes (an unnamed\n".to_string()), " // lambda-parameter receiver, a coproduct payload typed as its variant)\n".to_string()), " // are upstream resolution defects that cannot be conjured on demand.\n".to_string()), " // Every declared row must be admitted by its own exact key, and\n".to_string()), " // perturbing ANY of the three components must withdraw the admission.\n".to_string()), " let rows = crate::v1_compiler_infer::unresolved_method_frontier();\n".to_string()), " assert!(!rows.is_empty(), \"the frontier must be a declared, countable roster\");\n".to_string()), " for r in rows.iter() {\n".to_string()), " assert!(\n".to_string()), " crate::v1_compiler_infer::unresolved_method_frontier_trigger(\n".to_string()), " r.module_name.clone(), r.method.clone(), r.receiver_shape.clone()).is_some(),\n".to_string()), " \"row {}/{}/{} must be admitted by its own key\", r.module_name, r.method, r.receiver_shape\n".to_string()), " );\n".to_string()), " for perturbed in [\n".to_string()), " (format!(\"{}.other\", r.module_name), r.method.clone(), r.receiver_shape.clone()),\n".to_string()), " (r.module_name.clone(), format!(\"{}_other\", r.method), r.receiver_shape.clone()),\n".to_string()), " (r.module_name.clone(), r.method.clone(), format!(\"Product(Other{})\", r.receiver_shape.len())),\n".to_string()), " ] {\n".to_string()), " assert!(\n".to_string()), " crate::v1_compiler_infer::unresolved_method_frontier_trigger(\n".to_string()), " perturbed.0.clone(), perturbed.1.clone(), perturbed.2.clone()).is_none(),\n".to_string()), " \"perturbing the key to {:?} must WITHDRAW the admission — each component is load-bearing\", perturbed\n".to_string()), " );\n".to_string()), " }\n".to_string()), " }\n".to_string()), " // DISCRIMINATING RED for where_refinement_receiver_peel_note. A\n".to_string()), " // where-refinement alias reached method lookup as Product()\n".to_string()), " // because resolve_method_receiver_type short-circuits on Conj, so the\n".to_string()), " // base's algebra profile was never consulted. The peel must make the\n".to_string()), " // receiver decidable in BOTH directions on the SAME alias — a green\n".to_string()), " // that only proves the refusal stopped is indistinguishable from\n".to_string()), " // deleting the wall.\n".to_string()), " let peel_src = |call: &str| {\n".to_string()), " format!(\"module peel\\ntype Tight = String where string_non_empty\\nfn f(s: Tight) -> Int {{ s |> {} }}\\n\", call)\n".to_string()), " };\n".to_string()), " let peel_green = compile_one(\"peel_green.dag\", peel_src(\"count\"));\n".to_string()), " assert!(\n".to_string()), " peel_green.diagnostics.is_empty(),\n".to_string()), " \"a method on the refinement's String base must RESOLVE once the base is peeled — no diagnostic of any severity, got: {:?}\",\n".to_string()), " peel_green.diagnostics\n".to_string()), " );\n".to_string()), " // DISCRIMINATING RED for the two special-case arms (codex review\n".to_string()), " // 45430). The wall was reached only from the FINAL else, so an\n".to_string()), " // unresolved map_keys / map_values still returned the RECEIVER type\n".to_string()), " // with an empty diagnostic list — the exact success-shaped fallback\n".to_string()), " // this PR deletes, surviving in the two branches that ran before it.\n".to_string()), " let special = compile_one(\"special.dag\",\n".to_string()), " \"module special\\nfn f(xs: List) -> List {{ xs |> map_keys }}\\nfn g(xs: List) -> List {{ xs |> map_values }}\\n\".replace(\"{{\", \"{\").replace(\"}}\", \"}\"));\n".to_string()), " let special_missing: Vec<_> = special.diagnostics.iter()\n".to_string()), " .filter(|d| matches!(*d.diagnostic, crate::v1_std_core::CompilerDiagnostic::MethodNotFound { .. }))\n".to_string()), " .collect();\n".to_string()), " assert!(\n".to_string()), " special_missing.len() >= 2,\n".to_string()), " \"map_keys and map_values must route through the SAME refusal as every other method when the receiver is not a keyed collection — a wall reachable only from the final else is not a wall, got: {:?}\",\n".to_string()), " special.diagnostics\n".to_string()), " );\n".to_string()), " // ReceiverTypeUnestablished CLASSIFICATION control. The behavioural\n".to_string()), " // evidence for this class is the corpus census, not a synthetic\n".to_string()), " // source: 18 sites whole-tree, counted as advisories with the gate at\n".to_string()), " // zero blocking diagnostics. A synthetic reproducer WAS attempted --\n".to_string()), " // an untyped lambda parameter inside a record-field fn, the shape the\n".to_string()), " // real sites have -- and it produced no diagnostic at all, so it did\n".to_string()), " // not reproduce the shape and is not asserted here as though it did.\n".to_string()), " // ADMISSION is roster-gated, not automatic: an anonymous receiver is\n".to_string()), " // admitted only where a declared row names (module, method,\n".to_string()), " // Primitive()), and the perturbation loop above proves that gate for\n".to_string()), " // every row. Admitting on the CAUSE alone was the earlier version and\n".to_string()), " // was an unbounded green path — sound about decidability, wrong about\n".to_string()), " // admission, since it made every future anonymous-receiver call pass\n".to_string()), " // including one whose method does not exist (codex review 45459).\n".to_string()), " // What THIS control pins is the remaining half, the classification of\n".to_string()), " // an admitted one: COUNTED and NON-BLOCKING. Blocking it fabricates a\n".to_string()), " // refusal over the 18 measured sites; dropping it restores #7479 silence.\n".to_string()), " let unestablished_diag = std::rc::Rc::new(\n".to_string()), " crate::v1_std_core::CompilerDiagnostic::ReceiverTypeUnestablished {\n".to_string()), " method: \"probe\".to_string(),\n".to_string()), " span: std::rc::Rc::new(crate::std_types::SourceSpan {\n".to_string()), " file: \"probe.dag\".to_string(), start: 0, end: 0,\n".to_string()), " }),\n".to_string()), " });\n".to_string()), " assert!(\n".to_string()), " !crate::v1_std_core::is_error_diagnostic(unestablished_diag.clone())\n".to_string()), " && !crate::v1_std_core::is_interpreter_blocking_diagnostic(unestablished_diag.clone()),\n".to_string()), " \"ReceiverTypeUnestablished must not block — the receiver's type is an upstream deficit, so refusing here fabricates a refusal over correct code\"\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " crate::v1_std_core::is_discovery_corpus_advisory_typecheck_diagnostic(unestablished_diag.clone()),\n".to_string()), " \"...and it must be a COUNTED advisory, never absent — an uncounted degradation is the absorbing fallback DESIGN §5 forbids\"\n".to_string()), " );\n".to_string()), " // DISCRIMINATING CONTROL for the occurrence ratchet (codex reviews\n".to_string()), " // 45464 and 45491). A (module, method, receiver_shape) key bounds\n".to_string()), " // WHERE an unresolved call may live but not HOW MANY, and the rows\n".to_string()), " // need not be singletons (the multi-occurrence rows this once named\n".to_string()), " // were deleted at zero observed — see frontier_occurrence_budget_note —\n".to_string()), " // so the control takes whichever row survives and counts against\n".to_string()), " // its declared receiver shape rather than against Primitive()).\n".to_string()), " // The comparison is EQUALITY, not a ceiling: a ceiling lets seven\n".to_string()), " // shrink to six and a seventh come back silently, which is a static\n".to_string()), " // limit rather than a ratchet. Equality is safe because the check runs\n".to_string()), " // per MODULE, and every occurrence in a module is present whenever\n".to_string()), " // that module is typechecked at all — a closure that omits the module\n".to_string()), " // never runs its rows. Exercised at the mechanism so the boundary is\n".to_string()), " // exact on both sides.\n".to_string()), " let budget_row = rows.iter()\n".to_string()), " .next()\n".to_string()), " .expect(\"the frontier must hold at least one row to bound\");\n".to_string()), " let probe_span = || std::rc::Rc::new(crate::std_types::SourceSpan {\n".to_string()), " file: \"probe.dag\".to_string(), start: 0, end: 0,\n".to_string()), " });\n".to_string()), " let unestablished_at = |n: usize| {\n".to_string()), " std::rc::Rc::new((0..n).map(|_| std::rc::Rc::new(crate::v1_std_core::ErrorNode {\n".to_string()), " diagnostic: std::rc::Rc::new(crate::v1_std_core::CompilerDiagnostic::MethodExistenceFrontierAdmitted {\n".to_string()), " method: budget_row.method.clone(),\n".to_string()), " receiver_type: budget_row.receiver_shape.clone(),\n".to_string()), " trigger: String::new(),\n".to_string()), " span: probe_span(),\n".to_string()), " }),\n".to_string()), " module_name: budget_row.module_name.clone(),\n".to_string()), " })).collect::>())\n".to_string()), " };\n".to_string()), " let budget_at = |n: usize| crate::v1_compiler_infer::frontier_occurrence_budget_diags(\n".to_string()), " budget_row.module_name.clone(), probe_span(), unestablished_at(n));\n".to_string()), " assert!(\n".to_string()), " budget_at(budget_row.occurrences as usize).is_empty(),\n".to_string()), " \"exactly the declared occurrence count must pass\"\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " budget_at(budget_row.occurrences as usize + 1).iter().any(|d| matches!(*d.diagnostic, crate::v1_std_core::CompilerDiagnostic::FrontierOccurrenceBudgetExceeded { .. })),\n".to_string()), " \"one MORE than the declared count must refuse — otherwise the row bounds where an unresolved call may live but not how many\"\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " budget_at(budget_row.occurrences as usize + 1).iter().all(|d| crate::v1_std_core::is_error_diagnostic(d.diagnostic.clone())),\n".to_string()), " \"...and that refusal must BLOCK, or the ratchet is decorative\"\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " budget_at(0).iter().any(|d| matches!(*d.diagnostic, crate::v1_std_core::CompilerDiagnostic::FrontierOccurrenceBudgetExceeded { .. })),\n".to_string()), " \"FEWER than declared must ALSO refuse, and this is the half that makes it a ratchet rather than a ceiling: fixing a call forces the declared count DOWN, so a later reintroduction has no headroom to slip back into (codex review 45491)\"\n".to_string()), " );\n".to_string()), " // DISCRIMINATING PAIR for the early-return walk. An early return is a\n".to_string()), " // second exit from the same declaration and must meet its declared\n".to_string()), " // type; a return inside a nested LAMBDA belongs to the lambda's own\n".to_string()), " // callable return, so checking it against the enclosing declaration\n".to_string()), " // fabricates a refusal — the mirror image of the hole the walk closes\n".to_string()), " // (codex reviews 45472 and 45481, both confirmed by execution).\n".to_string()), " let early_return = compile_one(\"early_return.dag\",\n".to_string()), " \"module early_return\\nfn f(cond: Bool) -> Int { if cond { return \\\"wrong\\\" } 1 }\\n\".to_string());\n".to_string()), " assert!(\n".to_string()), " early_return.diagnostics.iter().any(|d| matches!(*d.diagnostic, crate::v1_std_core::CompilerDiagnostic::TypeMismatch { .. })),\n".to_string()), " \"an early return of the wrong type must refuse — the trailing expression conforming says nothing about the other exit, got: {:?}\",\n".to_string()), " early_return.diagnostics\n".to_string()), " );\n".to_string()), " let lambda_return = compile_one(\"lambda_return.dag\",\n".to_string()), " \"module lambda_return\\nfn apply_it(g: fn(Int) -> String, v: Int) -> String { g(v) }\\nfn outer(v: Int) -> Int { apply_it(g: x => { return \\\"inner\\\" }, v: v) 1 }\\n\".to_string());\n".to_string()), " assert!(\n".to_string()), " lambda_return.diagnostics.iter().all(|d| !matches!(*d.diagnostic, crate::v1_std_core::CompilerDiagnostic::TypeMismatch { .. })),\n".to_string()), " \"a return inside a nested lambda belongs to the LAMBDA's declared return, not the enclosing function's — checking it here fabricates a refusal, got: {:?}\",\n".to_string()), " lambda_return.diagnostics\n".to_string()), " );\n".to_string()), " let peel_red = compile_one(\"peel_red.dag\", peel_src(\"filter_map(x => x)\"));\n".to_string()), " assert!(\n".to_string()), " peel_red.diagnostics.iter().any(|d| matches!(*d.diagnostic, crate::v1_std_core::CompilerDiagnostic::MethodNotFound { .. })),\n".to_string()), " \"peeling must make the receiver DECIDABLE, not merely quiet: a method absent from the peeled base must refuse as MethodNotFound rather than resting in the frontier, got: {:?}\",\n".to_string()), " peel_red.diagnostics\n".to_string()), " );\n".to_string()), " })\n".to_string()), " .expect(\"failed to spawn thread\")\n".to_string()), " .join();\n".to_string()), " result.expect(\"method_existence_wall_witness panicked\");\n".to_string()), " }\n\n".to_string()) } pub fn ct_declared_type_conformance_witness_test() -> String { diff --git a/src/v1/stage0/src/v1_compiler_infer.rs b/src/v1/stage0/src/v1_compiler_infer.rs index ec8c8dcd1d9..96fe419b39a 100644 --- a/src/v1/stage0/src/v1_compiler_infer.rs +++ b/src/v1/stage0/src/v1_compiler_infer.rs @@ -3244,7 +3244,7 @@ pub fn where_refinement_predicates_equivalent( } pub fn where_predicate_guaranteed_min_length(pred_name: String) -> Option { - if (pred_name.clone() == "non_empty".to_string()) { + if (pred_name.clone() == "string_non_empty".to_string()) { Some(1) } else { if (pred_name.clone() == "lower_hex_16".to_string()) { @@ -3268,7 +3268,7 @@ pub fn where_predicate_guaranteed_min_length(pred_name: String) -> Option { } pub fn where_predicate_required_min_length(pred_name: String) -> Option { - if (pred_name.clone() == "non_empty".to_string()) { + if (pred_name.clone() == "string_non_empty".to_string()) { Some(1) } else { std::option::Option::None @@ -3397,7 +3397,7 @@ pub fn where_refinement_is_int_literal_predicate(pred_name: String) -> bool { } pub fn where_refinement_is_string_literal_predicate(pred_name: String) -> bool { - (((((((pred_name.clone() == "non_empty".to_string()) + (((((((pred_name.clone() == "string_non_empty".to_string()) || (pred_name.clone() == "lower_hex_64".to_string())) || (pred_name.clone() == "lower_hex_40".to_string())) || (pred_name.clone() == "lower_hex_128".to_string())) @@ -3418,7 +3418,7 @@ pub fn where_refinement_is_deferred_predicate(pred_name: String) -> bool { } pub fn decidable_where_string_predicate_holds(pred_name: String, value: String) -> Option { - if (pred_name.clone() == "non_empty".to_string()) { + if (pred_name.clone() == "string_non_empty".to_string()) { Some((v1_rt::string_length(&value) > 0)) } else { if (pred_name.clone() == "lower_hex_64".to_string()) { @@ -9768,7 +9768,7 @@ pub fn method_existence_wall_note() -> String { pub fn where_refinement_receiver_peel_note() -> String { thread_local! { static CACHED: String = { - "A where-refinement type is a Conj carrying its base as its single child and its predicates in type_annotation, and resolve_method_receiver_type SHORT-CIRCUITS on connective == Conj — it treats any product as already-structural and returns it untouched. So NonEmptyStr, declared `String where non_empty`, reached method lookup as Product(NonEmptyStr) and String's algebra profile was never consulted: `.length()` on a branded string had no surface to resolve against and no surface to prove absence against either, which put 12 correct corpus sites (8 in extdeps.filesystem.linux, 4 across gunbc.design) in the wall's undecided residue. This peel is the fix, and the FIRST version of it was a §3 violation that this note asserted its way past — worth recording, because the note is where the defect actually lived. It hand-rolled a second recursive walker over the Conj/annotation/single-child shape and then CLAIMED, in this sentence, that the refinement chain had one traversal authority and the peel was its second consumer. Both walkers independently encoded the shape test, the lookup_type_for base resolution and the recursion, so they could drift apart silently; the prose asserted the property instead of the code establishing it (codex review 45410). WHY THESE READ NODE STORAGE DIRECTLY, since it is asked and the answer is not a per-function one: they are 2 of the 589 direct Node-storage reads in this file (579 of them on origin/main), which is the v1 seed's pervasive and only idiom — the seed IS the traversal, the stage that walks the tree so that later stages need not. There is no canonical query or fold surface reachable from here: fold_node and node_query live in src/v2/std, no v1 seed module imports v2 at all, and v1 COMPILES v2, so routing v1 inference through v2's fold inverts the bootstrap rather than tidying it. DESIGN's fold_node line is scoped to the 7 v2 stages and is a DRY example within v2, not a rule binding the seed. So the disposition here is the SEED'S disposition, the same trigger the hand-Rust receipt carries — the v1 seed shrinks to zero at v2 self-host and these dissolve with it — and attaching a separate per-function trigger to 2 reads while 587 identical reads beside them carry none would be a fabricated bound, describing separable work that does not exist (codex review 45570). The repair is the extraction the claim described: where_refinement_chain is the one walk, it yields the refinement chain from the surface alias down to its ground base, and it has exactly two consumers — type_where_refinement_predicates_transitive flat_maps the immediate predicates over the chain, and peel_where_refinement_base takes its last link. The shape test itself is is_where_refinement_type, held once. Now there is one traversal authority, and it is one because the code says so. It runs only where the wall was already about to refuse or admit, so no previously-resolving call changes meaning; tier0 keeps first claim on the unpeeled receiver, which is what preserves a method declared on the brand itself. The consequence that matters is not that 12 sites went green — it is that they became DECIDABLE IN BOTH DIRECTIONS: once the peeled receiver is kernel-profiled, a method genuinely absent from String now refuses as MethodNotFound instead of resting in the frontier. Widening what the wall can decide is the only move that shrinks the frontier without either fabricating a success or fabricating a refusal.".to_string() + "A where-refinement type is a Conj carrying its base as its single child and its predicates in type_annotation, and resolve_method_receiver_type SHORT-CIRCUITS on connective == Conj — it treats any product as already-structural and returns it untouched. So NonEmptyStr, declared `String where string_non_empty`, reached method lookup as Product(NonEmptyStr) and String's algebra profile was never consulted: `.length()` on a branded string had no surface to resolve against and no surface to prove absence against either, which put 12 correct corpus sites (8 in extdeps.filesystem.linux, 4 across gunbc.design) in the wall's undecided residue. This peel is the fix, and the FIRST version of it was a §3 violation that this note asserted its way past — worth recording, because the note is where the defect actually lived. It hand-rolled a second recursive walker over the Conj/annotation/single-child shape and then CLAIMED, in this sentence, that the refinement chain had one traversal authority and the peel was its second consumer. Both walkers independently encoded the shape test, the lookup_type_for base resolution and the recursion, so they could drift apart silently; the prose asserted the property instead of the code establishing it (codex review 45410). WHY THESE READ NODE STORAGE DIRECTLY, since it is asked and the answer is not a per-function one: they are 2 of the 589 direct Node-storage reads in this file (579 of them on origin/main), which is the v1 seed's pervasive and only idiom — the seed IS the traversal, the stage that walks the tree so that later stages need not. There is no canonical query or fold surface reachable from here: fold_node and node_query live in src/v2/std, no v1 seed module imports v2 at all, and v1 COMPILES v2, so routing v1 inference through v2's fold inverts the bootstrap rather than tidying it. DESIGN's fold_node line is scoped to the 7 v2 stages and is a DRY example within v2, not a rule binding the seed. So the disposition here is the SEED'S disposition, the same trigger the hand-Rust receipt carries — the v1 seed shrinks to zero at v2 self-host and these dissolve with it — and attaching a separate per-function trigger to 2 reads while 587 identical reads beside them carry none would be a fabricated bound, describing separable work that does not exist (codex review 45570). The repair is the extraction the claim described: where_refinement_chain is the one walk, it yields the refinement chain from the surface alias down to its ground base, and it has exactly two consumers — type_where_refinement_predicates_transitive flat_maps the immediate predicates over the chain, and peel_where_refinement_base takes its last link. The shape test itself is is_where_refinement_type, held once. Now there is one traversal authority, and it is one because the code says so. It runs only where the wall was already about to refuse or admit, so no previously-resolving call changes meaning; tier0 keeps first claim on the unpeeled receiver, which is what preserves a method declared on the brand itself. The consequence that matters is not that 12 sites went green — it is that they became DECIDABLE IN BOTH DIRECTIONS: once the peeled receiver is kernel-profiled, a method genuinely absent from String now refuses as MethodNotFound instead of resting in the frontier. Widening what the wall can decide is the only move that shrinks the frontier without either fabricating a success or fabricating a refusal.".to_string() }; } CACHED.with(|c: &String| c.clone()) diff --git a/src/v1/stage0/src/v1_compiler_parse.rs b/src/v1/stage0/src/v1_compiler_parse.rs index 0e333433843..07cb54514ae 100644 --- a/src/v1/stage0/src/v1_compiler_parse.rs +++ b/src/v1/stage0/src/v1_compiler_parse.rs @@ -6136,13 +6136,13 @@ pub fn parse_single_predicate(tokens: Rc, ctx: Rc) -> } } EatResult::EatUnchanged { tokens: __eu, .. } => match pred_name.clone().as_str() { - "non_empty" => parsed_predicate_result( + "string_non_empty" => parsed_predicate_result( tokens.clone(), ctx.clone(), |value_identity, predicate_identity| { crate::v1_std_core::make_field_init_node( predicate_identity.clone(), - "non_empty".to_string(), + "string_non_empty".to_string(), crate::v1_std_core::make_expr_node( value_identity.clone(), Rc::new(ExprData::ExprLiteral {