| author | |
| committer | |
| log | 6ed7850972c5d74912e6802474564de332ecf0d9 |
| tree | 21f6e28332d2abeaebbf75088a4b8af6542c72f7 |
| parent | fc1a5cd9e74faf19e5974c733b0bcd9444d48b7b |
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-known | 4190 | 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 or | 5141 | 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 | } |
| 5137 | 5143 | ||
| 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 | } |
| 13148 | 13154 | ||
| 13149 | // TODO: nolias | 13155 | // TODO: noalias |
| 13150 | 13156 | ||
| 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, |
| 4276 | 4276 | ||
| 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 | |||
| 826 | const EnumWithOneMember = enum { Eof }; | ||
| 827 | |||
| 828 | fn 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 | |||
| 837 | test "comparison operator on enum with one member is comptime known" { | ||
| 838 | doALoopThing(EnumWithOneMember.Eof); | ||
| 839 | } | ||
| 840 | |||
| 841 | const State = enum { Start }; | ||
| 842 | test "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 | |||
| 850 | test "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 | } |
| 98 | 98 | ||
| 99 | const EnumWithOneMember = enum { Eof }; | ||
| 100 | |||
| 101 | fn 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 | |||
| 110 | test "comparison operator on enum with one member is comptime known" { | ||
| 111 | doALoopThing(EnumWithOneMember.Eof); | ||
| 112 | } | ||
| 113 | |||
| 114 | const State = enum { Start }; | ||
| 115 | test "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 | |||
| 123 | test "enum literal in array literal" { | 99 | test "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 | } |
| 45 | 45 | ||
| 46 | test "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 | |||
| 70 | test "exporting enum type and value" { | 46 | test "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 | |||
| 60 | test "constant enum initialization with differing sizes" { | ||
| 61 | try test3_1(test3_foo); | ||
| 62 | try test3_2(test3_bar); | ||
| 63 | } | ||
| 64 | const Test3Foo = union(enum) { | ||
| 65 | One: void, | ||
| 66 | Two: f32, | ||
| 67 | Three: Test3Point, | ||
| 68 | }; | ||
| 69 | const Test3Point = struct { | ||
| 70 | x: i32, | ||
| 71 | y: i32, | ||
| 72 | }; | ||
| 73 | const test3_foo = Test3Foo{ | ||
| 74 | .Three = Test3Point{ | ||
| 75 | .x = 3, | ||
| 76 | .y = 4, | ||
| 77 | }, | ||
| 78 | }; | ||
| 79 | const test3_bar = Test3Foo{ .Two = 13 }; | ||
| 80 | fn 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 | } | ||
| 89 | fn 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 | } |
| 36 | 36 | ||
| 37 | test "constant enum initialization with differing sizes" { | ||
| 38 | try test3_1(test3_foo); | ||
| 39 | try test3_2(test3_bar); | ||
| 40 | } | ||
| 41 | const Test3Foo = union(enum) { | ||
| 42 | One: void, | ||
| 43 | Two: f32, | ||
| 44 | Three: Test3Point, | ||
| 45 | }; | ||
| 46 | const Test3Point = struct { | ||
| 47 | x: i32, | ||
| 48 | y: i32, | ||
| 49 | }; | ||
| 50 | const test3_foo = Test3Foo{ | ||
| 51 | .Three = Test3Point{ | ||
| 52 | .x = 3, | ||
| 53 | .y = 4, | ||
| 54 | }, | ||
| 55 | }; | ||
| 56 | const test3_bar = Test3Foo{ .Two = 13 }; | ||
| 57 | fn 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 | } | ||
| 66 | fn test3_2(f: Test3Foo) !void { | ||
| 67 | switch (f) { | ||
| 68 | Test3Foo.Two => |x| { | ||
| 69 | try expect(x == 13); | ||
| 70 | }, | ||
| 71 | else => unreachable, | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | test "pointer comparison" { | 37 | test "pointer comparison" { |
| 76 | const a = @as([]const u8, "a"); | 38 | const a = @as([]const u8, "a"); |
| 77 | const b = &a; | 39 | const b = &a; |