diff options
| -rw-r--r-- | src/Sema.zig | 22 | ||||
| -rw-r--r-- | src/type.zig | 1 | ||||
| -rw-r--r-- | test/behavior.zig | 6 | ||||
| -rw-r--r-- | test/behavior/enum.zig | 48 | ||||
| -rw-r--r-- | test/behavior/enum_llvm.zig | 24 | ||||
| -rw-r--r-- | test/behavior/enum_stage1.zig | 62 | ||||
| -rw-r--r-- | test/behavior/misc.zig | 38 |
7 files changed, 103 insertions, 98 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 8d27553f94..544681f5f9 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -4187,10 +4187,17 @@ fn analyzeCall( return sema.failWithNeededComptime(block, arg_src); } } else if (is_anytype) { - // We insert into the map an instruction which is runtime-known - // but has the type of the argument. - const child_arg = try child_block.addArg(sema.typeOf(arg), 0); - child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg); + const arg_ty = sema.typeOf(arg); + if (arg_ty.requiresComptime()) { + const arg_val = try sema.resolveConstValue(block, arg_src, arg); + const child_arg = try child_sema.addConstant(arg_ty, arg_val); + child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg); + } else { + // We insert into the map an instruction which is runtime-known + // but has the type of the argument. + const child_arg = try child_block.addArg(arg_ty, 0); + child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg); + } } arg_i += 1; } @@ -5130,9 +5137,8 @@ fn funcCommon( const comptime_params = try sema.arena.alloc(bool, block.params.items.len); for (block.params.items) |param, i| { param_types[i] = param.ty; - comptime_params[i] = param.is_comptime; - is_generic = is_generic or param.is_comptime or - param.ty.tag() == .generic_poison or param.ty.requiresComptime(); + comptime_params[i] = param.is_comptime or param.ty.requiresComptime(); + is_generic = is_generic or comptime_params[i] or param.ty.tag() == .generic_poison; } if (align_val.tag() != .null_value) { @@ -13146,7 +13152,7 @@ fn coerceInMemoryAllowedFns( return .no_match; } - // TODO: nolias + // TODO: noalias // Note: Cast direction is reversed here. const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, false, target, dest_src, src_src); diff --git a/src/type.zig b/src/type.zig index 1482710e51..fb543e1f2c 100644 --- a/src/type.zig +++ b/src/type.zig @@ -4275,7 +4275,6 @@ pub const Type = extern union { is_generic: bool, pub fn paramIsComptime(self: @This(), i: usize) bool { - if (!self.is_generic) return false; assert(i < self.param_types.len); return self.comptime_params[i]; } diff --git a/test/behavior.zig b/test/behavior.zig index 46b4cf083d..7bc52ff518 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -67,6 +67,7 @@ test { _ = @import("behavior/bugs/394.zig"); _ = @import("behavior/bugs/656.zig"); _ = @import("behavior/bugs/1277.zig"); + _ = @import("behavior/bugs/1310.zig"); _ = @import("behavior/bugs/1381.zig"); _ = @import("behavior/bugs/1500.zig"); _ = @import("behavior/bugs/1741.zig"); @@ -74,7 +75,9 @@ test { _ = @import("behavior/bugs/2578.zig"); _ = @import("behavior/bugs/3007.zig"); _ = @import("behavior/bugs/3112.zig"); + _ = @import("behavior/bugs/3367.zig"); _ = @import("behavior/bugs/7250.zig"); + _ = @import("behavior/bugs/9584.zig"); _ = @import("behavior/cast_llvm.zig"); _ = @import("behavior/enum_llvm.zig"); _ = @import("behavior/eval.zig"); @@ -121,7 +124,6 @@ test { _ = @import("behavior/bugs/1025.zig"); _ = @import("behavior/bugs/1076.zig"); _ = @import("behavior/bugs/1120.zig"); - _ = @import("behavior/bugs/1310.zig"); _ = @import("behavior/bugs/1322.zig"); _ = @import("behavior/bugs/1421.zig"); _ = @import("behavior/bugs/1442.zig"); @@ -130,7 +132,6 @@ test { _ = @import("behavior/bugs/1851.zig"); _ = @import("behavior/bugs/1914.zig"); _ = @import("behavior/bugs/2114.zig"); - _ = @import("behavior/bugs/3367.zig"); _ = @import("behavior/bugs/3384.zig"); _ = @import("behavior/bugs/3742.zig"); _ = @import("behavior/bugs/3779.zig"); @@ -144,7 +145,6 @@ test { _ = @import("behavior/bugs/7003.zig"); _ = @import("behavior/bugs/7027.zig"); _ = @import("behavior/bugs/7047.zig"); - _ = @import("behavior/bugs/9584.zig"); _ = @import("behavior/bugs/10147.zig"); _ = @import("behavior/byteswap.zig"); _ = @import("behavior/call_stage1.zig"); diff --git a/test/behavior/enum.zig b/test/behavior/enum.zig index 6de1763deb..d044619edf 100644 --- a/test/behavior/enum.zig +++ b/test/behavior/enum.zig @@ -822,3 +822,51 @@ test "enum with one member default to u0 tag type" { const E0 = enum { X }; comptime try expect(Tag(E0) == u0); } + +const EnumWithOneMember = enum { Eof }; + +fn doALoopThing(id: EnumWithOneMember) void { + while (true) { + if (id == EnumWithOneMember.Eof) { + break; + } + @compileError("above if condition should be comptime"); + } +} + +test "comparison operator on enum with one member is comptime known" { + doALoopThing(EnumWithOneMember.Eof); +} + +const State = enum { Start }; +test "switch on enum with one member is comptime known" { + var state = State.Start; + switch (state) { + State.Start => return, + } + @compileError("analysis should not reach here"); +} + +test "method call on an enum" { + const S = struct { + const E = enum { + one, + two, + + fn method(self: *E) bool { + return self.* == .two; + } + + fn generic_method(self: *E, foo: anytype) bool { + return self.* == .two and foo == bool; + } + }; + fn doTheTest() !void { + var e = E.two; + try expect(e.method()); + try expect(e.generic_method(bool)); + } + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} diff --git a/test/behavior/enum_llvm.zig b/test/behavior/enum_llvm.zig index 6d57aac2c1..81a1c72e59 100644 --- a/test/behavior/enum_llvm.zig +++ b/test/behavior/enum_llvm.zig @@ -96,30 +96,6 @@ fn getC(data: *const BitFieldOfEnums) C { return data.c; } -const EnumWithOneMember = enum { Eof }; - -fn doALoopThing(id: EnumWithOneMember) void { - while (true) { - if (id == EnumWithOneMember.Eof) { - break; - } - @compileError("above if condition should be comptime"); - } -} - -test "comparison operator on enum with one member is comptime known" { - doALoopThing(EnumWithOneMember.Eof); -} - -const State = enum { Start }; -test "switch on enum with one member is comptime known" { - var state = State.Start; - switch (state) { - State.Start => return, - } - @compileError("analysis should not reach here"); -} - test "enum literal in array literal" { const Items = enum { one, two }; const array = [_]Items{ .one, .two }; diff --git a/test/behavior/enum_stage1.zig b/test/behavior/enum_stage1.zig index 0f9c1dc6f5..c9658918f8 100644 --- a/test/behavior/enum_stage1.zig +++ b/test/behavior/enum_stage1.zig @@ -43,30 +43,6 @@ test "enum literal casting to error union with payload enum" { try expect((try bar) == Bar.B); } -test "method call on an enum" { - const S = struct { - const E = enum { - one, - two, - - fn method(self: *E) bool { - return self.* == .two; - } - - fn generic_method(self: *E, foo: anytype) bool { - return self.* == .two and foo == bool; - } - }; - fn doTheTest() !void { - var e = E.two; - try expect(e.method()); - try expect(e.generic_method(bool)); - } - }; - try S.doTheTest(); - comptime try S.doTheTest(); -} - test "exporting enum type and value" { const S = struct { const E = enum(c_int) { one, two }; @@ -80,3 +56,41 @@ test "exporting enum type and value" { }; try expect(S.e == .two); } + +test "constant enum initialization with differing sizes" { + try test3_1(test3_foo); + try test3_2(test3_bar); +} +const Test3Foo = union(enum) { + One: void, + Two: f32, + Three: Test3Point, +}; +const Test3Point = struct { + x: i32, + y: i32, +}; +const test3_foo = Test3Foo{ + .Three = Test3Point{ + .x = 3, + .y = 4, + }, +}; +const test3_bar = Test3Foo{ .Two = 13 }; +fn test3_1(f: Test3Foo) !void { + switch (f) { + Test3Foo.Three => |pt| { + try expect(pt.x == 3); + try expect(pt.y == 4); + }, + else => unreachable, + } +} +fn test3_2(f: Test3Foo) !void { + switch (f) { + Test3Foo.Two => |x| { + try expect(x == 13); + }, + else => unreachable, + } +} diff --git a/test/behavior/misc.zig b/test/behavior/misc.zig index 7a248ed320..df435ac60c 100644 --- a/test/behavior/misc.zig +++ b/test/behavior/misc.zig @@ -34,44 +34,6 @@ test "explicit cast optional pointers" { _ = b; } -test "constant enum initialization with differing sizes" { - try test3_1(test3_foo); - try test3_2(test3_bar); -} -const Test3Foo = union(enum) { - One: void, - Two: f32, - Three: Test3Point, -}; -const Test3Point = struct { - x: i32, - y: i32, -}; -const test3_foo = Test3Foo{ - .Three = Test3Point{ - .x = 3, - .y = 4, - }, -}; -const test3_bar = Test3Foo{ .Two = 13 }; -fn test3_1(f: Test3Foo) !void { - switch (f) { - Test3Foo.Three => |pt| { - try expect(pt.x == 3); - try expect(pt.y == 4); - }, - else => unreachable, - } -} -fn test3_2(f: Test3Foo) !void { - switch (f) { - Test3Foo.Two => |x| { - try expect(x == 13); - }, - else => unreachable, - } -} - test "pointer comparison" { const a = @as([]const u8, "a"); const b = &a; |
