diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-01-20 15:36:40 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-01-20 16:17:16 -0700 |
| commit | 4fccc95b0152aefeb40912768ec045b57a2fdc2b (patch) | |
| tree | 711ec4766c0cd236b239eb448398d2162c770068 /src/type.zig | |
| parent | e86ff712a666ab5be54fa763cc12a5f245718117 (diff) | |
| download | zig-4fccc95b0152aefeb40912768ec045b57a2fdc2b.tar.gz zig-4fccc95b0152aefeb40912768ec045b57a2fdc2b.zip | |
Sema: fix requiresComptime infinite recursion
When asking a struct or union whether the type requires comptime, it may
need to ask itself recursively, for example because of a field which is
a pointer to itself. This commit adds a field to each to keep track of
when computing the "requires comptime" value and returns `false` if the
check is already ongoing.
Diffstat (limited to 'src/type.zig')
| -rw-r--r-- | src/type.zig | 44 |
1 files changed, 33 insertions, 11 deletions
diff --git a/src/type.zig b/src/type.zig index f7d8795162..0801d7e01f 100644 --- a/src/type.zig +++ b/src/type.zig @@ -1544,22 +1544,40 @@ pub const Type = extern union { .@"struct" => { const struct_obj = ty.castTag(.@"struct").?.data; - for (struct_obj.fields.values()) |field| { - if (requiresComptime(field.ty)) { - return true; - } + switch (struct_obj.requires_comptime) { + .no, .wip => return false, + .yes => return true, + .unknown => { + struct_obj.requires_comptime = .wip; + for (struct_obj.fields.values()) |field| { + if (requiresComptime(field.ty)) { + struct_obj.requires_comptime = .yes; + return true; + } + } + struct_obj.requires_comptime = .no; + return false; + }, } - return false; }, .@"union", .union_tagged => { const union_obj = ty.cast(Payload.Union).?.data; - for (union_obj.fields.values()) |field| { - if (requiresComptime(field.ty)) { - return true; - } + switch (union_obj.requires_comptime) { + .no, .wip => return false, + .yes => return true, + .unknown => { + union_obj.requires_comptime = .wip; + for (union_obj.fields.values()) |field| { + if (requiresComptime(field.ty)) { + union_obj.requires_comptime = .yes; + return true; + } + } + union_obj.requires_comptime = .no; + return false; + }, } - return false; }, .error_union => return requiresComptime(errorUnionPayload(ty)), @@ -3661,7 +3679,7 @@ pub const Type = extern union { .Slice, .Many, .C => true, .One => ty.elemType().zigTypeTag() == .Array, }, - .Struct => ty.tag() == .tuple, + .Struct => ty.isTuple(), else => false, }; } @@ -4501,6 +4519,10 @@ pub const Type = extern union { } }; + pub fn isTuple(ty: Type) bool { + return ty.tag() == .tuple; + } + /// The sub-types are named after what fields they contain. pub const Payload = struct { tag: Tag, |
