`expr?` previously did a brain-dead RET through whatever AX/DX/CX held — only safe when operand and enclosing fn had identical variant ordering. Tests relied on that alignment by construction. Now: - Typecheck: each non-first variant of operand must appear as a variant of the enclosing fn's return tagged union. Enclosing must itself be tagged (a non-tagged return has no slot for errors to land in). - Cgen: on tag != 0, walk operand's error variants and emit a conditional tag remap (cmp/jne/mov/jmp) for any whose index in enclosing differs from operand's. Identity cases emit nothing, so same-shape operands cost zero extra instructions. Selfhost cgen doesn't implement N_TRYPROP at all (no selfhost source uses `?`); byte-identity tests still pass. One existing e2e row used `?` with main returning i32 — relied on the old loose semantics. Switched to `!` (abort-on-error); it was exercising success-unwrap, not propagation.
5.8 KiB
5.8 KiB