`constant: U : value` produced a constant of the wrong type:
lb_const_value took its union-lowering branch only when
`is_type_union_constantable(type)` held, so for a union with a variant
that whitelist rejects (`union{bool, ^int}`) the value fell through to
the scalar branch and reached `LLVMConstInt(lb_type(m, union_type),
...)`. The constant emitted there does not match the union's type:
bytes that change between runs for `true`, a compiler crash for `1.0`,
an `is_type_string` assertion for a string literal.
The checker already resolves which variant a constant represents and
records it in `ExactValue::variant_type` - the variant type, tag index,
payload and padding the union branch needs - so that branch is now also
taken when the value pins a variant this backend can build as a
constant. The type-level whitelist was re-guessing information the
value already carries; variant types this backend cannot build as
constants (`any`) stay excluded.
lb_build_static_variables had the same defect in another place: it
lowered an initializer with the expression's type instead of the
declared type, so `@(static) s: U` emitted a payload-only constant and
LLVM rejected the module with “Global variable initializer type does not
match global variable type!”. It now passes the declared type and gives
the global the constant's layout-compatible type, the way the file-scope
path already does.
Blast radius: every union-typed constant, i.e. typed constants, global
static initializers, @(static)/@(thread_local)/@(rodata), default
parameters and constant aggregate elements. Unions whose variants are
all constantable keep the previous path.
Note that with this commit, casting through
multiply-nested unions is forbidden, e.g.
```
U :: union {int, V}
V :: union {bool}
x: U = true
```
does not compile.
(Previously the compiler would simply crash)
This is to avoid situations where adding variants
can lead to unexpected changes in the value.
For example if `U` is changed to have a `bool`
variant of its own:
```
U :: union {int, bool, V}
```
Then `x: U = true` would equal
`U(true)` instead of `U(V(true))`.
Single-variant unions are exempt, primarily to
improve the ergonomics of `Maybe` in cases like:
```
x: Maybe(union{int, bool}) = 1
```
Fix#6100Fix#6699Fix#6895Fix#6896Fix#6897Fix#7036Fix#7083Fix#7091
Broadcasting `field = value` compound literals
would assert.
This is because we were checking for a
`field = value` compound before checking
if the types matched, and thus could broadcast.
when iterating the values of an array literal,if one of the values
is a function with multiple returns, it doesn't offset the struct
field index by the number of values.