authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-27 19:39:28-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-27 19:39:28-07:00
log6ed7850972c5d74912e6802474564de332ecf0d9
tree21f6e28332d2abeaebbf75088a4b8af6542c72f7
parentfc1a5cd9e74faf19e5974c733b0bcd9444d48b7b

Sema: fix anytype parameters whose types require comptime


7 files changed, 103 insertions(+), 98 deletions(-)

src/Sema.zig+14-8
...@@ -4187,10 +4187,17 @@ fn analyzeCall(...@@ -4187,10 +4187,17 @@ fn analyzeCall(
4187 return sema.failWithNeededComptime(block, arg_src);4187 return sema.failWithNeededComptime(block, arg_src);
4188 }4188 }
4189 } else if (is_anytype) {4189 } else if (is_anytype) {
4190 // We insert into the map an instruction which is runtime-known4190 const arg_ty = sema.typeOf(arg);
4191 // but has the type of the argument.4191 if (arg_ty.requiresComptime()) {
4192 const child_arg = try child_block.addArg(sema.typeOf(arg), 0);4192 const arg_val = try sema.resolveConstValue(block, arg_src, arg);
4193 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);4193 const child_arg = try child_sema.addConstant(arg_ty, arg_val);
4194 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
4195 } else {
4196 // We insert into the map an instruction which is runtime-known
4197 // but has the type of the argument.
4198 const child_arg = try child_block.addArg(arg_ty, 0);
4199 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
4200 }
4194 }4201 }
4195 arg_i += 1;4202 arg_i += 1;
4196 }4203 }
...@@ -5130,9 +5137,8 @@ fn funcCommon(...@@ -5130,9 +5137,8 @@ fn funcCommon(
5130 const comptime_params = try sema.arena.alloc(bool, block.params.items.len);5137 const comptime_params = try sema.arena.alloc(bool, block.params.items.len);
5131 for (block.params.items) |param, i| {5138 for (block.params.items) |param, i| {
5132 param_types[i] = param.ty;5139 param_types[i] = param.ty;
5133 comptime_params[i] = param.is_comptime;5140 comptime_params[i] = param.is_comptime or param.ty.requiresComptime();
5134 is_generic = is_generic or param.is_comptime or5141 is_generic = is_generic or comptime_params[i] or param.ty.tag() == .generic_poison;
5135 param.ty.tag() == .generic_poison or param.ty.requiresComptime();
5136 }5142 }
51375143
5138 if (align_val.tag() != .null_value) {5144 if (align_val.tag() != .null_value) {
...@@ -13146,7 +13152,7 @@ fn coerceInMemoryAllowedFns(...@@ -13146,7 +13152,7 @@ fn coerceInMemoryAllowedFns(
13146 return .no_match;13152 return .no_match;
13147 }13153 }
1314813154
13149 // TODO: nolias13155 // TODO: noalias
1315013156
13151 // Note: Cast direction is reversed here.13157 // Note: Cast direction is reversed here.
13152 const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, false, target, dest_src, src_src);13158 const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, false, target, dest_src, src_src);
src/type.zig-1
...@@ -4275,7 +4275,6 @@ pub const Type = extern union {...@@ -4275,7 +4275,6 @@ pub const Type = extern union {
4275 is_generic: bool,4275 is_generic: bool,
42764276
4277 pub fn paramIsComptime(self: @This(), i: usize) bool {4277 pub fn paramIsComptime(self: @This(), i: usize) bool {
4278 if (!self.is_generic) return false;
4279 assert(i < self.param_types.len);4278 assert(i < self.param_types.len);
4280 return self.comptime_params[i];4279 return self.comptime_params[i];
4281 }4280 }
test/behavior.zig+3-3
...@@ -67,6 +67,7 @@ test {...@@ -67,6 +67,7 @@ test {
67 _ = @import("behavior/bugs/394.zig");67 _ = @import("behavior/bugs/394.zig");
68 _ = @import("behavior/bugs/656.zig");68 _ = @import("behavior/bugs/656.zig");
69 _ = @import("behavior/bugs/1277.zig");69 _ = @import("behavior/bugs/1277.zig");
70 _ = @import("behavior/bugs/1310.zig");
70 _ = @import("behavior/bugs/1381.zig");71 _ = @import("behavior/bugs/1381.zig");
71 _ = @import("behavior/bugs/1500.zig");72 _ = @import("behavior/bugs/1500.zig");
72 _ = @import("behavior/bugs/1741.zig");73 _ = @import("behavior/bugs/1741.zig");
...@@ -74,7 +75,9 @@ test {...@@ -74,7 +75,9 @@ test {
74 _ = @import("behavior/bugs/2578.zig");75 _ = @import("behavior/bugs/2578.zig");
75 _ = @import("behavior/bugs/3007.zig");76 _ = @import("behavior/bugs/3007.zig");
76 _ = @import("behavior/bugs/3112.zig");77 _ = @import("behavior/bugs/3112.zig");
78 _ = @import("behavior/bugs/3367.zig");
77 _ = @import("behavior/bugs/7250.zig");79 _ = @import("behavior/bugs/7250.zig");
80 _ = @import("behavior/bugs/9584.zig");
78 _ = @import("behavior/cast_llvm.zig");81 _ = @import("behavior/cast_llvm.zig");
79 _ = @import("behavior/enum_llvm.zig");82 _ = @import("behavior/enum_llvm.zig");
80 _ = @import("behavior/eval.zig");83 _ = @import("behavior/eval.zig");
...@@ -121,7 +124,6 @@ test {...@@ -121,7 +124,6 @@ test {
121 _ = @import("behavior/bugs/1025.zig");124 _ = @import("behavior/bugs/1025.zig");
122 _ = @import("behavior/bugs/1076.zig");125 _ = @import("behavior/bugs/1076.zig");
123 _ = @import("behavior/bugs/1120.zig");126 _ = @import("behavior/bugs/1120.zig");
124 _ = @import("behavior/bugs/1310.zig");
125 _ = @import("behavior/bugs/1322.zig");127 _ = @import("behavior/bugs/1322.zig");
126 _ = @import("behavior/bugs/1421.zig");128 _ = @import("behavior/bugs/1421.zig");
127 _ = @import("behavior/bugs/1442.zig");129 _ = @import("behavior/bugs/1442.zig");
...@@ -130,7 +132,6 @@ test {...@@ -130,7 +132,6 @@ test {
130 _ = @import("behavior/bugs/1851.zig");132 _ = @import("behavior/bugs/1851.zig");
131 _ = @import("behavior/bugs/1914.zig");133 _ = @import("behavior/bugs/1914.zig");
132 _ = @import("behavior/bugs/2114.zig");134 _ = @import("behavior/bugs/2114.zig");
133 _ = @import("behavior/bugs/3367.zig");
134 _ = @import("behavior/bugs/3384.zig");135 _ = @import("behavior/bugs/3384.zig");
135 _ = @import("behavior/bugs/3742.zig");136 _ = @import("behavior/bugs/3742.zig");
136 _ = @import("behavior/bugs/3779.zig");137 _ = @import("behavior/bugs/3779.zig");
...@@ -144,7 +145,6 @@ test {...@@ -144,7 +145,6 @@ test {
144 _ = @import("behavior/bugs/7003.zig");145 _ = @import("behavior/bugs/7003.zig");
145 _ = @import("behavior/bugs/7027.zig");146 _ = @import("behavior/bugs/7027.zig");
146 _ = @import("behavior/bugs/7047.zig");147 _ = @import("behavior/bugs/7047.zig");
147 _ = @import("behavior/bugs/9584.zig");
148 _ = @import("behavior/bugs/10147.zig");148 _ = @import("behavior/bugs/10147.zig");
149 _ = @import("behavior/byteswap.zig");149 _ = @import("behavior/byteswap.zig");
150 _ = @import("behavior/call_stage1.zig");150 _ = @import("behavior/call_stage1.zig");
test/behavior/enum.zig+48
...@@ -822,3 +822,51 @@ test "enum with one member default to u0 tag type" {...@@ -822,3 +822,51 @@ test "enum with one member default to u0 tag type" {
822 const E0 = enum { X };822 const E0 = enum { X };
823 comptime try expect(Tag(E0) == u0);823 comptime try expect(Tag(E0) == u0);
824}824}
825
826const EnumWithOneMember = enum { Eof };
827
828fn doALoopThing(id: EnumWithOneMember) void {
829 while (true) {
830 if (id == EnumWithOneMember.Eof) {
831 break;
832 }
833 @compileError("above if condition should be comptime");
834 }
835}
836
837test "comparison operator on enum with one member is comptime known" {
838 doALoopThing(EnumWithOneMember.Eof);
839}
840
841const State = enum { Start };
842test "switch on enum with one member is comptime known" {
843 var state = State.Start;
844 switch (state) {
845 State.Start => return,
846 }
847 @compileError("analysis should not reach here");
848}
849
850test "method call on an enum" {
851 const S = struct {
852 const E = enum {
853 one,
854 two,
855
856 fn method(self: *E) bool {
857 return self.* == .two;
858 }
859
860 fn generic_method(self: *E, foo: anytype) bool {
861 return self.* == .two and foo == bool;
862 }
863 };
864 fn doTheTest() !void {
865 var e = E.two;
866 try expect(e.method());
867 try expect(e.generic_method(bool));
868 }
869 };
870 try S.doTheTest();
871 comptime try S.doTheTest();
872}
test/behavior/enum_llvm.zig-24
...@@ -96,30 +96,6 @@ fn getC(data: *const BitFieldOfEnums) C {...@@ -96,30 +96,6 @@ fn getC(data: *const BitFieldOfEnums) C {
96 return data.c;96 return data.c;
97}97}
9898
99const EnumWithOneMember = enum { Eof };
100
101fn doALoopThing(id: EnumWithOneMember) void {
102 while (true) {
103 if (id == EnumWithOneMember.Eof) {
104 break;
105 }
106 @compileError("above if condition should be comptime");
107 }
108}
109
110test "comparison operator on enum with one member is comptime known" {
111 doALoopThing(EnumWithOneMember.Eof);
112}
113
114const State = enum { Start };
115test "switch on enum with one member is comptime known" {
116 var state = State.Start;
117 switch (state) {
118 State.Start => return,
119 }
120 @compileError("analysis should not reach here");
121}
122
123test "enum literal in array literal" {99test "enum literal in array literal" {
124 const Items = enum { one, two };100 const Items = enum { one, two };
125 const array = [_]Items{ .one, .two };101 const array = [_]Items{ .one, .two };
test/behavior/enum_stage1.zig+38-24
...@@ -43,30 +43,6 @@ test "enum literal casting to error union with payload enum" {...@@ -43,30 +43,6 @@ test "enum literal casting to error union with payload enum" {
43 try expect((try bar) == Bar.B);43 try expect((try bar) == Bar.B);
44}44}
4545
46test "method call on an enum" {
47 const S = struct {
48 const E = enum {
49 one,
50 two,
51
52 fn method(self: *E) bool {
53 return self.* == .two;
54 }
55
56 fn generic_method(self: *E, foo: anytype) bool {
57 return self.* == .two and foo == bool;
58 }
59 };
60 fn doTheTest() !void {
61 var e = E.two;
62 try expect(e.method());
63 try expect(e.generic_method(bool));
64 }
65 };
66 try S.doTheTest();
67 comptime try S.doTheTest();
68}
69
70test "exporting enum type and value" {46test "exporting enum type and value" {
71 const S = struct {47 const S = struct {
72 const E = enum(c_int) { one, two };48 const E = enum(c_int) { one, two };
...@@ -80,3 +56,41 @@ test "exporting enum type and value" {...@@ -80,3 +56,41 @@ test "exporting enum type and value" {
80 };56 };
81 try expect(S.e == .two);57 try expect(S.e == .two);
82}58}
59
60test "constant enum initialization with differing sizes" {
61 try test3_1(test3_foo);
62 try test3_2(test3_bar);
63}
64const Test3Foo = union(enum) {
65 One: void,
66 Two: f32,
67 Three: Test3Point,
68};
69const Test3Point = struct {
70 x: i32,
71 y: i32,
72};
73const test3_foo = Test3Foo{
74 .Three = Test3Point{
75 .x = 3,
76 .y = 4,
77 },
78};
79const test3_bar = Test3Foo{ .Two = 13 };
80fn test3_1(f: Test3Foo) !void {
81 switch (f) {
82 Test3Foo.Three => |pt| {
83 try expect(pt.x == 3);
84 try expect(pt.y == 4);
85 },
86 else => unreachable,
87 }
88}
89fn test3_2(f: Test3Foo) !void {
90 switch (f) {
91 Test3Foo.Two => |x| {
92 try expect(x == 13);
93 },
94 else => unreachable,
95 }
96}
test/behavior/misc.zig-38
...@@ -34,44 +34,6 @@ test "explicit cast optional pointers" {...@@ -34,44 +34,6 @@ test "explicit cast optional pointers" {
34 _ = b;34 _ = b;
35}35}
3636
37test "constant enum initialization with differing sizes" {
38 try test3_1(test3_foo);
39 try test3_2(test3_bar);
40}
41const Test3Foo = union(enum) {
42 One: void,
43 Two: f32,
44 Three: Test3Point,
45};
46const Test3Point = struct {
47 x: i32,
48 y: i32,
49};
50const test3_foo = Test3Foo{
51 .Three = Test3Point{
52 .x = 3,
53 .y = 4,
54 },
55};
56const test3_bar = Test3Foo{ .Two = 13 };
57fn test3_1(f: Test3Foo) !void {
58 switch (f) {
59 Test3Foo.Three => |pt| {
60 try expect(pt.x == 3);
61 try expect(pt.y == 4);
62 },
63 else => unreachable,
64 }
65}
66fn test3_2(f: Test3Foo) !void {
67 switch (f) {
68 Test3Foo.Two => |x| {
69 try expect(x == 13);
70 },
71 else => unreachable,
72 }
73}
74
75test "pointer comparison" {37test "pointer comparison" {
76 const a = @as([]const u8, "a");38 const a = @as([]const u8, "a");
77 const b = &a;39 const b = &a;