Commit 2b589d71fb
Changed files (9)
test/behavior/cast.zig
@@ -266,3 +266,32 @@ test "array coersion to undefined at runtime" {
array = undefined;
try expect(std.mem.eql(u8, &array, &undefined_val));
}
+
+test "implicitly cast from int to anyerror!?T" {
+ implicitIntLitToOptional();
+ comptime implicitIntLitToOptional();
+}
+fn implicitIntLitToOptional() void {
+ const f: ?i32 = 1;
+ _ = f;
+ const g: anyerror!?i32 = 1;
+ _ = g catch {};
+}
+
+test "return u8 coercing into ?u32 return type" {
+ const S = struct {
+ fn doTheTest() !void {
+ try expect(foo(123).? == 123);
+ }
+ fn foo(arg: u8) ?u32 {
+ return arg;
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "cast from ?[*]T to ??[*]T" {
+ const a: ??[*]u8 = @as(?[*]u8, null);
+ try expect(a != null and a.? == null);
+}
test/behavior/cast_llvm.zig
@@ -65,3 +65,135 @@ test "implicit ptr to *c_void" {
var c: *u32 = @ptrCast(*u32, ptr2.?);
try expect(c.* == 1);
}
+
+const A = struct {
+ a: i32,
+};
+test "return null from fn() anyerror!?&T" {
+ const a = returnNullFromOptionalTypeErrorRef();
+ const b = returnNullLitFromOptionalTypeErrorRef();
+ try expect((try a) == null and (try b) == null);
+}
+fn returnNullFromOptionalTypeErrorRef() anyerror!?*A {
+ const a: ?*A = null;
+ return a;
+}
+fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
+ return null;
+}
+
+test "peer type resolution: [0]u8 and []const u8" {
+ try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
+ try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
+ comptime {
+ try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
+ try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
+ }
+}
+fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
+ if (a) {
+ return &[_]u8{};
+ }
+
+ return slice[0..1];
+}
+
+test "implicitly cast from [N]T to ?[]const T" {
+ try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
+ comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
+}
+
+fn castToOptionalSlice() ?[]const u8 {
+ return "hi";
+}
+
+test "cast u128 to f128 and back" {
+ comptime try testCast128();
+ try testCast128();
+}
+
+fn testCast128() !void {
+ try expect(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000);
+}
+
+fn cast128Int(x: f128) u128 {
+ return @bitCast(u128, x);
+}
+
+fn cast128Float(x: u128) f128 {
+ return @bitCast(f128, x);
+}
+
+test "implicit cast from *[N]T to ?[*]T" {
+ var x: ?[*]u16 = null;
+ var y: [4]u16 = [4]u16{ 0, 1, 2, 3 };
+
+ x = &y;
+ try expect(std.mem.eql(u16, x.?[0..4], y[0..4]));
+ x.?[0] = 8;
+ y[3] = 6;
+ try expect(std.mem.eql(u16, x.?[0..4], y[0..4]));
+}
+
+test "implicit cast from *T to ?*c_void" {
+ var a: u8 = 1;
+ incrementVoidPtrValue(&a);
+ try std.testing.expect(a == 2);
+}
+
+fn incrementVoidPtrValue(value: ?*c_void) void {
+ @ptrCast(*u8, value.?).* += 1;
+}
+
+test "implicit cast *[0]T to E![]const u8" {
+ var x = @as(anyerror![]const u8, &[0]u8{});
+ try expect((x catch unreachable).len == 0);
+}
+
+var global_array: [4]u8 = undefined;
+test "cast from array reference to fn" {
+ const f = @ptrCast(fn () callconv(.C) void, &global_array);
+ try expect(@ptrToInt(f) == @ptrToInt(&global_array));
+}
+
+test "*const [N]null u8 to ?[]const u8" {
+ const S = struct {
+ fn doTheTest() !void {
+ var a = "Hello";
+ var b: ?[]const u8 = a;
+ try expect(mem.eql(u8, b.?, "Hello"));
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "cast between [*c]T and ?[*:0]T on fn parameter" {
+ const S = struct {
+ const Handler = ?fn ([*c]const u8) callconv(.C) void;
+ fn addCallback(handler: Handler) void {
+ _ = handler;
+ }
+
+ fn myCallback(cstr: ?[*:0]const u8) callconv(.C) void {
+ _ = cstr;
+ }
+
+ fn doTheTest() void {
+ addCallback(myCallback);
+ }
+ };
+ S.doTheTest();
+}
+
+var global_struct: struct { f0: usize } = undefined;
+test "assignment to optional pointer result loc" {
+ var foo: struct { ptr: ?*c_void } = .{ .ptr = &global_struct };
+ try expect(foo.ptr.? == @ptrCast(*c_void, &global_struct));
+}
+
+test "cast between *[N]void and []void" {
+ var a: [4]void = undefined;
+ var b: []void = &a;
+ try expect(b.len == 4);
+}
test/behavior/cast_stage1.zig
@@ -58,55 +58,6 @@ fn castToOptionalTypeError(z: i32) !void {
try expect((b catch unreachable).?.a == 1);
}
-test "implicitly cast from int to anyerror!?T" {
- implicitIntLitToOptional();
- comptime implicitIntLitToOptional();
-}
-fn implicitIntLitToOptional() void {
- const f: ?i32 = 1;
- _ = f;
- const g: anyerror!?i32 = 1;
- _ = g catch {};
-}
-
-test "return null from fn() anyerror!?&T" {
- const a = returnNullFromOptionalTypeErrorRef();
- const b = returnNullLitFromOptionalTypeErrorRef();
- try expect((try a) == null and (try b) == null);
-}
-fn returnNullFromOptionalTypeErrorRef() anyerror!?*A {
- const a: ?*A = null;
- return a;
-}
-fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
- return null;
-}
-
-test "peer type resolution: [0]u8 and []const u8" {
- try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
- try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
- comptime {
- try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
- try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
- }
-}
-fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
- if (a) {
- return &[_]u8{};
- }
-
- return slice[0..1];
-}
-
-test "implicitly cast from [N]T to ?[]const T" {
- try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
- comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
-}
-
-fn castToOptionalSlice() ?[]const u8 {
- return "hi";
-}
-
test "implicitly cast from [0]T to anyerror![]T" {
try testCastZeroArrayToErrSliceMut();
comptime try testCastZeroArrayToErrSliceMut();
@@ -191,23 +142,6 @@ fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
};
}
-test "cast u128 to f128 and back" {
- comptime try testCast128();
- try testCast128();
-}
-
-fn testCast128() !void {
- try expect(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000);
-}
-
-fn cast128Int(x: f128) u128 {
- return @bitCast(u128, x);
-}
-
-fn cast128Float(x: u128) f128 {
- return @bitCast(f128, x);
-}
-
test "single-item pointer of array to slice to unknown length pointer" {
try testCastPtrOfArrayToSliceAndPtr();
comptime try testCastPtrOfArrayToSliceAndPtr();
@@ -316,27 +250,6 @@ test "@floatCast cast down" {
}
}
-test "implicit cast from *[N]T to ?[*]T" {
- var x: ?[*]u16 = null;
- var y: [4]u16 = [4]u16{ 0, 1, 2, 3 };
-
- x = &y;
- try expect(std.mem.eql(u16, x.?[0..4], y[0..4]));
- x.?[0] = 8;
- y[3] = 6;
- try expect(std.mem.eql(u16, x.?[0..4], y[0..4]));
-}
-
-test "implicit cast from *T to ?*c_void" {
- var a: u8 = 1;
- incrementVoidPtrValue(&a);
- try std.testing.expect(a == 2);
-}
-
-fn incrementVoidPtrValue(value: ?*c_void) void {
- @ptrCast(*u8, value.?).* += 1;
-}
-
test "peer type resolution: unreachable, null, slice" {
const S = struct {
fn doTheTest(num: usize, word: []const u8) !void {
@@ -374,11 +287,6 @@ test "peer type resolution: unreachable, error set, unreachable" {
try expect(transformed_err == error.SystemResources);
}
-test "implicit cast *[0]T to E![]const u8" {
- var x = @as(anyerror![]const u8, &[0]u8{});
- try expect((x catch unreachable).len == 0);
-}
-
test "peer cast *[0]T to E![]const T" {
var buffer: [5]u8 = "abcde".*;
var buf: anyerror![]const u8 = buffer[0..];
@@ -395,24 +303,6 @@ test "peer cast *[0]T to []const T" {
try expect(mem.eql(u8, "abcde", y));
}
-var global_array: [4]u8 = undefined;
-test "cast from array reference to fn" {
- const f = @ptrCast(fn () callconv(.C) void, &global_array);
- try expect(@ptrToInt(f) == @ptrToInt(&global_array));
-}
-
-test "*const [N]null u8 to ?[]const u8" {
- const S = struct {
- fn doTheTest() !void {
- var a = "Hello";
- var b: ?[]const u8 = a;
- try expect(mem.eql(u8, b.?, "Hello"));
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
test "peer resolution of string literals" {
const S = struct {
const E = enum { a, b, c, d };
@@ -502,19 +392,6 @@ test "cast i8 fn call peers to i32 result" {
comptime try S.doTheTest();
}
-test "return u8 coercing into ?u32 return type" {
- const S = struct {
- fn doTheTest() !void {
- try expect(foo(123).? == 123);
- }
- fn foo(arg: u8) ?u32 {
- return arg;
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
test "peer type resolution implicit cast to return type" {
const S = struct {
fn doTheTest() !void {
@@ -553,24 +430,6 @@ test "variable initialization uses result locations properly with regards to the
try expect(x == 1);
}
-test "cast between [*c]T and ?[*:0]T on fn parameter" {
- const S = struct {
- const Handler = ?fn ([*c]const u8) callconv(.C) void;
- fn addCallback(handler: Handler) void {
- _ = handler;
- }
-
- fn myCallback(cstr: ?[*:0]const u8) callconv(.C) void {
- _ = cstr;
- }
-
- fn doTheTest() void {
- addCallback(myCallback);
- }
- };
- S.doTheTest();
-}
-
test "cast between C pointer with different but compatible types" {
const S = struct {
fn foo(arg: [*]c_ushort) u16 {
@@ -584,13 +443,6 @@ test "cast between C pointer with different but compatible types" {
try S.doTheTest();
}
-var global_struct: struct { f0: usize } = undefined;
-
-test "assignment to optional pointer result loc" {
- var foo: struct { ptr: ?*c_void } = .{ .ptr = &global_struct };
- try expect(foo.ptr.? == @ptrCast(*c_void, &global_struct));
-}
-
test "peer type resolve string lit with sentinel-terminated mutable slice" {
var array: [4:0]u8 = undefined;
array[4] = 0; // TODO remove this when #4372 is solved
@@ -649,14 +501,3 @@ test "comptime float casts" {
fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void {
try expect(@floatToInt(I, f) == i);
}
-
-test "cast from ?[*]T to ??[*]T" {
- const a: ??[*]u8 = @as(?[*]u8, null);
- try expect(a != null and a.? == null);
-}
-
-test "cast between *[N]void and []void" {
- var a: [4]void = undefined;
- var b: []void = &a;
- try expect(b.len == 4);
-}
test/behavior/fn.zig
@@ -121,3 +121,45 @@ test "inline function call that calls optional function pointer, return pointer
};
try S.doTheTest();
}
+
+test "implicit cast function unreachable return" {
+ wantsFnWithVoid(fnWithUnreachable);
+}
+
+fn wantsFnWithVoid(f: fn () void) void {
+ _ = f;
+}
+
+fn fnWithUnreachable() noreturn {
+ unreachable;
+}
+
+test "extern struct with stdcallcc fn pointer" {
+ const S = extern struct {
+ ptr: fn () callconv(if (builtin.target.cpu.arch == .i386) .Stdcall else .C) i32,
+
+ fn foo() callconv(if (builtin.target.cpu.arch == .i386) .Stdcall else .C) i32 {
+ return 1234;
+ }
+ };
+
+ var s: S = undefined;
+ s.ptr = S.foo;
+ try expect(s.ptr() == 1234);
+}
+
+const nComplexCallconv = 100;
+fn fComplexCallconvRet(x: u32) callconv(blk: {
+ const s: struct { n: u32 } = .{ .n = nComplexCallconv };
+ break :blk switch (s.n) {
+ 0 => .C,
+ 1 => .Inline,
+ else => .Unspecified,
+ };
+}) struct { x: u32 } {
+ return .{ .x = x * x };
+}
+
+test "function with complex callconv and return type expressions" {
+ try expect(fComplexCallconvRet(3).x == 9);
+}
test/behavior/fn_stage1.zig
@@ -23,18 +23,6 @@ fn acceptsString(foo: []u8) void {
_ = foo;
}
-test "implicit cast function unreachable return" {
- wantsFnWithVoid(fnWithUnreachable);
-}
-
-fn wantsFnWithVoid(f: fn () void) void {
- _ = f;
-}
-
-fn fnWithUnreachable() noreturn {
- unreachable;
-}
-
test "function pointers" {
const fns = [_]@TypeOf(fn1){
fn1,
@@ -126,20 +114,6 @@ test "pass by non-copying value as method, at comptime" {
}
}
-test "extern struct with stdcallcc fn pointer" {
- const S = extern struct {
- ptr: fn () callconv(if (builtin.target.cpu.arch == .i386) .Stdcall else .C) i32,
-
- fn foo() callconv(if (builtin.target.cpu.arch == .i386) .Stdcall else .C) i32 {
- return 1234;
- }
- };
-
- var s: S = undefined;
- s.ptr = S.foo;
- try expect(s.ptr() == 1234);
-}
-
test "implicit cast fn call result to optional in field result" {
const S = struct {
fn entry() !void {
@@ -204,19 +178,3 @@ test "function with inferred error set but returning no error" {
const return_ty = @typeInfo(@TypeOf(S.foo)).Fn.return_type.?;
try expectEqual(0, @typeInfo(@typeInfo(return_ty).ErrorUnion.error_set).ErrorSet.?.len);
}
-
-const nComplexCallconv = 100;
-fn fComplexCallconvRet(x: u32) callconv(blk: {
- const s: struct { n: u32 } = .{ .n = nComplexCallconv };
- break :blk switch (s.n) {
- 0 => .C,
- 1 => .Inline,
- else => .Unspecified,
- };
-}) struct { x: u32 } {
- return .{ .x = x * x };
-}
-
-test "function with complex callconv and return type expressions" {
- try expect(fComplexCallconvRet(3).x == 9);
-}
test/behavior/generics.zig
@@ -134,3 +134,32 @@ test "use generic param in generic param" {
fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
return a + b;
}
+
+test "generic fn with implicit cast" {
+ try expect(getFirstByte(u8, &[_]u8{13}) == 13);
+ try expect(getFirstByte(u16, &[_]u16{
+ 0,
+ 13,
+ }) == 0);
+}
+fn getByte(ptr: ?*const u8) u8 {
+ return ptr.?.*;
+}
+fn getFirstByte(comptime T: type, mem: []const T) u8 {
+ return getByte(@ptrCast(*const u8, &mem[0]));
+}
+
+test "generic fn keeps non-generic parameter types" {
+ const A = 128;
+
+ const S = struct {
+ fn f(comptime T: type, s: []T) !void {
+ try expect(A != @typeInfo(@TypeOf(s)).Pointer.alignment);
+ }
+ };
+
+ // The compiler monomorphizes `S.f` for `T=u8` on its first use, check that
+ // `x` type not affect `s` parameter type.
+ var x: [16]u8 align(A) = undefined;
+ try S.f(u8, &x);
+}
test/behavior/generics_llvm.zig
@@ -0,0 +1,42 @@
+const std = @import("std");
+const expect = std.testing.expect;
+
+const foos = [_]fn (anytype) bool{
+ foo1,
+ foo2,
+};
+
+fn foo1(arg: anytype) bool {
+ return arg;
+}
+fn foo2(arg: anytype) bool {
+ return !arg;
+}
+
+test "array of generic fns" {
+ try expect(foos[0](true));
+ try expect(!foos[1](true));
+}
+
+test "generic struct" {
+ var a1 = GenNode(i32){
+ .value = 13,
+ .next = null,
+ };
+ var b1 = GenNode(bool){
+ .value = true,
+ .next = null,
+ };
+ try expect(a1.value == 13);
+ try expect(a1.value == a1.getVal());
+ try expect(b1.getVal());
+}
+fn GenNode(comptime T: type) type {
+ return struct {
+ value: T,
+ next: ?*GenNode(T),
+ fn getVal(n: *const GenNode(T)) T {
+ return n.value;
+ }
+ };
+}
test/behavior/generics_stage1.zig
@@ -1,73 +0,0 @@
-const std = @import("std");
-const testing = std.testing;
-const expect = testing.expect;
-const expectEqual = testing.expectEqual;
-
-test "generic struct" {
- var a1 = GenNode(i32){
- .value = 13,
- .next = null,
- };
- var b1 = GenNode(bool){
- .value = true,
- .next = null,
- };
- try expect(a1.value == 13);
- try expect(a1.value == a1.getVal());
- try expect(b1.getVal());
-}
-fn GenNode(comptime T: type) type {
- return struct {
- value: T,
- next: ?*GenNode(T),
- fn getVal(n: *const GenNode(T)) T {
- return n.value;
- }
- };
-}
-
-test "generic fn with implicit cast" {
- try expect(getFirstByte(u8, &[_]u8{13}) == 13);
- try expect(getFirstByte(u16, &[_]u16{
- 0,
- 13,
- }) == 0);
-}
-fn getByte(ptr: ?*const u8) u8 {
- return ptr.?.*;
-}
-fn getFirstByte(comptime T: type, mem: []const T) u8 {
- return getByte(@ptrCast(*const u8, &mem[0]));
-}
-
-const foos = [_]fn (anytype) bool{
- foo1,
- foo2,
-};
-
-fn foo1(arg: anytype) bool {
- return arg;
-}
-fn foo2(arg: anytype) bool {
- return !arg;
-}
-
-test "array of generic fns" {
- try expect(foos[0](true));
- try expect(!foos[1](true));
-}
-
-test "generic fn keeps non-generic parameter types" {
- const A = 128;
-
- const S = struct {
- fn f(comptime T: type, s: []T) !void {
- try expect(A != @typeInfo(@TypeOf(s)).Pointer.alignment);
- }
- };
-
- // The compiler monomorphizes `S.f` for `T=u8` on its first use, check that
- // `x` type not affect `s` parameter type.
- var x: [16]u8 align(A) = undefined;
- try S.f(u8, &x);
-}
test/behavior.zig
@@ -58,6 +58,7 @@ test {
_ = @import("behavior/floatop.zig");
_ = @import("behavior/fn.zig");
_ = @import("behavior/for.zig");
+ _ = @import("behavior/generics_llvm.zig");
_ = @import("behavior/math.zig");
_ = @import("behavior/maximum_minimum.zig");
_ = @import("behavior/null_llvm.zig");
@@ -145,7 +146,6 @@ test {
_ = @import("behavior/fn_delegation.zig");
_ = @import("behavior/fn_in_struct_in_comptime.zig");
_ = @import("behavior/for_stage1.zig");
- _ = @import("behavior/generics_stage1.zig");
_ = @import("behavior/if_stage1.zig");
_ = @import("behavior/import.zig");
_ = @import("behavior/incomplete_struct_param_tld.zig");