Files
sx/examples/diagnostics/1200-diagnostics-null-coalesce-non-optional.sx
agra 58f97fff10 fix: diagnose ?? with a non-optional lhs instead of codegen panic (issue 0172)
lowerNullCoalesce fed resolveOptionalInner's .unresolved (returned for a
non-optional lhs) into the merge-block params / optionalUnwrap / RHS
target type, reaching codegen and panicking 'unresolved type reached
LLVM emission'. Guard: when inferExprType(nc.lhs) is a resolved
non-optional type, emit a located diagnostic and bail; an .unresolved
lhs (prior error) is excluded to avoid double-report. ?? is optional-only
per specs.md (error unions use or/catch), so rejecting a failable lhs is
correct; comptime panic closed too.

Regression: examples/diagnostics/1200-diagnostics-null-coalesce-non-optional.sx.
Verified by 3 adversarial reviews, suite 790/0. Filed adjacent bug 0180
(?? lowering defects for generic/alias/tuple optional lhs).
2026-06-23 03:31:58 +03:00

18 lines
924 B
Plaintext

// `??` (null-coalesce) requires an optional left operand. A resolved
// non-optional lhs is malformed user input and must be a clean, located type
// error — not a compiler crash. Regression (issue 0172): `lowerNullCoalesce`
// used to feed the `.unresolved` inner type (from `resolveOptionalInner` on a
// non-optional lhs) straight into the merge-block params / `optionalUnwrap` /
// the RHS target type, which reached emit_llvm's "unresolved type reached LLVM
// emission" panic (exit 134) with no diagnostic. A guard now inspects the
// inferred lhs type: a resolved non-optional emits this error and bails before
// codegen; an already-`.unresolved` lhs (a prior error, e.g. undefined name)
// passes through untouched so the original diagnostic isn't double-reported.
#import "modules/std.sx";
main :: () {
x := 5 ?? 7; // <- left operand of '??' must be an optional, but has type 'i64'
print("{}\n", x);
}