diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2025-01-19 23:19:59 +0000 |
|---|---|---|
| committer | Matthew Lugg <mlugg@mlugg.co.uk> | 2025-01-21 02:41:42 +0000 |
| commit | 0ec6b2dd883568900aa28dd5fea6d22258eed792 (patch) | |
| tree | 5c731f5f54deb17b0e8bf674be1ba29052f7a3ea /src/codegen | |
| parent | 216e0f37306d5cded92d547f65f9c2566d7b1523 (diff) | |
| download | zig-0ec6b2dd883568900aa28dd5fea6d22258eed792.tar.gz zig-0ec6b2dd883568900aa28dd5fea6d22258eed792.zip | |
compiler: simplify generic functions, fix issues with inline calls
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
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/c.zig | 1 | ||||
| -rw-r--r-- | src/codegen/c/Type.zig | 1 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 2 | ||||
| -rw-r--r-- | src/codegen/spirv.zig | 1 |
4 files changed, 0 insertions, 5 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index bbb06ae06f..5364b0432d 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -968,7 +968,6 @@ pub const DeclGen = struct { .null => unreachable, .empty_tuple => unreachable, .@"unreachable" => unreachable, - .generic_poison => unreachable, .false => try writer.writeAll("false"), .true => try writer.writeAll("true"), diff --git a/src/codegen/c/Type.zig b/src/codegen/c/Type.zig index 20ba8fe6c0..2673576b90 100644 --- a/src/codegen/c/Type.zig +++ b/src/codegen/c/Type.zig @@ -1451,7 +1451,6 @@ pub const Pool = struct { .bool_true, .bool_false, .empty_tuple, - .generic_poison, .none, => unreachable, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 43558a9f1d..89595f0f5c 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3372,7 +3372,6 @@ pub const Object = struct { .bool_true, .bool_false, .empty_tuple, - .generic_poison, .none, => unreachable, else => switch (ip.indexToKey(t.toIntern())) { @@ -3923,7 +3922,6 @@ pub const Object = struct { .null => unreachable, // non-runtime value .empty_tuple => unreachable, // non-runtime value .@"unreachable" => unreachable, // non-runtime value - .generic_poison => unreachable, // non-runtime value .false => .false, .true => .true, diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index ceb9c46b1b..e9322a9d70 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -941,7 +941,6 @@ const NavGen = struct { .null, .empty_tuple, .@"unreachable", - .generic_poison, => unreachable, // non-runtime values .false, .true => break :cache try self.constBool(val.toBool(), repr), |
