mirror of
https://github.com/ziglang/zig.git
synced 2026-02-01 12:13:44 +00:00
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.
This commit is contained in:
parent
e86ff712a6
commit
4fccc95b01
@ -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`.
|
||||
|
||||
44
src/type.zig
44
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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user