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(
41874187 return sema.failWithNeededComptime(block, arg_src);
41884188 }
41894189 } else if (is_anytype) {
4190 // We insert into the map an instruction which is runtime-known
4191 // but has the type of the argument.
4192 const child_arg = try child_block.addArg(sema.typeOf(arg), 0);
4193 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
4190 const arg_ty = sema.typeOf(arg);
4191 if (arg_ty.requiresComptime()) {
4192 const arg_val = try sema.resolveConstValue(block, arg_src, 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 }
41944201 }
41954202 arg_i += 1;
41964203 }
......@@ -5130,9 +5137,8 @@ fn funcCommon(
51305137 const comptime_params = try sema.arena.alloc(bool, block.params.items.len);
51315138 for (block.params.items) |param, i| {
51325139 param_types[i] = param.ty;
5133 comptime_params[i] = param.is_comptime;
5134 is_generic = is_generic or param.is_comptime or
5135 param.ty.tag() == .generic_poison or param.ty.requiresComptime();
5140 comptime_params[i] = param.is_comptime or param.ty.requiresComptime();
5141 is_generic = is_generic or comptime_params[i] or param.ty.tag() == .generic_poison;
51365142 }
51375143
51385144 if (align_val.tag() != .null_value) {
......@@ -13146,7 +13152,7 @@ fn coerceInMemoryAllowedFns(
1314613152 return .no_match;
1314713153 }
1314813154
13149 // TODO: nolias
13155 // TODO: noalias
1315013156
1315113157 // Note: Cast direction is reversed here.
1315213158 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 {
42754275 is_generic: bool,
42764276
42774277 pub fn paramIsComptime(self: @This(), i: usize) bool {
4278 if (!self.is_generic) return false;
42794278 assert(i < self.param_types.len);
42804279 return self.comptime_params[i];
42814280 }
test/behavior.zig+3-3
......@@ -67,6 +67,7 @@ test {
6767 _ = @import("behavior/bugs/394.zig");
6868 _ = @import("behavior/bugs/656.zig");
6969 _ = @import("behavior/bugs/1277.zig");
70 _ = @import("behavior/bugs/1310.zig");
7071 _ = @import("behavior/bugs/1381.zig");
7172 _ = @import("behavior/bugs/1500.zig");
7273 _ = @import("behavior/bugs/1741.zig");
......@@ -74,7 +75,9 @@ test {
7475 _ = @import("behavior/bugs/2578.zig");
7576 _ = @import("behavior/bugs/3007.zig");
7677 _ = @import("behavior/bugs/3112.zig");
78 _ = @import("behavior/bugs/3367.zig");
7779 _ = @import("behavior/bugs/7250.zig");
80 _ = @import("behavior/bugs/9584.zig");
7881 _ = @import("behavior/cast_llvm.zig");
7982 _ = @import("behavior/enum_llvm.zig");
8083 _ = @import("behavior/eval.zig");
......@@ -121,7 +124,6 @@ test {
121124 _ = @import("behavior/bugs/1025.zig");
122125 _ = @import("behavior/bugs/1076.zig");
123126 _ = @import("behavior/bugs/1120.zig");
124 _ = @import("behavior/bugs/1310.zig");
125127 _ = @import("behavior/bugs/1322.zig");
126128 _ = @import("behavior/bugs/1421.zig");
127129 _ = @import("behavior/bugs/1442.zig");
......@@ -130,7 +132,6 @@ test {
130132 _ = @import("behavior/bugs/1851.zig");
131133 _ = @import("behavior/bugs/1914.zig");
132134 _ = @import("behavior/bugs/2114.zig");
133 _ = @import("behavior/bugs/3367.zig");
134135 _ = @import("behavior/bugs/3384.zig");
135136 _ = @import("behavior/bugs/3742.zig");
136137 _ = @import("behavior/bugs/3779.zig");
......@@ -144,7 +145,6 @@ test {
144145 _ = @import("behavior/bugs/7003.zig");
145146 _ = @import("behavior/bugs/7027.zig");
146147 _ = @import("behavior/bugs/7047.zig");
147 _ = @import("behavior/bugs/9584.zig");
148148 _ = @import("behavior/bugs/10147.zig");
149149 _ = @import("behavior/byteswap.zig");
150150 _ = @import("behavior/call_stage1.zig");
test/behavior/enum.zig+48
......@@ -822,3 +822,51 @@ test "enum with one member default to u0 tag type" {
822822 const E0 = enum { X };
823823 comptime try expect(Tag(E0) == u0);
824824}
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 {
9696 return data.c;
9797}
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
12399test "enum literal in array literal" {
124100 const Items = enum { one, two };
125101 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" {
4343 try expect((try bar) == Bar.B);
4444}
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
7046test "exporting enum type and value" {
7147 const S = struct {
7248 const E = enum(c_int) { one, two };
......@@ -80,3 +56,41 @@ test "exporting enum type and value" {
8056 };
8157 try expect(S.e == .two);
8258}
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" {
3434 _ = b;
3535}
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
7537test "pointer comparison" {
7638 const a = @as([]const u8, "a");
7739 const b = &a;