Sema: fix infinite recursion in explainWhyTypeIsComptime

Co-authored-by: Veikka Tuominen <git@vexu.eu>
This commit is contained in:
Anton Lilja 2022-08-06 13:17:09 +02:00 committed by GitHub
parent 5c9826630d
commit 86d9c3de2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 84 additions and 6 deletions

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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