stage2: move some tests which are now passing

This commit is contained in:
Robin Voetter 2021-11-22 03:32:28 +01:00
parent cb248898ab
commit 2b589d71fb
9 changed files with 275 additions and 275 deletions

View File

@ -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");

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}
};
}

View File

@ -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);
}