Commit 86d9c3de2b
Changed files (4)
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);
}
}
}
test/cases/compile_errors/AstGen_comptime_known_struct_is_resolved_before_error.zig
@@ -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
test/cases/compile_errors/self_referential_struct_requires_comptime.zig
@@ -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
test/cases/compile_errors/self_referential_union_requires_comptime.zig
@@ -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