Summary
A user-declared ADT sharing a built-in container's name compiles to a module with no exports. data Array { Mk(Int) } with an unwrap match is vera check-green; codegen then refuses the match arm with E602 ("a scrutinee whose representation is a (ptr, len) pair — function skipped") and vera run reports Available exports: (none), against a fresh-name control that prints 7. The failure is loud, never a wrong answer.
Map, Set and Decimal shadows are inert by width-luck: their built-in width (i32) equals the ADT pointer width, the same coincidence that hid most of #1309.
Mechanism and lineage
The built-in-name branches (Array/Map/Set/Decimal/String handling) run before the declared-ADT lookup in the type derivations, so a user declaration that §8.4.1 says may shadow a prelude name still derives the built-in's representation. This is the same ordering disease as #1309 — that fix moved only the alias branch above the built-ins (_type_expr_to_wasm_type, and _return_type_is_string in the same release); the declared-ADT-vs-built-in-name ordering was not touched. Measured pre-existing at v0.1.11 — the ordering is identical there.
Why it was verified but not fixed in the v0.1.12 release round
The fix needs coordinated movement in at least three derivation sites: vera/codegen/core.py (_type_expr_to_wasm_type, ~line 2701), vera/wasm/inference.py:840 (_canonical_wasm_type), and a third derivation not yet located — with the first two fixed, the program still loses its exports. One instructive trap from the attempt: the natural getattr(self, "_adt_layouts", {}) spelling in the second site's mixin is a silent no-op, because that class carries _adt_type_names instead. A partial fix in a release commit, with no end-to-end effect, was reverted rather than shipped.
Found by the release PR's full-cycle review (PR #1330 round). Carried to the v0.1.13 queue.
Summary
A user-declared ADT sharing a built-in container's name compiles to a module with no exports.
data Array { Mk(Int) }with anunwrapmatch isvera check-green; codegen then refuses the match arm with E602 ("a scrutinee whose representation is a (ptr, len) pair — function skipped") andvera runreportsAvailable exports: (none), against a fresh-name control that prints 7. The failure is loud, never a wrong answer.Map,SetandDecimalshadows are inert by width-luck: their built-in width (i32) equals the ADT pointer width, the same coincidence that hid most of #1309.Mechanism and lineage
The built-in-name branches (
Array/Map/Set/Decimal/Stringhandling) run before the declared-ADT lookup in the type derivations, so a user declaration that §8.4.1 says may shadow a prelude name still derives the built-in's representation. This is the same ordering disease as #1309 — that fix moved only the alias branch above the built-ins (_type_expr_to_wasm_type, and_return_type_is_stringin the same release); the declared-ADT-vs-built-in-name ordering was not touched. Measured pre-existing at v0.1.11 — the ordering is identical there.Why it was verified but not fixed in the v0.1.12 release round
The fix needs coordinated movement in at least three derivation sites:
vera/codegen/core.py(_type_expr_to_wasm_type, ~line 2701),vera/wasm/inference.py:840(_canonical_wasm_type), and a third derivation not yet located — with the first two fixed, the program still loses its exports. One instructive trap from the attempt: the naturalgetattr(self, "_adt_layouts", {})spelling in the second site's mixin is a silent no-op, because that class carries_adt_type_namesinstead. A partial fix in a release commit, with no end-to-end effect, was reverted rather than shipped.Found by the release PR's full-cycle review (PR #1330 round). Carried to the v0.1.13 queue.