mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 12:59:04 +00:00
Sema: fix infinite recursion in explainWhyTypeIsComptime
Co-authored-by: Veikka Tuominen <git@vexu.eu>
This commit is contained in:
parent
5c9826630d
commit
86d9c3de2b
36
src/Sema.zig
36
src/Sema.zig
@ -19764,6 +19764,8 @@ fn validateRunTimeType(
|
||||
};
|
||||
}
|
||||
|
||||
const TypeSet = std.HashMapUnmanaged(Type, void, Type.HashContext64, std.hash_map.default_max_load_percentage);
|
||||
|
||||
fn explainWhyTypeIsComptime(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
@ -19771,6 +19773,22 @@ fn explainWhyTypeIsComptime(
|
||||
msg: *Module.ErrorMsg,
|
||||
src_loc: Module.SrcLoc,
|
||||
ty: Type,
|
||||
) CompileError!void {
|
||||
var type_set = TypeSet{};
|
||||
defer type_set.deinit(sema.gpa);
|
||||
|
||||
try sema.resolveTypeFully(block, src, ty);
|
||||
return sema.explainWhyTypeIsComptimeInner(block, src, msg, src_loc, ty, &type_set);
|
||||
}
|
||||
|
||||
fn explainWhyTypeIsComptimeInner(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
src: LazySrcLoc,
|
||||
msg: *Module.ErrorMsg,
|
||||
src_loc: Module.SrcLoc,
|
||||
ty: Type,
|
||||
type_set: *TypeSet,
|
||||
) CompileError!void {
|
||||
const mod = sema.mod;
|
||||
switch (ty.zigTypeTag()) {
|
||||
@ -19808,7 +19826,7 @@ fn explainWhyTypeIsComptime(
|
||||
},
|
||||
|
||||
.Array, .Vector => {
|
||||
try sema.explainWhyTypeIsComptime(block, src, msg, src_loc, ty.elemType());
|
||||
try sema.explainWhyTypeIsComptimeInner(block, src, msg, src_loc, ty.elemType(), type_set);
|
||||
},
|
||||
.Pointer => {
|
||||
const elem_ty = ty.elemType2();
|
||||
@ -19826,18 +19844,20 @@ fn explainWhyTypeIsComptime(
|
||||
}
|
||||
return;
|
||||
}
|
||||
try sema.explainWhyTypeIsComptime(block, src, msg, src_loc, ty.elemType());
|
||||
try sema.explainWhyTypeIsComptimeInner(block, src, msg, src_loc, ty.elemType(), type_set);
|
||||
},
|
||||
|
||||
.Optional => {
|
||||
var buf: Type.Payload.ElemType = undefined;
|
||||
try sema.explainWhyTypeIsComptime(block, src, msg, src_loc, ty.optionalChild(&buf));
|
||||
try sema.explainWhyTypeIsComptimeInner(block, src, msg, src_loc, ty.optionalChild(&buf), type_set);
|
||||
},
|
||||
.ErrorUnion => {
|
||||
try sema.explainWhyTypeIsComptime(block, src, msg, src_loc, ty.errorUnionPayload());
|
||||
try sema.explainWhyTypeIsComptimeInner(block, src, msg, src_loc, ty.errorUnionPayload(), type_set);
|
||||
},
|
||||
|
||||
.Struct => {
|
||||
if ((try type_set.getOrPutContext(sema.gpa, ty, .{ .mod = mod })).found_existing) return;
|
||||
|
||||
if (ty.castTag(.@"struct")) |payload| {
|
||||
const struct_obj = payload.data;
|
||||
for (struct_obj.fields.values()) |field, i| {
|
||||
@ -19845,9 +19865,10 @@ fn explainWhyTypeIsComptime(
|
||||
.index = i,
|
||||
.range = .type,
|
||||
});
|
||||
|
||||
if (try sema.typeRequiresComptime(block, src, field.ty)) {
|
||||
try mod.errNoteNonLazy(field_src_loc, msg, "struct requires comptime because of this field", .{});
|
||||
try sema.explainWhyTypeIsComptime(block, src, msg, field_src_loc, field.ty);
|
||||
try sema.explainWhyTypeIsComptimeInner(block, src, msg, field_src_loc, field.ty, type_set);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -19855,6 +19876,8 @@ fn explainWhyTypeIsComptime(
|
||||
},
|
||||
|
||||
.Union => {
|
||||
if ((try type_set.getOrPutContext(sema.gpa, ty, .{ .mod = mod })).found_existing) return;
|
||||
|
||||
if (ty.cast(Type.Payload.Union)) |payload| {
|
||||
const union_obj = payload.data;
|
||||
for (union_obj.fields.values()) |field, i| {
|
||||
@ -19862,9 +19885,10 @@ fn explainWhyTypeIsComptime(
|
||||
.index = i,
|
||||
.range = .type,
|
||||
});
|
||||
|
||||
if (try sema.typeRequiresComptime(block, src, field.ty)) {
|
||||
try mod.errNoteNonLazy(field_src_loc, msg, "union requires comptime because of this field", .{});
|
||||
try sema.explainWhyTypeIsComptime(block, src, msg, field_src_loc, field.ty);
|
||||
try sema.explainWhyTypeIsComptimeInner(block, src, msg, field_src_loc, field.ty, type_set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
const S1 = struct {
|
||||
a: S2,
|
||||
};
|
||||
const S2 = struct {
|
||||
b: fn () void,
|
||||
};
|
||||
pub export fn entry() void {
|
||||
var s: S1 = undefined;
|
||||
_ = s;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :8:12: error: variable of type 'tmp.S1' must be const or comptime
|
||||
// :2:8: note: struct requires comptime because of this field
|
||||
// :5:8: note: struct requires comptime because of this field
|
||||
// :5:8: note: use '*const fn() void' for a function pointer type
|
||||
@ -0,0 +1,18 @@
|
||||
const S = struct {
|
||||
a: fn () void,
|
||||
b: *S,
|
||||
};
|
||||
pub export fn entry() void {
|
||||
var s: S = undefined;
|
||||
_ = s;
|
||||
}
|
||||
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :6:12: error: variable of type 'tmp.S' must be const or comptime
|
||||
// :2:8: note: struct requires comptime because of this field
|
||||
// :2:8: note: use '*const fn() void' for a function pointer type
|
||||
// :3:8: note: struct requires comptime because of this field
|
||||
@ -0,0 +1,17 @@
|
||||
const U = union {
|
||||
a: fn () void,
|
||||
b: *U,
|
||||
};
|
||||
pub export fn entry() void {
|
||||
var u: U = undefined;
|
||||
_ = u;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :6:12: error: variable of type 'tmp.U' must be const or comptime
|
||||
// :2:8: note: union requires comptime because of this field
|
||||
// :2:8: note: use '*const fn() void' for a function pointer type
|
||||
// :3:8: note: union requires comptime because of this field
|
||||
Loading…
x
Reference in New Issue
Block a user