test(ir): lock coercion forms before A4.3 extraction (A4.3 scaffolding step 1)

Test-first scaffolding ahead of extracting src/ir/conversions.zig — no code
change to the coercion targets (lowerXX / coerceToType / coerceOrErase /
buildProtocolErasure / tryUserConversion / failable-adapter selection).

Adds 4 .ir snapshots (first .ir for 01xx/09xx/10xx), each captured surgically
via `sx ir | normalize_ir`, path-free, idempotent, and print-free at IR-gen time
(0114-types-build-block-convert was rejected — it prints `--- void / 0 args ---`
+ sx source at IR-gen):
- 0107-types-int-cmp-in-float-ternary   numeric int<->float coercion
- 0903-optionals-optional-roundtrip     optional wrap/unwrap
- 0904-optionals-any-to-string-optional xx unbox_any + optional
- 1004-errors-try                       error-channel adapter/coercion

Protocol erasure + user Into are already pinned by the 04xx snapshots
(0400/0413/0414/0416); duplicate-conversion rejection by the 0410/0411/0412
anchors.

Adds 1 unit test via the public surface (no new exposure, mirroring A4.1/A4.2
sub-step 1): optionalOfFlattened — the optional wrap/flatten coercion rule
(T -> ?T; ?T -> ?T, never ??T; contrasted with the non-flattening optionalOf).
The lowerXX/coerceToType/coerceOrErase/buildProtocolErasure decisions are private
+ emission-bound, so their CoercionPlan unit tests land with the extracted module
in sub-step 2.

zig build, zig build test, tests/run_examples.sh (357/0) all green.
This commit is contained in:
agra
2026-06-02 22:32:01 +03:00
parent 137285f33d
commit 50dd2cc3d8
5 changed files with 14171 additions and 0 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -879,3 +879,27 @@ test "protocols: registerProtocolDecl builds the dispatch method table" {
try std.testing.expect(info.methods[1].ret_is_self);
try std.testing.expectEqual(module.types.ptrTo(.void), info.methods[1].ret_type);
}
// ── A4.3 test-first scaffolding: coercion planning ───────────────────
// Lock the one coercion-plan decision reachable via the existing public
// surface — the optional wrap/flatten rule — before coercion planning moves to
// `src/ir/conversions.zig`. The lowerXX / coerceToType / coerceOrErase /
// buildProtocolErasure decisions are private + emission-bound, so their
// CoercionPlan unit tests land with the extracted module in sub-step 2 (as the
// generics/protocols plan tests landed with their modules); behavior is locked
// here by the new `.ir` snapshots.
test "conversions: optionalOfFlattened wraps once, flattening a nested optional" {
const alloc = std.testing.allocator;
var module = ir_mod.Module.init(alloc);
defer module.deinit();
var l = Lowering.init(&module);
const opt_s64 = module.types.optionalOf(.s64);
// Wrap a non-optional: T -> ?T.
try std.testing.expectEqual(opt_s64, l.optionalOfFlattened(.s64));
// Wrap an already-optional FLATTENS: ?T -> ?T (the coercion never builds ??T).
try std.testing.expectEqual(opt_s64, l.optionalOfFlattened(opt_s64));
// Contrast: the plain wrap does NOT flatten — ?T -> ??T (distinct type).
try std.testing.expect(module.types.optionalOf(opt_s64) != opt_s64);
}