aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Module.zig4
-rw-r--r--src/type.zig44
2 files changed, 37 insertions, 11 deletions
diff --git a/src/Module.zig b/src/Module.zig
index c66509f33a..1cb890b886 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -821,6 +821,8 @@ pub const ErrorSet = struct {
}
};
+pub const RequiresComptime = enum { no, yes, unknown, wip };
+
/// Represents the data that a struct declaration provides.
pub const Struct = struct {
/// The Decl that corresponds to the struct itself.
@@ -849,6 +851,7 @@ pub const Struct = struct {
/// If true, definitely nonzero size at runtime. If false, resolving the fields
/// is necessary to determine whether it has bits at runtime.
known_has_bits: bool,
+ requires_comptime: RequiresComptime = .unknown,
pub const Fields = std.StringArrayHashMapUnmanaged(Field);
@@ -1038,6 +1041,7 @@ pub const Union = struct {
// which `have_layout` does not ensure.
fully_resolved,
},
+ requires_comptime: RequiresComptime = .unknown,
pub const Field = struct {
/// undefined until `status` is `have_field_types` or `have_layout`.
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,