fix(0098): enum literal resolves against the unwrapped optional child; non-enum targets are diagnosed

lowerEnumLiteral resolved the variant against the raw destination type,
so any non-enum destination fell into resolveVariantValue's silent
return-0 tail with the enum_init stamped as the wrong type:

  - ?E destinations produced variant 0 mis-typed as the optional
    (observed as variant 0 OR null, layout-dependent);
  - builtin destinations (i64) silently became 0;
  - unknown variants of real enums silently became variant 0;
  - a destination-less literal panicked LLVM emission (unresolved
    type reached codegen).

Now: optional destinations unwrap to the child enum (the coercion
layer's .optional_wrap handles E -> ?E), and the remaining shapes are
diagnosed — unknown variant (with the variant list, via the new
emitBadEnumVariant twin of emitBadVariant), non-enum destination, and
no destination (cascade-guarded: silent when the destination's type
already failed to resolve and was reported).

Regression tests: examples/0183 (return/assign/reassign into ?Enum,
non-zero variants, null path) + examples/1169/1170 (each diagnostic);
all three FAIL on pre-fix master. zig build test 426/426;
tests/run_examples.sh 598/598.
This commit is contained in:
agra
2026-06-12 12:35:20 +03:00
parent d8076b9333
commit 1bc60d3a35
15 changed files with 253 additions and 1 deletions

View File

@@ -1887,6 +1887,7 @@ pub const Lowering = struct {
pub const lowerTaggedEnumLiteral = lower_expr.lowerTaggedEnumLiteral;
pub const findTaggedVariant = lower_expr.findTaggedVariant;
pub const emitBadVariant = lower_expr.emitBadVariant;
pub const emitBadEnumVariant = lower_expr.emitBadEnumVariant;
pub const resolveVariantValue = lower_expr.resolveVariantValue;
pub const resolveVariantIndex = lower_expr.resolveVariantIndex;
pub const lowerArrayLiteral = lower_expr.lowerArrayLiteral;