* If more than one error is reported for the same Decl, the first error
message is kept and the second one discarded.
* Prevent functions from being sent to codegen backends if there were
any errors resolving any of their parameter types or return type.
There was a simple missing check of adding an inferred error set to
itself, in which case we should not try to mutate the hash map while
iterating over it.
Instead, use ResultLoc.none to allow for the expression type to be
inferred [^1]. This effectively moves the type coercion to Sema, in
order to turn comptime values into usable values for the backends to
consume. Right now the coercion is applies as comptime_int -> usize and
comptime_float -> f64, as an arbitrary choice.
[^1]: 9f25c8140c/src/AstGen.zig (L207-L208)
An assembly expression in a comptime block is legal Zig in the case of
global assembly [^1]. Instead of unconditionally asserting that the
expression lives in a runtime block, here we assert that if the
expression lives in a comptime block it must be outside of function
scope.
[^1]: https://ziglang.org/documentation/0.9.1/#Global-Assembly
* Sema: store the precomputed monomorphed_funcs hash inside Module.Fn.
This is important because it may be accessed when resizing monomorphed_funcs
while this Fn has already been added to the set, but does not have the
owner_decl, comptime_args, or other fields populated yet.
* Sema: in `analyzeIsNonErr`, take advantage of the AIR tag being
`wrap_errunion_payload` to infer that `is_non_err` is comptime true
without performing any error set resolution.
- Also add some code to check for empty inferred error sets in this
function. If necessary we do resolve the inferred error set.
* Sema: queue full type resolution of payload type when
`wrap_errunion_payload` AIR instruction is emitted. This ensures the
backend may check the alignment of it.
* Sema: resolveTypeFully now additionally resolves comptime-only
status.
closes#11306
This commit introduces a new AIR instruction `cmp_lt_errors_len`. It's
specific to this use case for two reasons:
* The total number of errors is not stable during semantic analysis; it
can only be reliably checked when flush() is called. So the backend
that is lowering the instruction must emit a relocation of some kind
and then populate it during flush().
* The fewer AIR instructions in memory, the better for compiler
performance, so we squish complex meanings into AIR tags without
hesitation.
The instruction is implemented only in the LLVM backend so far. It does
this by creating a simple function which is gutted and re-populated
with each flush().
AstGen now uses ResultLoc.coerced_ty for `@intToError` and Sema does the
coercion.
* In semaStructFields and semaUnionFields we return error.GenericPoison
if one of the field types ends up being generic poison.
- This requires handling function calls and function types taking
this into account when calling `typeRequiresComptime` on the return
type.
* Unrelated: I noticed using Valgrind that struct reification did not
populate the `known_opv` field. After fixing it, the behavior tests
run Valgrind-clean.
* ZIR: use `@ptrCast` to cast between slices instead of exploiting
the fact that stage1 incorrectly allows `@bitCast` between slices.
- A future enhancement will make Zig support `@ptrCast` to directly
cast between slices.
To no longer set the error code to undefined. This fixes the problem
where an undefined single-item pointer coerced to an error union of a
slice set the whole thing to undefined even though the sub-coercion to
the slice would have produced a defined value.
Sema:
* queue full resolution of std.builtin.Type.Error when doing `@typeInfo`
for error sets.
LLVM backend:
* change a TODO comment to a proper explanation of why debug info
for structs is left as a fwd decl sometimes.
* remove handling of packed unions which does not match the type
information or constant generation code.
* remove copy+pasted code
* fix union debug info not matching the memory layout
* remove unnecessary error checks and type casting
* Added peer type resolution for arrays and vectors: the vector type is
selected.
* Fixed passing the lhs type or rhs type instead of the peer resolved
type when calling Value methods during analyzeArithmetic handling of
comptime expressions.
* `checkVectorizableBinaryOperands` now allows mixing vectors and
arrays, as long as one of the operands is a vector.
This matches stage1's handling of `^=` but apparently stage1 is
inconsistent and does not handle e.g. `*=`. stage2 now will always allow
mixing vector and array operands for all operations.
We are putting off actual optimization of floats because we have a
couple proposals being considered which would change how it works.
In the meantime, lowering optimized float mode to be the same as
strict is a perfectly legal way to implement the Zig language specification.
* AstGen: restore the param_type ZIR instruction and pass it to the
expression for function call arguments. This does not solve the
problem for generic function parameters, but it catches stage2 up to
stage1 which also does not solve the problem for generic function
parameters.
- Most of the enhancements in this commit will still be needed for a
more sophisticated further improvement to handle generic function
types.
- In Sema, handling of `as` coercion recognizes the `var_args_param`
Type Tag and passes the operand through doing no coercion.
- That was the last ZIR tag and we are now using all 256 ZIR tags.
* AstGen: array init and struct init expressions use the anon form even
when the result location has a type. Prevents the type system
incorrectly believing, for example, that a tuple is actually an array
when the result location is a param_type of a function with `anytype`
parameter.
* Sema: add missing coercion in `unionInit` to coerce the init to the
corresponding union field type.
* `Value.fieldValue` now takes a type and does not take an allocator.
closes#11293
After this commit, stage2 passes all the parser tests.
Closures are not necessarily constant values. For example, Zig
code might do something like this:
fn foo(x: anytype) void {
const S = struct {field: @TypeOf(x)};
}
...in which case the closure_capture instruction has access to a
runtime value only. In such case we preserve the type and use a
dummy runtime value.
closes#11292
This also fixes a bug that I didn't see causing any problems yet in
generic function instantiation where it would read from a GetOrPutResult
too late.
Also it delays full resolution of generic function type parameters until
after the function body is finished being analyzed.
closes#11291
The code for detecting when a local const initialization expression
ended up being comptime-known gave up when it encountered dbg_stmt
instructions, but such instructions are not supposed to matter.
* std.meta: correct use of `default_value` in reification. stage1
accepted a wrong type for `null`.
* Sema: after instantiating a generic function, if the return type ends
up being a comptime-known type, then we return an error, undoing the
generic function instantiation, and making a comptime function call
instead.
- We also needed to clean up the dependency graph in this case.
* Sema: reified enums set tag_ty_inferred to false since an integer tag
type is provided. This is a limitation of the `@Type` builtin which
will be addressed with #10710.
* Sema: fix resolveInferredErrorSet incorrectly calling
ensureFuncBodyAnalyzed on generic functions.
That happens after a function body is analyzed. This prevents circular
dependency compile errors and yet a way to mark types that need to be
fully resolved before a given function is sent to the codegen backend.
The runtime behavior allowed this in both stage1 and stage2, but stage1
fails with index out of bounds during comptime. This behavior makes
sense to support, and comptime behavior should match runtime behavior. I
implement this fix only in stage2.
We were enforcing bounds on the index of an elem_ptr in pointerDeref,
but we want to support out-of-bounds accesses by reinterpreting memory.
This removes that check, so that the deref falls back to bitcasting, as
usual.
This was masked by another bug that was forcing bitcasts incorrectly,
which is why this wasn't noticed earlier.
Sema.pointerDeref() assumes that elem_ptrs have been "flattened" when
they were created, so that you an elem_ptr will never be the array_ptr
of another elem_ptr when they share the same type.
Value.elemPtr does this already, but a couple of places in Sema were
bypassing this logic.