In type position (T) is a 1-tuple (specs.md:843), so ?(?i64) is optional(tuple(?i64)); assigning a bare ?i64 had coerceToType classify .none and pass the value through, then optionalWrap built a corrupt insertvalue that aborted the LLVM verifier. After coercing toward an optional's child, verify the coerced type equals the child type (stmt.zig decl-init + coerce.zig .optional_wrap); on mismatch emit a located diagnostic (tuple-specific note only when the child is a tuple). formatTypeName now renders tuples as (x: i64, y: i64). Regressions: optionals/0911 (nested optional via alias, round-trip), diagnostics/1195 (the mismatch diagnostic). Updated diagnostics/1101 + protocols/0414 goldens for the improved tuple type-name rendering. Verified by 3 adversarial reviews. Filed adjacent bug 0171 (?any child not canonicalized).
19 lines
818 B
Plaintext
19 lines
818 B
Plaintext
// `?(?i64)` is `optional` wrapping the SINGLE-FIELD TUPLE `(?i64)` — in type
|
|
// position `(T)` is a 1-tuple, not a grouping (specs.md §"Tuple Types"). So
|
|
// assigning a bare `?i64` value to a `?(?i64)` slot is a type mismatch: the
|
|
// optional's payload is the tuple `(?i64)`, not `?i64`.
|
|
//
|
|
// Regression (issue 0165): this used to silently lower to a malformed
|
|
// `insertvalue { {{i64,i1}}, i1 }` that aborted the LLVM verifier. It now
|
|
// produces a clean diagnostic naming the payload type and pointing at the
|
|
// parens-are-a-tuple gotcha. (To write a genuine nested optional, alias the
|
|
// inner one: `Opt :: ?i64; x : ?Opt = ...` — see
|
|
// examples/optionals/0911-nested-optional-via-alias.sx.)
|
|
#import "modules/std.sx";
|
|
|
|
main :: () {
|
|
inner : ?i64 = 5;
|
|
outer : ?(?i64) = inner;
|
|
print("unreachable\n");
|
|
}
|