The original motivation here was to fix regressions caused by #22414. However, while working on this, I ended up discussing a language simplification with Andrew, which changes things a little from how they worked before #22414. The main user-facing change here is that any reference to a prior function parameter, even if potentially comptime-known at the usage site or even not analyzed, now makes a function generic. This applies even if the parameter being referenced is not a `comptime` parameter, since it could still be populated when performing an inline call. This is a breaking language change. The detection of this is done in AstGen; when evaluating a parameter type or return type, we track whether it referenced any prior parameter, and if so, we mark this type as being "generic" in ZIR. This will cause Sema to not evaluate it until the time of instantiation or inline call. A lovely consequence of this from an implementation perspective is that it eliminates the need for most of the "generic poison" system. In particular, `error.GenericPoison` is now completely unnecessary, because we identify generic expressions earlier in the pipeline; this simplifies the compiler and avoids redundant work. This also entirely eliminates the concept of the "generic poison value". The only remnant of this system is the "generic poison type" (`Type.generic_poison` and `InternPool.Index.generic_poison_type`). This type is used in two places: * During semantic analysis, to represent an unknown result type. * When storing generic function types, to represent a generic parameter/return type. It's possible that these use cases should instead use `.none`, but I leave that investigation to a future adventurer. One last thing. Prior to #22414, inline calls were a little inefficient, because they re-evaluated even non-generic parameter types whenever they were called. Changing this behavior is what ultimately led to #22538. Well, because the new logic will mark a type expression as generic if there is any change its resolved type could differ in an inline call, this redundant work is unnecessary! So, this is another way in which the new design reduces redundant work and complexity. Resolves: #22494 Resolves: #22532 Resolves: #22538
Test Case Quick Reference
Use comments at the end of the file to indicate metadata about the test case. Here are examples of different kinds of tests:
Compile Error Test
If you want it to be run with zig test and match expected error messages:
// error
// is_test=true
//
// :4:13: error: 'try' outside function scope
Execution
This will do zig run on the code and expect exit code 0.
// run
Translate-c
If you want to test translating C code to Zig use translate-c:
// translate-c
// c_frontend=aro,clang
// target=x86_64-linux
//
// pub const foo = 1;
// pub const immediately_after_foo = 2;
//
// pub const somewhere_else_in_the_file = 3:
Run Translated C
If you want to test translating C code to Zig and then executing it use run-translated-c:
// run-translated-c
// c_frontend=aro,clang
// target=x86_64-linux
//
// Hello world!
Incremental Compilation
Make multiple files that have ".", and then an integer, before the ".zig" extension, like this:
hello.0.zig
hello.1.zig
hello.2.zig
Each file can be a different kind of test, such as expecting compile errors, or expecting to be run and exit(0). The test harness will use these to simulate incremental compilation.
At the time of writing there is no way to specify multiple files being changed as part of an update.
Subdirectories
Subdirectories do not have any semantic meaning but they can be used for organization since the test harness will recurse into them. The full directory path will be prepended as a prefix on the test case name.
Limiting which Backends and Targets are Tested
// run
// backend=stage2,llvm
// target=x86_64-linux,x86_64-macos
Possible backends are:
stage1: equivalent to-fstage1.stage2: equivalent to passing-fno-stage1 -fno-LLVM.llvm: equivalent to-fLLVM -fno-stage1.