authorgravatar for liljaanton2001@gmail.comantlilja <liljaanton2001@gmail.com> 2022-08-06 13:17:09+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-08-06 14:17:09+03:00
log86d9c3de2b6b43329c16678f1bd7eaddd3d218d7
tree3697de6cee8439fbf0993d80645c5a51a9ec26ae
parent5c9826630dfb8a2f59663a569bb8e452359c9524
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Sema: fix infinite recursion in `explainWhyTypeIsComptime`

Co-authored-by: Veikka Tuominen <git@vexu.eu>

4 files changed, 84 insertions(+), 6 deletions(-)

src/Sema.zig+30-6
......@@ -19764,6 +19764,8 @@ fn validateRunTimeType(
1976419764 };
1976519765}
1976619766
19767const TypeSet = std.HashMapUnmanaged(Type, void, Type.HashContext64, std.hash_map.default_max_load_percentage);
19768
1976719769fn explainWhyTypeIsComptime(
1976819770 sema: *Sema,
1976919771 block: *Block,
......@@ -19771,6 +19773,22 @@ fn explainWhyTypeIsComptime(
1977119773 msg: *Module.ErrorMsg,
1977219774 src_loc: Module.SrcLoc,
1977319775 ty: Type,
19776) CompileError!void {
19777 var type_set = TypeSet{};
19778 defer type_set.deinit(sema.gpa);
19779
19780 try sema.resolveTypeFully(block, src, ty);
19781 return sema.explainWhyTypeIsComptimeInner(block, src, msg, src_loc, ty, &type_set);
19782}
19783
19784fn explainWhyTypeIsComptimeInner(
19785 sema: *Sema,
19786 block: *Block,
19787 src: LazySrcLoc,
19788 msg: *Module.ErrorMsg,
19789 src_loc: Module.SrcLoc,
19790 ty: Type,
19791 type_set: *TypeSet,
1977419792) CompileError!void {
1977519793 const mod = sema.mod;
1977619794 switch (ty.zigTypeTag()) {
......@@ -19808,7 +19826,7 @@ fn explainWhyTypeIsComptime(
1980819826 },
1980919827
1981019828 .Array, .Vector => {
19811 try sema.explainWhyTypeIsComptime(block, src, msg, src_loc, ty.elemType());
19829 try sema.explainWhyTypeIsComptimeInner(block, src, msg, src_loc, ty.elemType(), type_set);
1981219830 },
1981319831 .Pointer => {
1981419832 const elem_ty = ty.elemType2();
......@@ -19826,18 +19844,20 @@ fn explainWhyTypeIsComptime(
1982619844 }
1982719845 return;
1982819846 }
19829 try sema.explainWhyTypeIsComptime(block, src, msg, src_loc, ty.elemType());
19847 try sema.explainWhyTypeIsComptimeInner(block, src, msg, src_loc, ty.elemType(), type_set);
1983019848 },
1983119849
1983219850 .Optional => {
1983319851 var buf: Type.Payload.ElemType = undefined;
19834 try sema.explainWhyTypeIsComptime(block, src, msg, src_loc, ty.optionalChild(&buf));
19852 try sema.explainWhyTypeIsComptimeInner(block, src, msg, src_loc, ty.optionalChild(&buf), type_set);
1983519853 },
1983619854 .ErrorUnion => {
19837 try sema.explainWhyTypeIsComptime(block, src, msg, src_loc, ty.errorUnionPayload());
19855 try sema.explainWhyTypeIsComptimeInner(block, src, msg, src_loc, ty.errorUnionPayload(), type_set);
1983819856 },
1983919857
1984019858 .Struct => {
19859 if ((try type_set.getOrPutContext(sema.gpa, ty, .{ .mod = mod })).found_existing) return;
19860
1984119861 if (ty.castTag(.@"struct")) |payload| {
1984219862 const struct_obj = payload.data;
1984319863 for (struct_obj.fields.values()) |field, i| {
......@@ -19845,9 +19865,10 @@ fn explainWhyTypeIsComptime(
1984519865 .index = i,
1984619866 .range = .type,
1984719867 });
19868
1984819869 if (try sema.typeRequiresComptime(block, src, field.ty)) {
1984919870 try mod.errNoteNonLazy(field_src_loc, msg, "struct requires comptime because of this field", .{});
19850 try sema.explainWhyTypeIsComptime(block, src, msg, field_src_loc, field.ty);
19871 try sema.explainWhyTypeIsComptimeInner(block, src, msg, field_src_loc, field.ty, type_set);
1985119872 }
1985219873 }
1985319874 }
......@@ -19855,6 +19876,8 @@ fn explainWhyTypeIsComptime(
1985519876 },
1985619877
1985719878 .Union => {
19879 if ((try type_set.getOrPutContext(sema.gpa, ty, .{ .mod = mod })).found_existing) return;
19880
1985819881 if (ty.cast(Type.Payload.Union)) |payload| {
1985919882 const union_obj = payload.data;
1986019883 for (union_obj.fields.values()) |field, i| {
......@@ -19862,9 +19885,10 @@ fn explainWhyTypeIsComptime(
1986219885 .index = i,
1986319886 .range = .type,
1986419887 });
19888
1986519889 if (try sema.typeRequiresComptime(block, src, field.ty)) {
1986619890 try mod.errNoteNonLazy(field_src_loc, msg, "union requires comptime because of this field", .{});
19867 try sema.explainWhyTypeIsComptime(block, src, msg, field_src_loc, field.ty);
19891 try sema.explainWhyTypeIsComptimeInner(block, src, msg, field_src_loc, field.ty, type_set);
1986819892 }
1986919893 }
1987019894 }
test/cases/compile_errors/AstGen_comptime_known_struct_is_resolved_before_error.zig created+19
......@@ -0,0 +1,19 @@
1const S1 = struct {
2 a: S2,
3};
4const S2 = struct {
5 b: fn () void,
6};
7pub export fn entry() void {
8 var s: S1 = undefined;
9 _ = s;
10}
11
12// error
13// backend=stage2
14// target=native
15//
16// :8:12: error: variable of type 'tmp.S1' must be const or comptime
17// :2:8: note: struct requires comptime because of this field
18// :5:8: note: struct requires comptime because of this field
19// :5:8: note: use '*const fn() void' for a function pointer type
test/cases/compile_errors/self_referential_struct_requires_comptime.zig created+18
......@@ -0,0 +1,18 @@
1const S = struct {
2 a: fn () void,
3 b: *S,
4};
5pub export fn entry() void {
6 var s: S = undefined;
7 _ = s;
8}
9
10
11// error
12// backend=stage2
13// target=native
14//
15// :6:12: error: variable of type 'tmp.S' must be const or comptime
16// :2:8: note: struct requires comptime because of this field
17// :2:8: note: use '*const fn() void' for a function pointer type
18// :3:8: note: struct requires comptime because of this field
test/cases/compile_errors/self_referential_union_requires_comptime.zig created+17
......@@ -0,0 +1,17 @@
1const U = union {
2 a: fn () void,
3 b: *U,
4};
5pub export fn entry() void {
6 var u: U = undefined;
7 _ = u;
8}
9
10// error
11// backend=stage2
12// target=native
13//
14// :6:12: error: variable of type 'tmp.U' must be const or comptime
15// :2:8: note: union requires comptime because of this field
16// :2:8: note: use '*const fn() void' for a function pointer type
17// :3:8: note: union requires comptime because of this field