aboutsummaryrefslogtreecommitdiff
path: root/src/type.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-01-20 15:36:40 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-01-20 16:17:16 -0700
commit4fccc95b0152aefeb40912768ec045b57a2fdc2b (patch)
tree711ec4766c0cd236b239eb448398d2162c770068 /src/type.zig
parente86ff712a666ab5be54fa763cc12a5f245718117 (diff)
downloadzig-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.zig44
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,