mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 14:25:16 +00:00
stage2: move some tests which are now passing
This commit is contained in:
parent
cb248898ab
commit
2b589d71fb
@ -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");
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
42
test/behavior/generics_llvm.zig
Normal file
42
test/behavior/generics_llvm.zig
Normal 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;
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user