This implements the semantics as discussed in today's compiler meeting,
where the alignment of pointers to fields of default-layout unions
cannot exceed the field's alignment.
Resolves: #15878
Most of this migration was performed automatically with `zig fmt`. There
were a few exceptions which I had to manually fix:
* `@alignCast` and `@addrSpaceCast` cannot be automatically rewritten
* `@truncate`'s fixup is incorrect for vectors
* Test cases are not formatted, and their error locations change
Opaque and `noreturn` makes sense since they don't represent real
values, but `null` and `undefined` are perfectly normal
comptime-only values.
Closes#16088
I achieved this through a major refactor of the logic of analyzeMinMax.
This change should be compatible with vectors of comptime_int, which
Andrew said are supposed to work (but which currently do not).
We now resolve undefined symbols during incremental-compilation
where we discard the current symbol if we detect we found
an existing symbol which is not the one currently being updated.
The symbol will always be discarded in favor of the existing symbol
in such a case.
Calling into coercion logic here is a little opaque, and more to the
point wholly unnecessary. Instead, the (very short) logic is now
implemented directly in Sema.
Resolves: #16033
The existing logic for peer type resolution was quite convoluted and
buggy. This rewrite makes it much more resilient, readable, and
extensible. The algorithm works by first iterating over the types to
select a "strategy", then applying that strategy, possibly applying peer
resolution recursively.
Several new tests have been added to cover cases which the old logic did
not correctly handle.
Resolves: #15138Resolves: #15644Resolves: #15693Resolves: #15709Resolves: #15752
This is a bit harder than it seems at first glance. Actually resolving
the type is the easy part: the interesting thing is actually getting the
capture value. We split this into three cases:
* If all payload types are the same (as is required in status quo), we
can just do what we already do: get the first field value.
* If all payloads are in-memory coercible to the resolved type, we still
fetch the first field, but we also emit a `bitcast` to convert to the
resolved type.
* Otherwise, we need to handle each case separately. We emit a nested
`switch_br` which, for each possible case, gets the corresponding
union field, and coerces it to the resolved type. As an optimization,
the inner switch's 'else' prong is used for any peer which is
in-memory coercible to the target type, and the bitcast approach
described above is used.
Pointer captures have the additional constraint that all payload types
must be in-memory coercible to the resolved type.
Resolves: #2812
The idea here is that there are two ways we can reference a function at runtime:
* Through a direct call, i.e. where the function is comptime-known
* Through a function pointer
This means we can easily perform a form of rudimentary escape analysis
on functions. If we ever see a `decl_ref` or `ref` of a function, we
have a function pointer, which could "leak" into runtime code, so we
emit the function; but for a plain `decl_val`, there's no need to.
This change means that `comptime { _ = f; }` no longer forces a function
to be emitted, which was used for some things (mainly tests). These use
sites have been replaced with `_ = &f;`, which still triggers analysis
of the function body, since you're taking a pointer to the function.
Resolves: #6256Resolves: #15353