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:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user