organize behavior tests
Every test that is moved in this commit has been checked to see if it is now passing.
This commit is contained in:
@@ -91,8 +91,9 @@ test {
|
||||
// Tests that pass for stage1 and the llvm backend.
|
||||
_ = @import("behavior/array_llvm.zig");
|
||||
_ = @import("behavior/atomics.zig");
|
||||
_ = @import("behavior/basic_llvm.zig");
|
||||
_ = @import("behavior/bugs/1025.zig");
|
||||
_ = @import("behavior/bugs/1741.zig");
|
||||
_ = @import("behavior/bugs/1914.zig");
|
||||
_ = @import("behavior/bugs/2578.zig");
|
||||
_ = @import("behavior/bugs/3007.zig");
|
||||
_ = @import("behavior/bugs/9584.zig");
|
||||
@@ -116,13 +117,11 @@ test {
|
||||
|
||||
if (builtin.zig_backend == .stage1) {
|
||||
// Tests that only pass for the stage1 backend.
|
||||
_ = @import("behavior/align_stage1.zig");
|
||||
if (builtin.os.tag != .wasi) {
|
||||
_ = @import("behavior/asm.zig");
|
||||
_ = @import("behavior/async_fn.zig");
|
||||
}
|
||||
_ = @import("behavior/await_struct.zig");
|
||||
_ = @import("behavior/bitcast_stage1.zig");
|
||||
_ = @import("behavior/bitreverse.zig");
|
||||
_ = @import("behavior/bugs/421.zig");
|
||||
_ = @import("behavior/bugs/529.zig");
|
||||
@@ -130,14 +129,12 @@ test {
|
||||
_ = @import("behavior/bugs/726.zig");
|
||||
_ = @import("behavior/bugs/828.zig");
|
||||
_ = @import("behavior/bugs/920.zig");
|
||||
_ = @import("behavior/bugs/1025.zig");
|
||||
_ = @import("behavior/bugs/1076.zig");
|
||||
_ = @import("behavior/bugs/1120.zig");
|
||||
_ = @import("behavior/bugs/1421.zig");
|
||||
_ = @import("behavior/bugs/1442.zig");
|
||||
_ = @import("behavior/bugs/1607.zig");
|
||||
_ = @import("behavior/bugs/1851.zig");
|
||||
_ = @import("behavior/bugs/1914.zig");
|
||||
_ = @import("behavior/bugs/2114.zig");
|
||||
_ = @import("behavior/bugs/3384.zig");
|
||||
_ = @import("behavior/bugs/3742.zig");
|
||||
@@ -155,18 +152,11 @@ test {
|
||||
_ = @import("behavior/bugs/10147.zig");
|
||||
_ = @import("behavior/byteswap.zig");
|
||||
_ = @import("behavior/call_stage1.zig");
|
||||
_ = @import("behavior/cast_stage1.zig");
|
||||
_ = @import("behavior/const_slice_child.zig");
|
||||
_ = @import("behavior/defer_stage1.zig");
|
||||
_ = @import("behavior/enum_stage1.zig");
|
||||
_ = @import("behavior/error_stage1.zig");
|
||||
_ = @import("behavior/eval_stage1.zig");
|
||||
_ = @import("behavior/field_parent_ptr.zig");
|
||||
_ = @import("behavior/floatop_stage1.zig");
|
||||
_ = @import("behavior/fn_stage1.zig");
|
||||
_ = @import("behavior/fn_delegation.zig");
|
||||
_ = @import("behavior/for_stage1.zig");
|
||||
_ = @import("behavior/if_stage1.zig");
|
||||
_ = @import("behavior/ir_block_deps.zig");
|
||||
_ = @import("behavior/math_stage1.zig");
|
||||
_ = @import("behavior/misc.zig");
|
||||
|
||||
@@ -204,3 +204,229 @@ test "function alignment" {
|
||||
noop1();
|
||||
noop4();
|
||||
}
|
||||
|
||||
test "implicitly decreasing fn alignment" {
|
||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
|
||||
// function alignment is a compile error on wasm32/wasm64
|
||||
if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
|
||||
|
||||
try testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
|
||||
try testImplicitlyDecreaseFnAlign(alignedBig, 5678);
|
||||
}
|
||||
|
||||
// TODO make it a compile error to put align on the fn proto instead of on the ptr
|
||||
fn testImplicitlyDecreaseFnAlign(ptr: *align(1) const fn () i32, answer: i32) !void {
|
||||
try expect(ptr() == answer);
|
||||
}
|
||||
|
||||
fn alignedSmall() align(8) i32 {
|
||||
return 1234;
|
||||
}
|
||||
fn alignedBig() align(16) i32 {
|
||||
return 5678;
|
||||
}
|
||||
|
||||
test "@alignCast functions" {
|
||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
|
||||
// function alignment is a compile error on wasm32/wasm64
|
||||
if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
|
||||
if (native_arch == .thumb) return error.SkipZigTest;
|
||||
|
||||
try expect(fnExpectsOnly1(simple4) == 0x19);
|
||||
}
|
||||
fn fnExpectsOnly1(ptr: *const fn () align(1) i32) i32 {
|
||||
return fnExpects4(@alignCast(4, ptr));
|
||||
}
|
||||
fn fnExpects4(ptr: *align(4) const fn () i32) i32 {
|
||||
return ptr();
|
||||
}
|
||||
fn simple4() align(4) i32 {
|
||||
return 0x19;
|
||||
}
|
||||
|
||||
test "generic function with align param" {
|
||||
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
|
||||
// function alignment is a compile error on wasm32/wasm64
|
||||
if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
|
||||
if (native_arch == .thumb) return error.SkipZigTest;
|
||||
|
||||
try expect(whyWouldYouEverDoThis(1) == 0x1);
|
||||
try expect(whyWouldYouEverDoThis(4) == 0x1);
|
||||
try expect(whyWouldYouEverDoThis(8) == 0x1);
|
||||
}
|
||||
|
||||
fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
|
||||
_ = align_bytes;
|
||||
return 0x1;
|
||||
}
|
||||
|
||||
test "runtime known array index has best alignment possible" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
|
||||
// take full advantage of over-alignment
|
||||
var array align(4) = [_]u8{ 1, 2, 3, 4 };
|
||||
try expect(@TypeOf(&array[0]) == *align(4) u8);
|
||||
try expect(@TypeOf(&array[1]) == *u8);
|
||||
try expect(@TypeOf(&array[2]) == *align(2) u8);
|
||||
try expect(@TypeOf(&array[3]) == *u8);
|
||||
|
||||
// because align is too small but we still figure out to use 2
|
||||
var bigger align(2) = [_]u64{ 1, 2, 3, 4 };
|
||||
try expect(@TypeOf(&bigger[0]) == *align(2) u64);
|
||||
try expect(@TypeOf(&bigger[1]) == *align(2) u64);
|
||||
try expect(@TypeOf(&bigger[2]) == *align(2) u64);
|
||||
try expect(@TypeOf(&bigger[3]) == *align(2) u64);
|
||||
|
||||
// because pointer is align 2 and u32 align % 2 == 0 we can assume align 2
|
||||
var smaller align(2) = [_]u32{ 1, 2, 3, 4 };
|
||||
var runtime_zero: usize = 0;
|
||||
comptime try expect(@TypeOf(smaller[runtime_zero..]) == []align(2) u32);
|
||||
comptime try expect(@TypeOf(smaller[runtime_zero..].ptr) == [*]align(2) u32);
|
||||
try testIndex(smaller[runtime_zero..].ptr, 0, *align(2) u32);
|
||||
try testIndex(smaller[runtime_zero..].ptr, 1, *align(2) u32);
|
||||
try testIndex(smaller[runtime_zero..].ptr, 2, *align(2) u32);
|
||||
try testIndex(smaller[runtime_zero..].ptr, 3, *align(2) u32);
|
||||
|
||||
// has to use ABI alignment because index known at runtime only
|
||||
try testIndex2(array[runtime_zero..].ptr, 0, *u8);
|
||||
try testIndex2(array[runtime_zero..].ptr, 1, *u8);
|
||||
try testIndex2(array[runtime_zero..].ptr, 2, *u8);
|
||||
try testIndex2(array[runtime_zero..].ptr, 3, *u8);
|
||||
}
|
||||
fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) !void {
|
||||
comptime try expect(@TypeOf(&smaller[index]) == T);
|
||||
}
|
||||
fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) !void {
|
||||
comptime try expect(@TypeOf(&ptr[index]) == T);
|
||||
}
|
||||
|
||||
test "alignment of function with c calling convention" {
|
||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||
|
||||
var runtime_nothing = ¬hing;
|
||||
const casted1 = @ptrCast(*const u8, runtime_nothing);
|
||||
const casted2 = @ptrCast(*const fn () callconv(.C) void, casted1);
|
||||
casted2();
|
||||
}
|
||||
|
||||
fn nothing() callconv(.C) void {}
|
||||
|
||||
const DefaultAligned = struct {
|
||||
nevermind: u32,
|
||||
badguy: i128,
|
||||
};
|
||||
|
||||
test "read 128-bit field from default aligned struct in stack memory" {
|
||||
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
|
||||
var default_aligned = DefaultAligned{
|
||||
.nevermind = 1,
|
||||
.badguy = 12,
|
||||
};
|
||||
try expect((@ptrToInt(&default_aligned.badguy) % 16) == 0);
|
||||
try expect(12 == default_aligned.badguy);
|
||||
}
|
||||
|
||||
var default_aligned_global = DefaultAligned{
|
||||
.nevermind = 1,
|
||||
.badguy = 12,
|
||||
};
|
||||
|
||||
test "read 128-bit field from default aligned struct in global memory" {
|
||||
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
|
||||
try expect((@ptrToInt(&default_aligned_global.badguy) % 16) == 0);
|
||||
try expect(12 == default_aligned_global.badguy);
|
||||
}
|
||||
|
||||
test "struct field explicit alignment" {
|
||||
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
|
||||
const S = struct {
|
||||
const Node = struct {
|
||||
next: *Node,
|
||||
massive_byte: u8 align(64),
|
||||
};
|
||||
};
|
||||
|
||||
var node: S.Node = undefined;
|
||||
node.massive_byte = 100;
|
||||
try expect(node.massive_byte == 100);
|
||||
comptime try expect(@TypeOf(&node.massive_byte) == *align(64) u8);
|
||||
try expect(@ptrToInt(&node.massive_byte) % 64 == 0);
|
||||
}
|
||||
|
||||
test "align(@alignOf(T)) T does not force resolution of T" {
|
||||
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
|
||||
const S = struct {
|
||||
const A = struct {
|
||||
a: *align(@alignOf(A)) A,
|
||||
};
|
||||
fn doTheTest() void {
|
||||
suspend {
|
||||
resume @frame();
|
||||
}
|
||||
_ = bar(@Frame(doTheTest));
|
||||
}
|
||||
fn bar(comptime T: type) *align(@alignOf(T)) T {
|
||||
ok = true;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var ok = false;
|
||||
};
|
||||
_ = async S.doTheTest();
|
||||
try expect(S.ok);
|
||||
}
|
||||
|
||||
test "align(N) on functions" {
|
||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
|
||||
// function alignment is a compile error on wasm32/wasm64
|
||||
if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
|
||||
if (native_arch == .thumb) return error.SkipZigTest;
|
||||
|
||||
try expect((@ptrToInt(&overaligned_fn) & (0x1000 - 1)) == 0);
|
||||
}
|
||||
fn overaligned_fn() align(0x1000) i32 {
|
||||
return 42;
|
||||
}
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const builtin = @import("builtin");
|
||||
const native_arch = builtin.target.cpu.arch;
|
||||
|
||||
test "implicitly decreasing fn alignment" {
|
||||
// function alignment is a compile error on wasm32/wasm64
|
||||
if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
|
||||
|
||||
try testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
|
||||
try testImplicitlyDecreaseFnAlign(alignedBig, 5678);
|
||||
}
|
||||
|
||||
fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) !void {
|
||||
try expect(ptr() == answer);
|
||||
}
|
||||
|
||||
fn alignedSmall() align(8) i32 {
|
||||
return 1234;
|
||||
}
|
||||
fn alignedBig() align(16) i32 {
|
||||
return 5678;
|
||||
}
|
||||
|
||||
test "@alignCast functions" {
|
||||
// function alignment is a compile error on wasm32/wasm64
|
||||
if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
|
||||
if (native_arch == .thumb) return error.SkipZigTest;
|
||||
|
||||
try expect(fnExpectsOnly1(simple4) == 0x19);
|
||||
}
|
||||
fn fnExpectsOnly1(ptr: fn () align(1) i32) i32 {
|
||||
return fnExpects4(@alignCast(4, ptr));
|
||||
}
|
||||
fn fnExpects4(ptr: fn () align(4) i32) i32 {
|
||||
return ptr();
|
||||
}
|
||||
fn simple4() align(4) i32 {
|
||||
return 0x19;
|
||||
}
|
||||
|
||||
test "generic function with align param" {
|
||||
// function alignment is a compile error on wasm32/wasm64
|
||||
if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
|
||||
if (native_arch == .thumb) return error.SkipZigTest;
|
||||
|
||||
try expect(whyWouldYouEverDoThis(1) == 0x1);
|
||||
try expect(whyWouldYouEverDoThis(4) == 0x1);
|
||||
try expect(whyWouldYouEverDoThis(8) == 0x1);
|
||||
}
|
||||
|
||||
fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
|
||||
_ = align_bytes;
|
||||
return 0x1;
|
||||
}
|
||||
|
||||
test "runtime known array index has best alignment possible" {
|
||||
// take full advantage of over-alignment
|
||||
var array align(4) = [_]u8{ 1, 2, 3, 4 };
|
||||
try expect(@TypeOf(&array[0]) == *align(4) u8);
|
||||
try expect(@TypeOf(&array[1]) == *u8);
|
||||
try expect(@TypeOf(&array[2]) == *align(2) u8);
|
||||
try expect(@TypeOf(&array[3]) == *u8);
|
||||
|
||||
// because align is too small but we still figure out to use 2
|
||||
var bigger align(2) = [_]u64{ 1, 2, 3, 4 };
|
||||
try expect(@TypeOf(&bigger[0]) == *align(2) u64);
|
||||
try expect(@TypeOf(&bigger[1]) == *align(2) u64);
|
||||
try expect(@TypeOf(&bigger[2]) == *align(2) u64);
|
||||
try expect(@TypeOf(&bigger[3]) == *align(2) u64);
|
||||
|
||||
// because pointer is align 2 and u32 align % 2 == 0 we can assume align 2
|
||||
var smaller align(2) = [_]u32{ 1, 2, 3, 4 };
|
||||
var runtime_zero: usize = 0;
|
||||
comptime try expect(@TypeOf(smaller[runtime_zero..]) == []align(2) u32);
|
||||
comptime try expect(@TypeOf(smaller[runtime_zero..].ptr) == [*]align(2) u32);
|
||||
try testIndex(smaller[runtime_zero..].ptr, 0, *align(2) u32);
|
||||
try testIndex(smaller[runtime_zero..].ptr, 1, *align(2) u32);
|
||||
try testIndex(smaller[runtime_zero..].ptr, 2, *align(2) u32);
|
||||
try testIndex(smaller[runtime_zero..].ptr, 3, *align(2) u32);
|
||||
|
||||
// has to use ABI alignment because index known at runtime only
|
||||
try testIndex2(array[runtime_zero..].ptr, 0, *u8);
|
||||
try testIndex2(array[runtime_zero..].ptr, 1, *u8);
|
||||
try testIndex2(array[runtime_zero..].ptr, 2, *u8);
|
||||
try testIndex2(array[runtime_zero..].ptr, 3, *u8);
|
||||
}
|
||||
fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) !void {
|
||||
comptime try expect(@TypeOf(&smaller[index]) == T);
|
||||
}
|
||||
fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) !void {
|
||||
comptime try expect(@TypeOf(&ptr[index]) == T);
|
||||
}
|
||||
|
||||
test "alignment of function with c calling convention" {
|
||||
var runtime_nothing = nothing;
|
||||
const casted1 = @ptrCast(*const u8, runtime_nothing);
|
||||
const casted2 = @ptrCast(fn () callconv(.C) void, casted1);
|
||||
casted2();
|
||||
}
|
||||
|
||||
fn nothing() callconv(.C) void {}
|
||||
|
||||
const DefaultAligned = struct {
|
||||
nevermind: u32,
|
||||
badguy: i128,
|
||||
};
|
||||
|
||||
test "read 128-bit field from default aligned struct in stack memory" {
|
||||
var default_aligned = DefaultAligned{
|
||||
.nevermind = 1,
|
||||
.badguy = 12,
|
||||
};
|
||||
try expect((@ptrToInt(&default_aligned.badguy) % 16) == 0);
|
||||
try expect(12 == default_aligned.badguy);
|
||||
}
|
||||
|
||||
var default_aligned_global = DefaultAligned{
|
||||
.nevermind = 1,
|
||||
.badguy = 12,
|
||||
};
|
||||
|
||||
test "read 128-bit field from default aligned struct in global memory" {
|
||||
try expect((@ptrToInt(&default_aligned_global.badguy) % 16) == 0);
|
||||
try expect(12 == default_aligned_global.badguy);
|
||||
}
|
||||
|
||||
test "struct field explicit alignment" {
|
||||
const S = struct {
|
||||
const Node = struct {
|
||||
next: *Node,
|
||||
massive_byte: u8 align(64),
|
||||
};
|
||||
};
|
||||
|
||||
var node: S.Node = undefined;
|
||||
node.massive_byte = 100;
|
||||
try expect(node.massive_byte == 100);
|
||||
comptime try expect(@TypeOf(&node.massive_byte) == *align(64) u8);
|
||||
try expect(@ptrToInt(&node.massive_byte) % 64 == 0);
|
||||
}
|
||||
|
||||
test "align(@alignOf(T)) T does not force resolution of T" {
|
||||
const S = struct {
|
||||
const A = struct {
|
||||
a: *align(@alignOf(A)) A,
|
||||
};
|
||||
fn doTheTest() void {
|
||||
suspend {
|
||||
resume @frame();
|
||||
}
|
||||
_ = bar(@Frame(doTheTest));
|
||||
}
|
||||
fn bar(comptime T: type) *align(@alignOf(T)) T {
|
||||
ok = true;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var ok = false;
|
||||
};
|
||||
_ = async S.doTheTest();
|
||||
try expect(S.ok);
|
||||
}
|
||||
|
||||
test "align(N) on functions" {
|
||||
// function alignment is a compile error on wasm32/wasm64
|
||||
if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
|
||||
if (native_arch == .thumb) return error.SkipZigTest;
|
||||
|
||||
try expect((@ptrToInt(overaligned_fn) & (0x1000 - 1)) == 0);
|
||||
}
|
||||
fn overaligned_fn() align(0x1000) i32 {
|
||||
return 42;
|
||||
}
|
||||
@@ -294,3 +294,402 @@ test "const ptr from var variable" {
|
||||
fn copy(src: *const u64, dst: *u64) void {
|
||||
dst.* = src.*;
|
||||
}
|
||||
|
||||
test "call result of if else expression" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
|
||||
try expect(mem.eql(u8, f2(true), "a"));
|
||||
try expect(mem.eql(u8, f2(false), "b"));
|
||||
}
|
||||
fn f2(x: bool) []const u8 {
|
||||
return (if (x) fA else fB)();
|
||||
}
|
||||
|
||||
test "memcpy and memset intrinsics" {
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
|
||||
try testMemcpyMemset();
|
||||
// TODO add comptime test coverage
|
||||
//comptime try testMemcpyMemset();
|
||||
}
|
||||
|
||||
fn testMemcpyMemset() !void {
|
||||
var foo: [20]u8 = undefined;
|
||||
var bar: [20]u8 = undefined;
|
||||
|
||||
@memset(&foo, 'A', foo.len);
|
||||
@memcpy(&bar, &foo, bar.len);
|
||||
|
||||
try expect(bar[0] == 'A');
|
||||
try expect(bar[11] == 'A');
|
||||
try expect(bar[19] == 'A');
|
||||
}
|
||||
|
||||
test "variable is allowed to be a pointer to an opaque type" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
|
||||
var x: i32 = 1234;
|
||||
_ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x));
|
||||
}
|
||||
fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
|
||||
var a = ptr;
|
||||
return a;
|
||||
}
|
||||
|
||||
test "take address of parameter" {
|
||||
try testTakeAddressOfParameter(12.34);
|
||||
}
|
||||
fn testTakeAddressOfParameter(f: f32) !void {
|
||||
const f_ptr = &f;
|
||||
try expect(f_ptr.* == 12.34);
|
||||
}
|
||||
|
||||
test "pointer to void return type" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
|
||||
try testPointerToVoidReturnType();
|
||||
}
|
||||
fn testPointerToVoidReturnType() anyerror!void {
|
||||
const a = testPointerToVoidReturnType2();
|
||||
return a.*;
|
||||
}
|
||||
const test_pointer_to_void_return_type_x = void{};
|
||||
fn testPointerToVoidReturnType2() *const void {
|
||||
return &test_pointer_to_void_return_type_x;
|
||||
}
|
||||
|
||||
test "array 2D const double ptr" {
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
|
||||
const rect_2d_vertexes = [_][1]f32{
|
||||
[_]f32{1.0},
|
||||
[_]f32{2.0},
|
||||
};
|
||||
try testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]);
|
||||
}
|
||||
|
||||
fn testArray2DConstDoublePtr(ptr: *const f32) !void {
|
||||
const ptr2 = @ptrCast([*]const f32, ptr);
|
||||
try expect(ptr2[0] == 1.0);
|
||||
try expect(ptr2[1] == 2.0);
|
||||
}
|
||||
|
||||
test "double implicit cast in same expression" {
|
||||
var x = @as(i32, @as(u16, nine()));
|
||||
try expect(x == 9);
|
||||
}
|
||||
fn nine() u8 {
|
||||
return 9;
|
||||
}
|
||||
|
||||
test "struct inside function" {
|
||||
try testStructInFn();
|
||||
comptime try testStructInFn();
|
||||
}
|
||||
|
||||
fn testStructInFn() !void {
|
||||
const BlockKind = u32;
|
||||
|
||||
const Block = struct {
|
||||
kind: BlockKind,
|
||||
};
|
||||
|
||||
var block = Block{ .kind = 1234 };
|
||||
|
||||
block.kind += 1;
|
||||
|
||||
try expect(block.kind == 1235);
|
||||
}
|
||||
|
||||
test "fn call returning scalar optional in equality expression" {
|
||||
try expect(getNull() == null);
|
||||
}
|
||||
|
||||
fn getNull() ?*i32 {
|
||||
return null;
|
||||
}
|
||||
|
||||
test "global variable assignment with optional unwrapping with var initialized to undefined" {
|
||||
const S = struct {
|
||||
var data: i32 = 1234;
|
||||
fn foo() ?*i32 {
|
||||
return &data;
|
||||
}
|
||||
};
|
||||
global_foo = S.foo() orelse {
|
||||
@panic("bad");
|
||||
};
|
||||
try expect(global_foo.* == 1234);
|
||||
}
|
||||
|
||||
var global_foo: *i32 = undefined;
|
||||
|
||||
test "peer result location with typed parent, runtime condition, comptime prongs" {
|
||||
const S = struct {
|
||||
fn doTheTest(arg: i32) i32 {
|
||||
const st = Structy{
|
||||
.bleh = if (arg == 1) 1 else 1,
|
||||
};
|
||||
|
||||
if (st.bleh == 1)
|
||||
return 1234;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Structy = struct {
|
||||
bleh: i32,
|
||||
};
|
||||
};
|
||||
try expect(S.doTheTest(0) == 1234);
|
||||
try expect(S.doTheTest(1) == 1234);
|
||||
}
|
||||
|
||||
test "non-ambiguous reference of shadowed decls" {
|
||||
try expect(ZA().B().Self != ZA().Self);
|
||||
}
|
||||
|
||||
fn ZA() type {
|
||||
return struct {
|
||||
b: B(),
|
||||
|
||||
const Self = @This();
|
||||
|
||||
fn B() type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
test "use of declaration with same name as primitive" {
|
||||
const S = struct {
|
||||
const @"u8" = u16;
|
||||
const alias = @"u8";
|
||||
};
|
||||
const a: S.u8 = 300;
|
||||
try expect(a == 300);
|
||||
|
||||
const b: S.alias = 300;
|
||||
try expect(b == 300);
|
||||
|
||||
const @"u8" = u16;
|
||||
const c: @"u8" = 300;
|
||||
try expect(c == 300);
|
||||
}
|
||||
|
||||
test "constant equal function pointers" {
|
||||
const alias = emptyFn;
|
||||
try expect(comptime x: {
|
||||
break :x emptyFn == alias;
|
||||
});
|
||||
}
|
||||
|
||||
fn emptyFn() void {}
|
||||
|
||||
const addr1 = @ptrCast(*const u8, &emptyFn);
|
||||
test "comptime cast fn to ptr" {
|
||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||
|
||||
const addr2 = @ptrCast(*const u8, &emptyFn);
|
||||
comptime try expect(addr1 == addr2);
|
||||
}
|
||||
|
||||
test "equality compare fn ptrs" {
|
||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||
|
||||
var a = &emptyFn;
|
||||
try expect(a == a);
|
||||
}
|
||||
|
||||
test "self reference through fn ptr field" {
|
||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
|
||||
const S = struct {
|
||||
const A = struct {
|
||||
f: *const fn (A) u8,
|
||||
};
|
||||
|
||||
fn foo(a: A) u8 {
|
||||
_ = a;
|
||||
return 12;
|
||||
}
|
||||
};
|
||||
var a: S.A = undefined;
|
||||
a.f = S.foo;
|
||||
try expect(a.f(a) == 12);
|
||||
}
|
||||
|
||||
test "global variable initialized to global variable array element" {
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
|
||||
try expect(global_ptr == &gdt[0]);
|
||||
}
|
||||
const GDTEntry = struct {
|
||||
field: i32,
|
||||
};
|
||||
var gdt = [_]GDTEntry{
|
||||
GDTEntry{ .field = 1 },
|
||||
GDTEntry{ .field = 2 },
|
||||
};
|
||||
var global_ptr = &gdt[0];
|
||||
|
||||
test "global constant is loaded with a runtime-known index" {
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var index: usize = 1;
|
||||
const ptr = &pieces[index].field;
|
||||
try expect(ptr.* == 2);
|
||||
}
|
||||
const Piece = struct {
|
||||
field: i32,
|
||||
};
|
||||
const pieces = [_]Piece{ Piece{ .field = 1 }, Piece{ .field = 2 }, Piece{ .field = 3 } };
|
||||
};
|
||||
try S.doTheTest();
|
||||
}
|
||||
|
||||
test "multiline string literal is null terminated" {
|
||||
const s1 =
|
||||
\\one
|
||||
\\two)
|
||||
\\three
|
||||
;
|
||||
const s2 = "one\ntwo)\nthree";
|
||||
try expect(std.cstr.cmp(s1, s2) == 0);
|
||||
}
|
||||
|
||||
test "string escapes" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
try expectEqualStrings("\"", "\x22");
|
||||
try expectEqualStrings("\'", "\x27");
|
||||
try expectEqualStrings("\n", "\x0a");
|
||||
try expectEqualStrings("\r", "\x0d");
|
||||
try expectEqualStrings("\t", "\x09");
|
||||
try expectEqualStrings("\\", "\x5c");
|
||||
try expectEqualStrings("\u{1234}\u{069}\u{1}", "\xe1\x88\xb4\x69\x01");
|
||||
}
|
||||
|
||||
test "explicit cast optional pointers" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const a: ?*i32 = undefined;
|
||||
const b: ?*f32 = @ptrCast(?*f32, a);
|
||||
_ = b;
|
||||
}
|
||||
|
||||
test "pointer comparison" {
|
||||
const a = @as([]const u8, "a");
|
||||
const b = &a;
|
||||
try expect(ptrEql(b, b));
|
||||
}
|
||||
fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
|
||||
return a == b;
|
||||
}
|
||||
|
||||
test "string concatenation" {
|
||||
const a = "OK" ++ " IT " ++ "WORKED";
|
||||
const b = "OK IT WORKED";
|
||||
|
||||
comptime try expect(@TypeOf(a) == *const [12:0]u8);
|
||||
comptime try expect(@TypeOf(b) == *const [12:0]u8);
|
||||
|
||||
const len = mem.len(b);
|
||||
const len_with_null = len + 1;
|
||||
{
|
||||
var i: u32 = 0;
|
||||
while (i < len_with_null) : (i += 1) {
|
||||
try expect(a[i] == b[i]);
|
||||
}
|
||||
}
|
||||
try expect(a[len] == 0);
|
||||
try expect(b[len] == 0);
|
||||
}
|
||||
|
||||
test "thread local variable" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
threadlocal var t: i32 = 1234;
|
||||
};
|
||||
S.t += 1;
|
||||
try expect(S.t == 1235);
|
||||
}
|
||||
|
||||
test "result location is optional inside error union" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const x = maybe(true) catch unreachable;
|
||||
try expect(x.? == 42);
|
||||
}
|
||||
|
||||
fn maybe(x: bool) anyerror!?u32 {
|
||||
return switch (x) {
|
||||
true => @as(u32, 42),
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
|
||||
test "pointer to thread local array" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const s = "Hello world";
|
||||
std.mem.copy(u8, buffer[0..], s);
|
||||
try std.testing.expectEqualSlices(u8, buffer[0..], s);
|
||||
}
|
||||
|
||||
threadlocal var buffer: [11]u8 = undefined;
|
||||
|
||||
test "auto created variables have correct alignment" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn foo(str: [*]const u8) u32 {
|
||||
for (@ptrCast([*]align(1) const u32, str)[0..1]) |v| {
|
||||
return v;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
try expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
|
||||
comptime try expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
|
||||
}
|
||||
|
||||
test "extern variable with non-pointer opaque type" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
@export(var_to_export, .{ .name = "opaque_extern_var" });
|
||||
try expect(@ptrCast(*align(1) u32, &opaque_extern_var).* == 42);
|
||||
}
|
||||
extern var opaque_extern_var: opaque {};
|
||||
var var_to_export: u32 = 42;
|
||||
|
||||
test "lazy typeInfo value as generic parameter" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn foo(args: anytype) void {
|
||||
_ = args;
|
||||
}
|
||||
};
|
||||
S.foo(@typeInfo(@TypeOf(.{})));
|
||||
}
|
||||
|
||||
test "variable name containing underscores does not shadow int primitive" {
|
||||
const _u0 = 0;
|
||||
const i_8 = 0;
|
||||
const u16_ = 0;
|
||||
const i3_2 = 0;
|
||||
const u6__4 = 0;
|
||||
const i2_04_8 = 0;
|
||||
|
||||
_ = _u0;
|
||||
_ = i_8;
|
||||
_ = u16_;
|
||||
_ = i3_2;
|
||||
_ = u6__4;
|
||||
_ = i2_04_8;
|
||||
}
|
||||
|
||||
@@ -1,250 +0,0 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const mem = std.mem;
|
||||
const expect = std.testing.expect;
|
||||
const expectEqualStrings = std.testing.expectEqualStrings;
|
||||
|
||||
test "call result of if else expression" {
|
||||
try expect(mem.eql(u8, f2(true), "a"));
|
||||
try expect(mem.eql(u8, f2(false), "b"));
|
||||
}
|
||||
fn f2(x: bool) []const u8 {
|
||||
return (if (x) fA else fB)();
|
||||
}
|
||||
fn fA() []const u8 {
|
||||
return "a";
|
||||
}
|
||||
fn fB() []const u8 {
|
||||
return "b";
|
||||
}
|
||||
|
||||
test "memcpy and memset intrinsics" {
|
||||
try testMemcpyMemset();
|
||||
// TODO add comptime test coverage
|
||||
//comptime try testMemcpyMemset();
|
||||
}
|
||||
|
||||
fn testMemcpyMemset() !void {
|
||||
var foo: [20]u8 = undefined;
|
||||
var bar: [20]u8 = undefined;
|
||||
|
||||
@memset(&foo, 'A', foo.len);
|
||||
@memcpy(&bar, &foo, bar.len);
|
||||
|
||||
try expect(bar[0] == 'A');
|
||||
try expect(bar[11] == 'A');
|
||||
try expect(bar[19] == 'A');
|
||||
}
|
||||
|
||||
const OpaqueA = opaque {};
|
||||
const OpaqueB = opaque {};
|
||||
|
||||
test "variable is allowed to be a pointer to an opaque type" {
|
||||
var x: i32 = 1234;
|
||||
_ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x));
|
||||
}
|
||||
fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
|
||||
var a = ptr;
|
||||
return a;
|
||||
}
|
||||
|
||||
test "take address of parameter" {
|
||||
try testTakeAddressOfParameter(12.34);
|
||||
}
|
||||
fn testTakeAddressOfParameter(f: f32) !void {
|
||||
const f_ptr = &f;
|
||||
try expect(f_ptr.* == 12.34);
|
||||
}
|
||||
|
||||
test "pointer to void return type" {
|
||||
try testPointerToVoidReturnType();
|
||||
}
|
||||
fn testPointerToVoidReturnType() anyerror!void {
|
||||
const a = testPointerToVoidReturnType2();
|
||||
return a.*;
|
||||
}
|
||||
const test_pointer_to_void_return_type_x = void{};
|
||||
fn testPointerToVoidReturnType2() *const void {
|
||||
return &test_pointer_to_void_return_type_x;
|
||||
}
|
||||
|
||||
test "array 2D const double ptr" {
|
||||
const rect_2d_vertexes = [_][1]f32{
|
||||
[_]f32{1.0},
|
||||
[_]f32{2.0},
|
||||
};
|
||||
try testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]);
|
||||
}
|
||||
|
||||
fn testArray2DConstDoublePtr(ptr: *const f32) !void {
|
||||
const ptr2 = @ptrCast([*]const f32, ptr);
|
||||
try expect(ptr2[0] == 1.0);
|
||||
try expect(ptr2[1] == 2.0);
|
||||
}
|
||||
|
||||
test "double implicit cast in same expression" {
|
||||
var x = @as(i32, @as(u16, nine()));
|
||||
try expect(x == 9);
|
||||
}
|
||||
fn nine() u8 {
|
||||
return 9;
|
||||
}
|
||||
|
||||
test "struct inside function" {
|
||||
try testStructInFn();
|
||||
comptime try testStructInFn();
|
||||
}
|
||||
|
||||
fn testStructInFn() !void {
|
||||
const BlockKind = u32;
|
||||
|
||||
const Block = struct {
|
||||
kind: BlockKind,
|
||||
};
|
||||
|
||||
var block = Block{ .kind = 1234 };
|
||||
|
||||
block.kind += 1;
|
||||
|
||||
try expect(block.kind == 1235);
|
||||
}
|
||||
|
||||
test "fn call returning scalar optional in equality expression" {
|
||||
try expect(getNull() == null);
|
||||
}
|
||||
|
||||
fn getNull() ?*i32 {
|
||||
return null;
|
||||
}
|
||||
|
||||
var global_foo: *i32 = undefined;
|
||||
|
||||
test "global variable assignment with optional unwrapping with var initialized to undefined" {
|
||||
const S = struct {
|
||||
var data: i32 = 1234;
|
||||
fn foo() ?*i32 {
|
||||
return &data;
|
||||
}
|
||||
};
|
||||
global_foo = S.foo() orelse {
|
||||
@panic("bad");
|
||||
};
|
||||
try expect(global_foo.* == 1234);
|
||||
}
|
||||
|
||||
test "peer result location with typed parent, runtime condition, comptime prongs" {
|
||||
const S = struct {
|
||||
fn doTheTest(arg: i32) i32 {
|
||||
const st = Structy{
|
||||
.bleh = if (arg == 1) 1 else 1,
|
||||
};
|
||||
|
||||
if (st.bleh == 1)
|
||||
return 1234;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Structy = struct {
|
||||
bleh: i32,
|
||||
};
|
||||
};
|
||||
try expect(S.doTheTest(0) == 1234);
|
||||
try expect(S.doTheTest(1) == 1234);
|
||||
}
|
||||
|
||||
fn ZA() type {
|
||||
return struct {
|
||||
b: B(),
|
||||
|
||||
const Self = @This();
|
||||
|
||||
fn B() type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
test "non-ambiguous reference of shadowed decls" {
|
||||
try expect(ZA().B().Self != ZA().Self);
|
||||
}
|
||||
|
||||
test "use of declaration with same name as primitive" {
|
||||
const S = struct {
|
||||
const @"u8" = u16;
|
||||
const alias = @"u8";
|
||||
};
|
||||
const a: S.u8 = 300;
|
||||
try expect(a == 300);
|
||||
|
||||
const b: S.alias = 300;
|
||||
try expect(b == 300);
|
||||
|
||||
const @"u8" = u16;
|
||||
const c: @"u8" = 300;
|
||||
try expect(c == 300);
|
||||
}
|
||||
|
||||
fn emptyFn() void {}
|
||||
|
||||
test "constant equal function pointers" {
|
||||
const alias = emptyFn;
|
||||
try expect(comptime x: {
|
||||
break :x emptyFn == alias;
|
||||
});
|
||||
}
|
||||
|
||||
test "multiline string literal is null terminated" {
|
||||
const s1 =
|
||||
\\one
|
||||
\\two)
|
||||
\\three
|
||||
;
|
||||
const s2 = "one\ntwo)\nthree";
|
||||
try expect(std.cstr.cmp(s1, s2) == 0);
|
||||
}
|
||||
|
||||
test "self reference through fn ptr field" {
|
||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||
|
||||
const S = struct {
|
||||
const A = struct {
|
||||
f: *const fn (A) u8,
|
||||
};
|
||||
|
||||
fn foo(a: A) u8 {
|
||||
_ = a;
|
||||
return 12;
|
||||
}
|
||||
};
|
||||
var a: S.A = undefined;
|
||||
a.f = S.foo;
|
||||
try expect(a.f(a) == 12);
|
||||
}
|
||||
|
||||
test "global variable initialized to global variable array element" {
|
||||
try expect(global_ptr == &gdt[0]);
|
||||
}
|
||||
const GDTEntry = struct {
|
||||
field: i32,
|
||||
};
|
||||
var gdt = [_]GDTEntry{
|
||||
GDTEntry{ .field = 1 },
|
||||
GDTEntry{ .field = 2 },
|
||||
};
|
||||
var global_ptr = &gdt[0];
|
||||
|
||||
test "global constant is loaded with a runtime-known index" {
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var index: usize = 1;
|
||||
const ptr = &pieces[index].field;
|
||||
try expect(ptr.* == 2);
|
||||
}
|
||||
const Piece = struct {
|
||||
field: i32,
|
||||
};
|
||||
const pieces = [_]Piece{ Piece{ .field = 1 }, Piece{ .field = 2 }, Piece{ .field = 3 } };
|
||||
};
|
||||
try S.doTheTest();
|
||||
}
|
||||
@@ -70,3 +70,166 @@ test "bitcast generates a temporary value" {
|
||||
const x = @bitCast(u16, @bitCast([2]u8, y));
|
||||
try expect(y == x);
|
||||
}
|
||||
|
||||
test "@bitCast packed structs at runtime and comptime" {
|
||||
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
|
||||
const Full = packed struct {
|
||||
number: u16,
|
||||
};
|
||||
const Divided = packed struct {
|
||||
half1: u8,
|
||||
quarter3: u4,
|
||||
quarter4: u4,
|
||||
};
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var full = Full{ .number = 0x1234 };
|
||||
var two_halves = @bitCast(Divided, full);
|
||||
switch (native_endian) {
|
||||
.Big => {
|
||||
try expect(two_halves.half1 == 0x12);
|
||||
try expect(two_halves.quarter3 == 0x3);
|
||||
try expect(two_halves.quarter4 == 0x4);
|
||||
},
|
||||
.Little => {
|
||||
try expect(two_halves.half1 == 0x34);
|
||||
try expect(two_halves.quarter3 == 0x2);
|
||||
try expect(two_halves.quarter4 == 0x1);
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "@bitCast extern structs at runtime and comptime" {
|
||||
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
|
||||
const Full = extern struct {
|
||||
number: u16,
|
||||
};
|
||||
const TwoHalves = extern struct {
|
||||
half1: u8,
|
||||
half2: u8,
|
||||
};
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var full = Full{ .number = 0x1234 };
|
||||
var two_halves = @bitCast(TwoHalves, full);
|
||||
switch (native_endian) {
|
||||
.Big => {
|
||||
try expect(two_halves.half1 == 0x12);
|
||||
try expect(two_halves.half2 == 0x34);
|
||||
},
|
||||
.Little => {
|
||||
try expect(two_halves.half1 == 0x34);
|
||||
try expect(two_halves.half2 == 0x12);
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "bitcast packed struct to integer and back" {
|
||||
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
|
||||
const LevelUpMove = packed struct {
|
||||
move_id: u9,
|
||||
level: u7,
|
||||
};
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var move = LevelUpMove{ .move_id = 1, .level = 2 };
|
||||
var v = @bitCast(u16, move);
|
||||
var back_to_a_move = @bitCast(LevelUpMove, v);
|
||||
try expect(back_to_a_move.move_id == 1);
|
||||
try expect(back_to_a_move.level == 2);
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "implicit cast to error union by returning" {
|
||||
const S = struct {
|
||||
fn entry() !void {
|
||||
try expect((func(-1) catch unreachable) == maxInt(u64));
|
||||
}
|
||||
pub fn func(sz: i64) anyerror!u64 {
|
||||
return @bitCast(u64, sz);
|
||||
}
|
||||
};
|
||||
try S.entry();
|
||||
comptime try S.entry();
|
||||
}
|
||||
|
||||
test "bitcast packed struct literal to byte" {
|
||||
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
|
||||
const Foo = packed struct {
|
||||
value: u8,
|
||||
};
|
||||
const casted = @bitCast(u8, Foo{ .value = 0xF });
|
||||
try expect(casted == 0xf);
|
||||
}
|
||||
|
||||
test "comptime bitcast used in expression has the correct type" {
|
||||
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
|
||||
const Foo = packed struct {
|
||||
value: u8,
|
||||
};
|
||||
try expect(@bitCast(u8, Foo{ .value = 0xF }) == 0xf);
|
||||
}
|
||||
|
||||
test "bitcast passed as tuple element" {
|
||||
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
|
||||
const S = struct {
|
||||
fn foo(args: anytype) !void {
|
||||
comptime try expect(@TypeOf(args[0]) == f32);
|
||||
try expect(args[0] == 12.34);
|
||||
}
|
||||
};
|
||||
try S.foo(.{@bitCast(f32, @as(u32, 0x414570A4))});
|
||||
}
|
||||
|
||||
test "triple level result location with bitcast sandwich passed as tuple element" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
|
||||
const S = struct {
|
||||
fn foo(args: anytype) !void {
|
||||
comptime try expect(@TypeOf(args[0]) == f64);
|
||||
try expect(args[0] > 12.33 and args[0] < 12.35);
|
||||
}
|
||||
};
|
||||
try S.foo(.{@as(f64, @bitCast(f32, @as(u32, 0x414570A4)))});
|
||||
}
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const maxInt = std.math.maxInt;
|
||||
const native_endian = builtin.target.cpu.arch.endian();
|
||||
|
||||
test "@bitCast packed structs at runtime and comptime" {
|
||||
const Full = packed struct {
|
||||
number: u16,
|
||||
};
|
||||
const Divided = packed struct {
|
||||
half1: u8,
|
||||
quarter3: u4,
|
||||
quarter4: u4,
|
||||
};
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var full = Full{ .number = 0x1234 };
|
||||
var two_halves = @bitCast(Divided, full);
|
||||
switch (native_endian) {
|
||||
.Big => {
|
||||
try expect(two_halves.half1 == 0x12);
|
||||
try expect(two_halves.quarter3 == 0x3);
|
||||
try expect(two_halves.quarter4 == 0x4);
|
||||
},
|
||||
.Little => {
|
||||
try expect(two_halves.half1 == 0x34);
|
||||
try expect(two_halves.quarter3 == 0x2);
|
||||
try expect(two_halves.quarter4 == 0x1);
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "@bitCast extern structs at runtime and comptime" {
|
||||
const Full = extern struct {
|
||||
number: u16,
|
||||
};
|
||||
const TwoHalves = extern struct {
|
||||
half1: u8,
|
||||
half2: u8,
|
||||
};
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var full = Full{ .number = 0x1234 };
|
||||
var two_halves = @bitCast(TwoHalves, full);
|
||||
switch (native_endian) {
|
||||
.Big => {
|
||||
try expect(two_halves.half1 == 0x12);
|
||||
try expect(two_halves.half2 == 0x34);
|
||||
},
|
||||
.Little => {
|
||||
try expect(two_halves.half1 == 0x34);
|
||||
try expect(two_halves.half2 == 0x12);
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "bitcast packed struct to integer and back" {
|
||||
const LevelUpMove = packed struct {
|
||||
move_id: u9,
|
||||
level: u7,
|
||||
};
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var move = LevelUpMove{ .move_id = 1, .level = 2 };
|
||||
var v = @bitCast(u16, move);
|
||||
var back_to_a_move = @bitCast(LevelUpMove, v);
|
||||
try expect(back_to_a_move.move_id == 1);
|
||||
try expect(back_to_a_move.level == 2);
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "implicit cast to error union by returning" {
|
||||
const S = struct {
|
||||
fn entry() !void {
|
||||
try expect((func(-1) catch unreachable) == maxInt(u64));
|
||||
}
|
||||
pub fn func(sz: i64) anyerror!u64 {
|
||||
return @bitCast(u64, sz);
|
||||
}
|
||||
};
|
||||
try S.entry();
|
||||
comptime try S.entry();
|
||||
}
|
||||
|
||||
test "bitcast packed struct literal to byte" {
|
||||
const Foo = packed struct {
|
||||
value: u8,
|
||||
};
|
||||
const casted = @bitCast(u8, Foo{ .value = 0xF });
|
||||
try expect(casted == 0xf);
|
||||
}
|
||||
|
||||
test "comptime bitcast used in expression has the correct type" {
|
||||
const Foo = packed struct {
|
||||
value: u8,
|
||||
};
|
||||
try expect(@bitCast(u8, Foo{ .value = 0xF }) == 0xf);
|
||||
}
|
||||
|
||||
test "bitcast passed as tuple element" {
|
||||
const S = struct {
|
||||
fn foo(args: anytype) !void {
|
||||
comptime try expect(@TypeOf(args[0]) == f32);
|
||||
try expect(args[0] == 12.34);
|
||||
}
|
||||
};
|
||||
try S.foo(.{@bitCast(f32, @as(u32, 0x414570A4))});
|
||||
}
|
||||
|
||||
test "triple level result location with bitcast sandwich passed as tuple element" {
|
||||
const S = struct {
|
||||
fn foo(args: anytype) !void {
|
||||
comptime try expect(@TypeOf(args[0]) == f64);
|
||||
try expect(args[0] > 12.33 and args[0] < 12.35);
|
||||
}
|
||||
};
|
||||
try S.foo(.{@as(f64, @bitCast(f32, @as(u32, 0x414570A4)))});
|
||||
}
|
||||
@@ -336,3 +336,474 @@ test "expected [*c]const u8, found [*:0]const u8" {
|
||||
var c: [*:0]const u8 = b;
|
||||
try expect(std.mem.eql(u8, c[0..5], "hello"));
|
||||
}
|
||||
|
||||
test "explicit cast from integer to error type" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
try testCastIntToErr(error.ItBroke);
|
||||
comptime try testCastIntToErr(error.ItBroke);
|
||||
}
|
||||
fn testCastIntToErr(err: anyerror) !void {
|
||||
const x = @errorToInt(err);
|
||||
const y = @intToError(x);
|
||||
try expect(error.ItBroke == y);
|
||||
}
|
||||
|
||||
test "peer resolve array and const slice" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
try testPeerResolveArrayConstSlice(true);
|
||||
comptime try testPeerResolveArrayConstSlice(true);
|
||||
}
|
||||
fn testPeerResolveArrayConstSlice(b: bool) !void {
|
||||
const value1 = if (b) "aoeu" else @as([]const u8, "zz");
|
||||
const value2 = if (b) @as([]const u8, "zz") else "aoeu";
|
||||
try expect(mem.eql(u8, value1, "aoeu"));
|
||||
try expect(mem.eql(u8, value2, "zz"));
|
||||
}
|
||||
|
||||
test "implicitly cast from T to anyerror!?T" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
try castToOptionalTypeError(1);
|
||||
comptime try castToOptionalTypeError(1);
|
||||
}
|
||||
|
||||
const A = struct {
|
||||
a: i32,
|
||||
};
|
||||
fn castToOptionalTypeError(z: i32) !void {
|
||||
const x = @as(i32, 1);
|
||||
const y: anyerror!?i32 = x;
|
||||
try expect((try y).? == 1);
|
||||
|
||||
const f = z;
|
||||
const g: anyerror!?i32 = f;
|
||||
_ = g catch {};
|
||||
|
||||
const a = A{ .a = z };
|
||||
const b: anyerror!?A = a;
|
||||
try expect((b catch unreachable).?.a == 1);
|
||||
}
|
||||
|
||||
test "implicitly cast from [0]T to anyerror![]T" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
|
||||
try testCastZeroArrayToErrSliceMut();
|
||||
comptime try testCastZeroArrayToErrSliceMut();
|
||||
}
|
||||
|
||||
fn testCastZeroArrayToErrSliceMut() !void {
|
||||
try expect((gimmeErrOrSlice() catch unreachable).len == 0);
|
||||
}
|
||||
|
||||
fn gimmeErrOrSlice() anyerror![]u8 {
|
||||
return &[_]u8{};
|
||||
}
|
||||
|
||||
test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() anyerror!void {
|
||||
{
|
||||
var data = "hi".*;
|
||||
const slice = data[0..];
|
||||
try expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
|
||||
try expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
|
||||
}
|
||||
{
|
||||
var data: [2]u8 = "hi".*;
|
||||
const slice = data[0..];
|
||||
try expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
|
||||
try expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
|
||||
if (a) {
|
||||
return &[_]u8{};
|
||||
}
|
||||
|
||||
return slice[0..1];
|
||||
}
|
||||
|
||||
test "implicit cast from *const [N]T to []const T" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
try testCastConstArrayRefToConstSlice();
|
||||
comptime try testCastConstArrayRefToConstSlice();
|
||||
}
|
||||
|
||||
fn testCastConstArrayRefToConstSlice() !void {
|
||||
{
|
||||
const blah = "aoeu".*;
|
||||
const const_array_ref = &blah;
|
||||
try expect(@TypeOf(const_array_ref) == *const [4:0]u8);
|
||||
const slice: []const u8 = const_array_ref;
|
||||
try expect(mem.eql(u8, slice, "aoeu"));
|
||||
}
|
||||
{
|
||||
const blah: [4]u8 = "aoeu".*;
|
||||
const const_array_ref = &blah;
|
||||
try expect(@TypeOf(const_array_ref) == *const [4]u8);
|
||||
const slice: []const u8 = const_array_ref;
|
||||
try expect(mem.eql(u8, slice, "aoeu"));
|
||||
}
|
||||
}
|
||||
|
||||
test "peer type resolution: error and [N]T" {
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
|
||||
try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
|
||||
comptime try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
|
||||
try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
|
||||
comptime try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
|
||||
}
|
||||
|
||||
fn testPeerErrorAndArray(x: u8) anyerror![]const u8 {
|
||||
return switch (x) {
|
||||
0x00 => "OK",
|
||||
else => error.BadValue,
|
||||
};
|
||||
}
|
||||
fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
|
||||
return switch (x) {
|
||||
0x00 => "OK",
|
||||
0x01 => "OKK",
|
||||
else => error.BadValue,
|
||||
};
|
||||
}
|
||||
|
||||
test "single-item pointer of array to slice to unknown length pointer" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
try testCastPtrOfArrayToSliceAndPtr();
|
||||
comptime try testCastPtrOfArrayToSliceAndPtr();
|
||||
}
|
||||
|
||||
fn testCastPtrOfArrayToSliceAndPtr() !void {
|
||||
{
|
||||
var array = "aoeu".*;
|
||||
const x: [*]u8 = &array;
|
||||
x[0] += 1;
|
||||
try expect(mem.eql(u8, array[0..], "boeu"));
|
||||
const y: []u8 = &array;
|
||||
y[0] += 1;
|
||||
try expect(mem.eql(u8, array[0..], "coeu"));
|
||||
}
|
||||
{
|
||||
var array: [4]u8 = "aoeu".*;
|
||||
const x: [*]u8 = &array;
|
||||
x[0] += 1;
|
||||
try expect(mem.eql(u8, array[0..], "boeu"));
|
||||
const y: []u8 = &array;
|
||||
y[0] += 1;
|
||||
try expect(mem.eql(u8, array[0..], "coeu"));
|
||||
}
|
||||
}
|
||||
|
||||
test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const window_name = [1][*]const u8{"window name"};
|
||||
const x: [*]const ?[*]const u8 = &window_name;
|
||||
try expect(mem.eql(u8, std.mem.sliceTo(@ptrCast([*:0]const u8, x[0].?), 0), "window name"));
|
||||
}
|
||||
|
||||
test "vector casts" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
// Upcast (implicit, equivalent to @intCast)
|
||||
var up0: @Vector(2, u8) = [_]u8{ 0x55, 0xaa };
|
||||
var up1 = @as(@Vector(2, u16), up0);
|
||||
var up2 = @as(@Vector(2, u32), up0);
|
||||
var up3 = @as(@Vector(2, u64), up0);
|
||||
// Downcast (safety-checked)
|
||||
var down0 = up3;
|
||||
var down1 = @intCast(@Vector(2, u32), down0);
|
||||
var down2 = @intCast(@Vector(2, u16), down0);
|
||||
var down3 = @intCast(@Vector(2, u8), down0);
|
||||
|
||||
try expect(mem.eql(u16, &@as([2]u16, up1), &[2]u16{ 0x55, 0xaa }));
|
||||
try expect(mem.eql(u32, &@as([2]u32, up2), &[2]u32{ 0x55, 0xaa }));
|
||||
try expect(mem.eql(u64, &@as([2]u64, up3), &[2]u64{ 0x55, 0xaa }));
|
||||
|
||||
try expect(mem.eql(u32, &@as([2]u32, down1), &[2]u32{ 0x55, 0xaa }));
|
||||
try expect(mem.eql(u16, &@as([2]u16, down2), &[2]u16{ 0x55, 0xaa }));
|
||||
try expect(mem.eql(u8, &@as([2]u8, down3), &[2]u8{ 0x55, 0xaa }));
|
||||
}
|
||||
|
||||
fn doTheTestFloat() !void {
|
||||
var vec = @splat(2, @as(f32, 1234.0));
|
||||
var wider: @Vector(2, f64) = vec;
|
||||
try expect(wider[0] == 1234.0);
|
||||
try expect(wider[1] == 1234.0);
|
||||
}
|
||||
};
|
||||
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
try S.doTheTestFloat();
|
||||
comptime try S.doTheTestFloat();
|
||||
}
|
||||
|
||||
test "@floatCast cast down" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
{
|
||||
var double: f64 = 0.001534;
|
||||
var single = @floatCast(f32, double);
|
||||
try expect(single == 0.001534);
|
||||
}
|
||||
{
|
||||
const double: f64 = 0.001534;
|
||||
const single = @floatCast(f32, double);
|
||||
try expect(single == 0.001534);
|
||||
}
|
||||
}
|
||||
|
||||
test "peer type resolution: unreachable, error set, unreachable" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const Error = error{
|
||||
FileDescriptorAlreadyPresentInSet,
|
||||
OperationCausesCircularLoop,
|
||||
FileDescriptorNotRegistered,
|
||||
SystemResources,
|
||||
UserResourceLimitReached,
|
||||
FileDescriptorIncompatibleWithEpoll,
|
||||
Unexpected,
|
||||
};
|
||||
var err = Error.SystemResources;
|
||||
const transformed_err = switch (err) {
|
||||
error.FileDescriptorAlreadyPresentInSet => unreachable,
|
||||
error.OperationCausesCircularLoop => unreachable,
|
||||
error.FileDescriptorNotRegistered => unreachable,
|
||||
error.SystemResources => error.SystemResources,
|
||||
error.UserResourceLimitReached => error.UserResourceLimitReached,
|
||||
error.FileDescriptorIncompatibleWithEpoll => unreachable,
|
||||
error.Unexpected => unreachable,
|
||||
};
|
||||
try expect(transformed_err == error.SystemResources);
|
||||
}
|
||||
|
||||
test "peer cast *[0]T to E![]const T" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
var buffer: [5]u8 = "abcde".*;
|
||||
var buf: anyerror![]const u8 = buffer[0..];
|
||||
var b = false;
|
||||
var y = if (b) &[0]u8{} else buf;
|
||||
try expect(mem.eql(u8, "abcde", y catch unreachable));
|
||||
}
|
||||
|
||||
test "peer cast *[0]T to []const T" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
var buffer: [5]u8 = "abcde".*;
|
||||
var buf: []const u8 = buffer[0..];
|
||||
var b = false;
|
||||
var y = if (b) &[0]u8{} else buf;
|
||||
try expect(mem.eql(u8, "abcde", y));
|
||||
}
|
||||
|
||||
test "peer resolution of string literals" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
const E = enum { a, b, c, d };
|
||||
|
||||
fn doTheTest(e: E) !void {
|
||||
const cmd = switch (e) {
|
||||
.a => "one",
|
||||
.b => "two",
|
||||
.c => "three",
|
||||
.d => "four",
|
||||
};
|
||||
try expect(mem.eql(u8, cmd, "two"));
|
||||
}
|
||||
};
|
||||
try S.doTheTest(.b);
|
||||
comptime try S.doTheTest(.b);
|
||||
}
|
||||
|
||||
test "type coercion related to sentinel-termination" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
// [:x]T to []T
|
||||
{
|
||||
var array = [4:0]i32{ 1, 2, 3, 4 };
|
||||
var slice: [:0]i32 = &array;
|
||||
var dest: []i32 = slice;
|
||||
try expect(mem.eql(i32, dest, &[_]i32{ 1, 2, 3, 4 }));
|
||||
}
|
||||
|
||||
// [*:x]T to [*]T
|
||||
{
|
||||
var array = [4:99]i32{ 1, 2, 3, 4 };
|
||||
var dest: [*]i32 = &array;
|
||||
try expect(dest[0] == 1);
|
||||
try expect(dest[1] == 2);
|
||||
try expect(dest[2] == 3);
|
||||
try expect(dest[3] == 4);
|
||||
try expect(dest[4] == 99);
|
||||
}
|
||||
|
||||
// [N:x]T to [N]T
|
||||
{
|
||||
var array = [4:0]i32{ 1, 2, 3, 4 };
|
||||
var dest: [4]i32 = array;
|
||||
try expect(mem.eql(i32, &dest, &[_]i32{ 1, 2, 3, 4 }));
|
||||
}
|
||||
|
||||
// *[N:x]T to *[N]T
|
||||
{
|
||||
var array = [4:0]i32{ 1, 2, 3, 4 };
|
||||
var dest: *[4]i32 = &array;
|
||||
try expect(mem.eql(i32, dest, &[_]i32{ 1, 2, 3, 4 }));
|
||||
}
|
||||
|
||||
// [:x]T to [*:x]T
|
||||
{
|
||||
var array = [4:0]i32{ 1, 2, 3, 4 };
|
||||
var slice: [:0]i32 = &array;
|
||||
var dest: [*:0]i32 = slice;
|
||||
try expect(dest[0] == 1);
|
||||
try expect(dest[1] == 2);
|
||||
try expect(dest[2] == 3);
|
||||
try expect(dest[3] == 4);
|
||||
try expect(dest[4] == 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "peer type resolution implicit cast to return type" {
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
for ("hello") |c| _ = f(c);
|
||||
}
|
||||
fn f(c: u8) []const u8 {
|
||||
return switch (c) {
|
||||
'h', 'e' => &[_]u8{c}, // should cast to slice
|
||||
'l', ' ' => &[_]u8{ c, '.' }, // should cast to slice
|
||||
else => ([_]u8{c})[0..], // is a slice
|
||||
};
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "peer type resolution implicit cast to variable type" {
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var x: []const u8 = undefined;
|
||||
for ("hello") |c| x = switch (c) {
|
||||
'h', 'e' => &[_]u8{c}, // should cast to slice
|
||||
'l', ' ' => &[_]u8{ c, '.' }, // should cast to slice
|
||||
else => ([_]u8{c})[0..], // is a slice
|
||||
};
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "variable initialization uses result locations properly with regards to the type" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
var b = true;
|
||||
const x: i32 = if (b) 1 else 2;
|
||||
try expect(x == 1);
|
||||
}
|
||||
|
||||
test "cast between C pointer with different but compatible types" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn foo(arg: [*]c_ushort) u16 {
|
||||
return arg[0];
|
||||
}
|
||||
fn doTheTest() !void {
|
||||
var x = [_]u16{ 4, 2, 1, 3 };
|
||||
try expect(foo(@ptrCast([*]u16, &x)) == 4);
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
}
|
||||
|
||||
test "peer type resolve string lit with sentinel-terminated mutable slice" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
var array: [4:0]u8 = undefined;
|
||||
array[4] = 0; // TODO remove this when #4372 is solved
|
||||
var slice: [:0]u8 = array[0..4 :0];
|
||||
comptime try expect(@TypeOf(slice, "hi") == [:0]const u8);
|
||||
comptime try expect(@TypeOf("hi", slice) == [:0]const u8);
|
||||
}
|
||||
|
||||
test "peer type resolve array pointers, one of them const" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
var array1: [4]u8 = undefined;
|
||||
const array2: [5]u8 = undefined;
|
||||
comptime try expect(@TypeOf(&array1, &array2) == []const u8);
|
||||
comptime try expect(@TypeOf(&array2, &array1) == []const u8);
|
||||
}
|
||||
|
||||
test "peer type resolve array pointer and unknown pointer" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const const_array: [4]u8 = undefined;
|
||||
var array: [4]u8 = undefined;
|
||||
var const_ptr: [*]const u8 = undefined;
|
||||
var ptr: [*]u8 = undefined;
|
||||
|
||||
comptime try expect(@TypeOf(&array, ptr) == [*]u8);
|
||||
comptime try expect(@TypeOf(ptr, &array) == [*]u8);
|
||||
|
||||
comptime try expect(@TypeOf(&const_array, ptr) == [*]const u8);
|
||||
comptime try expect(@TypeOf(ptr, &const_array) == [*]const u8);
|
||||
|
||||
comptime try expect(@TypeOf(&array, const_ptr) == [*]const u8);
|
||||
comptime try expect(@TypeOf(const_ptr, &array) == [*]const u8);
|
||||
|
||||
comptime try expect(@TypeOf(&const_array, const_ptr) == [*]const u8);
|
||||
comptime try expect(@TypeOf(const_ptr, &const_array) == [*]const u8);
|
||||
}
|
||||
|
||||
test "comptime float casts" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const a = @intToFloat(comptime_float, 1);
|
||||
try expect(a == 1);
|
||||
try expect(@TypeOf(a) == comptime_float);
|
||||
const b = @floatToInt(comptime_int, 2);
|
||||
try expect(b == 2);
|
||||
try expect(@TypeOf(b) == comptime_int);
|
||||
|
||||
try expectFloatToInt(comptime_int, 1234, i16, 1234);
|
||||
try expectFloatToInt(comptime_float, 12.3, comptime_int, 12);
|
||||
}
|
||||
|
||||
@@ -1,426 +0,0 @@
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const mem = std.mem;
|
||||
const maxInt = std.math.maxInt;
|
||||
const Vector = std.meta.Vector;
|
||||
const native_endian = @import("builtin").target.cpu.arch.endian();
|
||||
|
||||
test "explicit cast from integer to error type" {
|
||||
try testCastIntToErr(error.ItBroke);
|
||||
comptime try testCastIntToErr(error.ItBroke);
|
||||
}
|
||||
fn testCastIntToErr(err: anyerror) !void {
|
||||
const x = @errorToInt(err);
|
||||
const y = @intToError(x);
|
||||
try expect(error.ItBroke == y);
|
||||
}
|
||||
|
||||
test "peer resolve array and const slice" {
|
||||
try testPeerResolveArrayConstSlice(true);
|
||||
comptime try testPeerResolveArrayConstSlice(true);
|
||||
}
|
||||
fn testPeerResolveArrayConstSlice(b: bool) !void {
|
||||
const value1 = if (b) "aoeu" else @as([]const u8, "zz");
|
||||
const value2 = if (b) @as([]const u8, "zz") else "aoeu";
|
||||
try expect(mem.eql(u8, value1, "aoeu"));
|
||||
try expect(mem.eql(u8, value2, "zz"));
|
||||
}
|
||||
|
||||
test "implicitly cast from T to anyerror!?T" {
|
||||
try castToOptionalTypeError(1);
|
||||
comptime try castToOptionalTypeError(1);
|
||||
}
|
||||
|
||||
const A = struct {
|
||||
a: i32,
|
||||
};
|
||||
fn castToOptionalTypeError(z: i32) !void {
|
||||
const x = @as(i32, 1);
|
||||
const y: anyerror!?i32 = x;
|
||||
try expect((try y).? == 1);
|
||||
|
||||
const f = z;
|
||||
const g: anyerror!?i32 = f;
|
||||
_ = g catch {};
|
||||
|
||||
const a = A{ .a = z };
|
||||
const b: anyerror!?A = a;
|
||||
try expect((b catch unreachable).?.a == 1);
|
||||
}
|
||||
|
||||
test "implicitly cast from [0]T to anyerror![]T" {
|
||||
try testCastZeroArrayToErrSliceMut();
|
||||
comptime try testCastZeroArrayToErrSliceMut();
|
||||
}
|
||||
|
||||
fn testCastZeroArrayToErrSliceMut() !void {
|
||||
try expect((gimmeErrOrSlice() catch unreachable).len == 0);
|
||||
}
|
||||
|
||||
fn gimmeErrOrSlice() anyerror![]u8 {
|
||||
return &[_]u8{};
|
||||
}
|
||||
|
||||
test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
|
||||
const S = struct {
|
||||
fn doTheTest() anyerror!void {
|
||||
{
|
||||
var data = "hi".*;
|
||||
const slice = data[0..];
|
||||
try expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
|
||||
try expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
|
||||
}
|
||||
{
|
||||
var data: [2]u8 = "hi".*;
|
||||
const slice = data[0..];
|
||||
try expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
|
||||
try expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
|
||||
if (a) {
|
||||
return &[_]u8{};
|
||||
}
|
||||
|
||||
return slice[0..1];
|
||||
}
|
||||
|
||||
test "implicit cast from *const [N]T to []const T" {
|
||||
try testCastConstArrayRefToConstSlice();
|
||||
comptime try testCastConstArrayRefToConstSlice();
|
||||
}
|
||||
|
||||
fn testCastConstArrayRefToConstSlice() !void {
|
||||
{
|
||||
const blah = "aoeu".*;
|
||||
const const_array_ref = &blah;
|
||||
try expect(@TypeOf(const_array_ref) == *const [4:0]u8);
|
||||
const slice: []const u8 = const_array_ref;
|
||||
try expect(mem.eql(u8, slice, "aoeu"));
|
||||
}
|
||||
{
|
||||
const blah: [4]u8 = "aoeu".*;
|
||||
const const_array_ref = &blah;
|
||||
try expect(@TypeOf(const_array_ref) == *const [4]u8);
|
||||
const slice: []const u8 = const_array_ref;
|
||||
try expect(mem.eql(u8, slice, "aoeu"));
|
||||
}
|
||||
}
|
||||
|
||||
test "peer type resolution: error and [N]T" {
|
||||
try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
|
||||
comptime try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
|
||||
try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
|
||||
comptime try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
|
||||
}
|
||||
|
||||
fn testPeerErrorAndArray(x: u8) anyerror![]const u8 {
|
||||
return switch (x) {
|
||||
0x00 => "OK",
|
||||
else => error.BadValue,
|
||||
};
|
||||
}
|
||||
fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
|
||||
return switch (x) {
|
||||
0x00 => "OK",
|
||||
0x01 => "OKK",
|
||||
else => error.BadValue,
|
||||
};
|
||||
}
|
||||
|
||||
test "single-item pointer of array to slice to unknown length pointer" {
|
||||
try testCastPtrOfArrayToSliceAndPtr();
|
||||
comptime try testCastPtrOfArrayToSliceAndPtr();
|
||||
}
|
||||
|
||||
fn testCastPtrOfArrayToSliceAndPtr() !void {
|
||||
{
|
||||
var array = "aoeu".*;
|
||||
const x: [*]u8 = &array;
|
||||
x[0] += 1;
|
||||
try expect(mem.eql(u8, array[0..], "boeu"));
|
||||
const y: []u8 = &array;
|
||||
y[0] += 1;
|
||||
try expect(mem.eql(u8, array[0..], "coeu"));
|
||||
}
|
||||
{
|
||||
var array: [4]u8 = "aoeu".*;
|
||||
const x: [*]u8 = &array;
|
||||
x[0] += 1;
|
||||
try expect(mem.eql(u8, array[0..], "boeu"));
|
||||
const y: []u8 = &array;
|
||||
y[0] += 1;
|
||||
try expect(mem.eql(u8, array[0..], "coeu"));
|
||||
}
|
||||
}
|
||||
|
||||
test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
|
||||
const window_name = [1][*]const u8{"window name"};
|
||||
const x: [*]const ?[*]const u8 = &window_name;
|
||||
try expect(mem.eql(u8, std.mem.sliceTo(@ptrCast([*:0]const u8, x[0].?), 0), "window name"));
|
||||
}
|
||||
|
||||
test "vector casts" {
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
// Upcast (implicit, equivalent to @intCast)
|
||||
var up0: Vector(2, u8) = [_]u8{ 0x55, 0xaa };
|
||||
var up1 = @as(Vector(2, u16), up0);
|
||||
var up2 = @as(Vector(2, u32), up0);
|
||||
var up3 = @as(Vector(2, u64), up0);
|
||||
// Downcast (safety-checked)
|
||||
var down0 = up3;
|
||||
var down1 = @intCast(Vector(2, u32), down0);
|
||||
var down2 = @intCast(Vector(2, u16), down0);
|
||||
var down3 = @intCast(Vector(2, u8), down0);
|
||||
|
||||
try expect(mem.eql(u16, &@as([2]u16, up1), &[2]u16{ 0x55, 0xaa }));
|
||||
try expect(mem.eql(u32, &@as([2]u32, up2), &[2]u32{ 0x55, 0xaa }));
|
||||
try expect(mem.eql(u64, &@as([2]u64, up3), &[2]u64{ 0x55, 0xaa }));
|
||||
|
||||
try expect(mem.eql(u32, &@as([2]u32, down1), &[2]u32{ 0x55, 0xaa }));
|
||||
try expect(mem.eql(u16, &@as([2]u16, down2), &[2]u16{ 0x55, 0xaa }));
|
||||
try expect(mem.eql(u8, &@as([2]u8, down3), &[2]u8{ 0x55, 0xaa }));
|
||||
}
|
||||
|
||||
fn doTheTestFloat() !void {
|
||||
var vec = @splat(2, @as(f32, 1234.0));
|
||||
var wider: Vector(2, f64) = vec;
|
||||
try expect(wider[0] == 1234.0);
|
||||
try expect(wider[1] == 1234.0);
|
||||
}
|
||||
};
|
||||
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
try S.doTheTestFloat();
|
||||
comptime try S.doTheTestFloat();
|
||||
}
|
||||
|
||||
test "@floatCast cast down" {
|
||||
{
|
||||
var double: f64 = 0.001534;
|
||||
var single = @floatCast(f32, double);
|
||||
try expect(single == 0.001534);
|
||||
}
|
||||
{
|
||||
const double: f64 = 0.001534;
|
||||
const single = @floatCast(f32, double);
|
||||
try expect(single == 0.001534);
|
||||
}
|
||||
}
|
||||
|
||||
test "peer type resolution: unreachable, error set, unreachable" {
|
||||
const Error = error{
|
||||
FileDescriptorAlreadyPresentInSet,
|
||||
OperationCausesCircularLoop,
|
||||
FileDescriptorNotRegistered,
|
||||
SystemResources,
|
||||
UserResourceLimitReached,
|
||||
FileDescriptorIncompatibleWithEpoll,
|
||||
Unexpected,
|
||||
};
|
||||
var err = Error.SystemResources;
|
||||
const transformed_err = switch (err) {
|
||||
error.FileDescriptorAlreadyPresentInSet => unreachable,
|
||||
error.OperationCausesCircularLoop => unreachable,
|
||||
error.FileDescriptorNotRegistered => unreachable,
|
||||
error.SystemResources => error.SystemResources,
|
||||
error.UserResourceLimitReached => error.UserResourceLimitReached,
|
||||
error.FileDescriptorIncompatibleWithEpoll => unreachable,
|
||||
error.Unexpected => unreachable,
|
||||
};
|
||||
try expect(transformed_err == error.SystemResources);
|
||||
}
|
||||
|
||||
test "peer cast *[0]T to E![]const T" {
|
||||
var buffer: [5]u8 = "abcde".*;
|
||||
var buf: anyerror![]const u8 = buffer[0..];
|
||||
var b = false;
|
||||
var y = if (b) &[0]u8{} else buf;
|
||||
try expect(mem.eql(u8, "abcde", y catch unreachable));
|
||||
}
|
||||
|
||||
test "peer cast *[0]T to []const T" {
|
||||
var buffer: [5]u8 = "abcde".*;
|
||||
var buf: []const u8 = buffer[0..];
|
||||
var b = false;
|
||||
var y = if (b) &[0]u8{} else buf;
|
||||
try expect(mem.eql(u8, "abcde", y));
|
||||
}
|
||||
|
||||
test "peer resolution of string literals" {
|
||||
const S = struct {
|
||||
const E = enum { a, b, c, d };
|
||||
|
||||
fn doTheTest(e: E) !void {
|
||||
const cmd = switch (e) {
|
||||
.a => "one",
|
||||
.b => "two",
|
||||
.c => "three",
|
||||
.d => "four",
|
||||
};
|
||||
try expect(mem.eql(u8, cmd, "two"));
|
||||
}
|
||||
};
|
||||
try S.doTheTest(.b);
|
||||
comptime try S.doTheTest(.b);
|
||||
}
|
||||
|
||||
test "type coercion related to sentinel-termination" {
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
// [:x]T to []T
|
||||
{
|
||||
var array = [4:0]i32{ 1, 2, 3, 4 };
|
||||
var slice: [:0]i32 = &array;
|
||||
var dest: []i32 = slice;
|
||||
try expect(mem.eql(i32, dest, &[_]i32{ 1, 2, 3, 4 }));
|
||||
}
|
||||
|
||||
// [*:x]T to [*]T
|
||||
{
|
||||
var array = [4:99]i32{ 1, 2, 3, 4 };
|
||||
var dest: [*]i32 = &array;
|
||||
try expect(dest[0] == 1);
|
||||
try expect(dest[1] == 2);
|
||||
try expect(dest[2] == 3);
|
||||
try expect(dest[3] == 4);
|
||||
try expect(dest[4] == 99);
|
||||
}
|
||||
|
||||
// [N:x]T to [N]T
|
||||
{
|
||||
var array = [4:0]i32{ 1, 2, 3, 4 };
|
||||
var dest: [4]i32 = array;
|
||||
try expect(mem.eql(i32, &dest, &[_]i32{ 1, 2, 3, 4 }));
|
||||
}
|
||||
|
||||
// *[N:x]T to *[N]T
|
||||
{
|
||||
var array = [4:0]i32{ 1, 2, 3, 4 };
|
||||
var dest: *[4]i32 = &array;
|
||||
try expect(mem.eql(i32, dest, &[_]i32{ 1, 2, 3, 4 }));
|
||||
}
|
||||
|
||||
// [:x]T to [*:x]T
|
||||
{
|
||||
var array = [4:0]i32{ 1, 2, 3, 4 };
|
||||
var slice: [:0]i32 = &array;
|
||||
var dest: [*:0]i32 = slice;
|
||||
try expect(dest[0] == 1);
|
||||
try expect(dest[1] == 2);
|
||||
try expect(dest[2] == 3);
|
||||
try expect(dest[3] == 4);
|
||||
try expect(dest[4] == 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "peer type resolution implicit cast to return type" {
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
for ("hello") |c| _ = f(c);
|
||||
}
|
||||
fn f(c: u8) []const u8 {
|
||||
return switch (c) {
|
||||
'h', 'e' => &[_]u8{c}, // should cast to slice
|
||||
'l', ' ' => &[_]u8{ c, '.' }, // should cast to slice
|
||||
else => ([_]u8{c})[0..], // is a slice
|
||||
};
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "peer type resolution implicit cast to variable type" {
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var x: []const u8 = undefined;
|
||||
for ("hello") |c| x = switch (c) {
|
||||
'h', 'e' => &[_]u8{c}, // should cast to slice
|
||||
'l', ' ' => &[_]u8{ c, '.' }, // should cast to slice
|
||||
else => ([_]u8{c})[0..], // is a slice
|
||||
};
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "variable initialization uses result locations properly with regards to the type" {
|
||||
var b = true;
|
||||
const x: i32 = if (b) 1 else 2;
|
||||
try expect(x == 1);
|
||||
}
|
||||
|
||||
test "cast between C pointer with different but compatible types" {
|
||||
const S = struct {
|
||||
fn foo(arg: [*]c_ushort) u16 {
|
||||
return arg[0];
|
||||
}
|
||||
fn doTheTest() !void {
|
||||
var x = [_]u16{ 4, 2, 1, 3 };
|
||||
try expect(foo(@ptrCast([*]u16, &x)) == 4);
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
}
|
||||
|
||||
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
|
||||
var slice: [:0]u8 = array[0..4 :0];
|
||||
comptime try expect(@TypeOf(slice, "hi") == [:0]const u8);
|
||||
comptime try expect(@TypeOf("hi", slice) == [:0]const u8);
|
||||
}
|
||||
|
||||
test "peer type resolve array pointers, one of them const" {
|
||||
var array1: [4]u8 = undefined;
|
||||
const array2: [5]u8 = undefined;
|
||||
comptime try expect(@TypeOf(&array1, &array2) == []const u8);
|
||||
comptime try expect(@TypeOf(&array2, &array1) == []const u8);
|
||||
}
|
||||
|
||||
test "peer type resolve array pointer and unknown pointer" {
|
||||
const const_array: [4]u8 = undefined;
|
||||
var array: [4]u8 = undefined;
|
||||
var const_ptr: [*]const u8 = undefined;
|
||||
var ptr: [*]u8 = undefined;
|
||||
|
||||
comptime try expect(@TypeOf(&array, ptr) == [*]u8);
|
||||
comptime try expect(@TypeOf(ptr, &array) == [*]u8);
|
||||
|
||||
comptime try expect(@TypeOf(&const_array, ptr) == [*]const u8);
|
||||
comptime try expect(@TypeOf(ptr, &const_array) == [*]const u8);
|
||||
|
||||
comptime try expect(@TypeOf(&array, const_ptr) == [*]const u8);
|
||||
comptime try expect(@TypeOf(const_ptr, &array) == [*]const u8);
|
||||
|
||||
comptime try expect(@TypeOf(&const_array, const_ptr) == [*]const u8);
|
||||
comptime try expect(@TypeOf(const_ptr, &const_array) == [*]const u8);
|
||||
}
|
||||
|
||||
test "comptime float casts" {
|
||||
const a = @intToFloat(comptime_float, 1);
|
||||
try expect(a == 1);
|
||||
try expect(@TypeOf(a) == comptime_float);
|
||||
const b = @floatToInt(comptime_int, 2);
|
||||
try expect(b == 2);
|
||||
try expect(@TypeOf(b) == comptime_int);
|
||||
|
||||
try expectFloatToInt(comptime_int, 1234, i16, 1234);
|
||||
try expectFloatToInt(comptime_float, 12.3, comptime_int, 12);
|
||||
}
|
||||
|
||||
fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void {
|
||||
try expect(@floatToInt(I, f) == i);
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
@@ -61,3 +62,58 @@ test "return variable while defer expression in scope to modify it" {
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
var result: [3]u8 = undefined;
|
||||
var index: usize = undefined;
|
||||
|
||||
fn runSomeErrorDefers(x: bool) !bool {
|
||||
index = 0;
|
||||
defer {
|
||||
result[index] = 'a';
|
||||
index += 1;
|
||||
}
|
||||
errdefer {
|
||||
result[index] = 'b';
|
||||
index += 1;
|
||||
}
|
||||
defer {
|
||||
result[index] = 'c';
|
||||
index += 1;
|
||||
}
|
||||
return if (x) x else error.FalseNotAllowed;
|
||||
}
|
||||
|
||||
test "mixing normal and error defers" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
try expect(runSomeErrorDefers(true) catch unreachable);
|
||||
try expect(result[0] == 'c');
|
||||
try expect(result[1] == 'a');
|
||||
|
||||
const ok = runSomeErrorDefers(false) catch |err| x: {
|
||||
try expect(err == error.FalseNotAllowed);
|
||||
break :x true;
|
||||
};
|
||||
try expect(ok);
|
||||
try expect(result[0] == 'c');
|
||||
try expect(result[1] == 'b');
|
||||
try expect(result[2] == 'a');
|
||||
}
|
||||
|
||||
test "errdefer with payload" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn foo() !i32 {
|
||||
errdefer |a| {
|
||||
expectEqual(error.One, a) catch @panic("test failure");
|
||||
}
|
||||
return error.One;
|
||||
}
|
||||
fn doTheTest() !void {
|
||||
try expectError(error.One, foo());
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const expectError = std.testing.expectError;
|
||||
|
||||
var result: [3]u8 = undefined;
|
||||
var index: usize = undefined;
|
||||
|
||||
fn runSomeErrorDefers(x: bool) !bool {
|
||||
index = 0;
|
||||
defer {
|
||||
result[index] = 'a';
|
||||
index += 1;
|
||||
}
|
||||
errdefer {
|
||||
result[index] = 'b';
|
||||
index += 1;
|
||||
}
|
||||
defer {
|
||||
result[index] = 'c';
|
||||
index += 1;
|
||||
}
|
||||
return if (x) x else error.FalseNotAllowed;
|
||||
}
|
||||
|
||||
test "mixing normal and error defers" {
|
||||
try expect(runSomeErrorDefers(true) catch unreachable);
|
||||
try expect(result[0] == 'c');
|
||||
try expect(result[1] == 'a');
|
||||
|
||||
const ok = runSomeErrorDefers(false) catch |err| x: {
|
||||
try expect(err == error.FalseNotAllowed);
|
||||
break :x true;
|
||||
};
|
||||
try expect(ok);
|
||||
try expect(result[0] == 'c');
|
||||
try expect(result[1] == 'b');
|
||||
try expect(result[2] == 'a');
|
||||
}
|
||||
|
||||
test "errdefer with payload" {
|
||||
const S = struct {
|
||||
fn foo() !i32 {
|
||||
errdefer |a| {
|
||||
expectEqual(error.One, a) catch @panic("test failure");
|
||||
}
|
||||
return error.One;
|
||||
}
|
||||
fn doTheTest() !void {
|
||||
try expectError(error.One, foo());
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const mem = std.mem;
|
||||
@@ -870,3 +871,104 @@ test "method call on an enum" {
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "enum value allocation" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const LargeEnum = enum(u32) {
|
||||
A0 = 0x80000000,
|
||||
A1,
|
||||
A2,
|
||||
};
|
||||
|
||||
try expect(@enumToInt(LargeEnum.A0) == 0x80000000);
|
||||
try expect(@enumToInt(LargeEnum.A1) == 0x80000001);
|
||||
try expect(@enumToInt(LargeEnum.A2) == 0x80000002);
|
||||
}
|
||||
|
||||
test "enum literal casting to tagged union" {
|
||||
const Arch = union(enum) {
|
||||
x86_64,
|
||||
arm: Arm32,
|
||||
|
||||
const Arm32 = enum {
|
||||
v8_5a,
|
||||
v8_4a,
|
||||
};
|
||||
};
|
||||
|
||||
var t = true;
|
||||
var x: Arch = .x86_64;
|
||||
var y = if (t) x else .x86_64;
|
||||
switch (y) {
|
||||
.x86_64 => {},
|
||||
else => @panic("fail"),
|
||||
}
|
||||
}
|
||||
|
||||
const Bar = enum { A, B, C, D };
|
||||
|
||||
test "enum literal casting to error union with payload enum" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
var bar: error{B}!Bar = undefined;
|
||||
bar = .B; // should never cast to the error set
|
||||
|
||||
try expect((try bar) == Bar.B);
|
||||
}
|
||||
|
||||
test "exporting enum type and value" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
const E = enum(c_int) { one, two };
|
||||
comptime {
|
||||
@export(E, .{ .name = "E" });
|
||||
}
|
||||
const e: E = .two;
|
||||
comptime {
|
||||
@export(e, .{ .name = "e" });
|
||||
}
|
||||
};
|
||||
try expect(S.e == .two);
|
||||
}
|
||||
|
||||
test "constant enum initialization with differing sizes" {
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const mem = std.mem;
|
||||
const Tag = std.meta.Tag;
|
||||
|
||||
test "enum value allocation" {
|
||||
const LargeEnum = enum(u32) {
|
||||
A0 = 0x80000000,
|
||||
A1,
|
||||
A2,
|
||||
};
|
||||
|
||||
try expect(@enumToInt(LargeEnum.A0) == 0x80000000);
|
||||
try expect(@enumToInt(LargeEnum.A1) == 0x80000001);
|
||||
try expect(@enumToInt(LargeEnum.A2) == 0x80000002);
|
||||
}
|
||||
|
||||
test "enum literal casting to tagged union" {
|
||||
const Arch = union(enum) {
|
||||
x86_64,
|
||||
arm: Arm32,
|
||||
|
||||
const Arm32 = enum {
|
||||
v8_5a,
|
||||
v8_4a,
|
||||
};
|
||||
};
|
||||
|
||||
var t = true;
|
||||
var x: Arch = .x86_64;
|
||||
var y = if (t) x else .x86_64;
|
||||
switch (y) {
|
||||
.x86_64 => {},
|
||||
else => @panic("fail"),
|
||||
}
|
||||
}
|
||||
|
||||
const Bar = enum { A, B, C, D };
|
||||
|
||||
test "enum literal casting to error union with payload enum" {
|
||||
var bar: error{B}!Bar = undefined;
|
||||
bar = .B; // should never cast to the error set
|
||||
|
||||
try expect((try bar) == Bar.B);
|
||||
}
|
||||
|
||||
test "exporting enum type and value" {
|
||||
const S = struct {
|
||||
const E = enum(c_int) { one, two };
|
||||
comptime {
|
||||
@export(E, .{ .name = "E" });
|
||||
}
|
||||
const e: E = .two;
|
||||
comptime {
|
||||
@export(e, .{ .name = "e" });
|
||||
}
|
||||
};
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
@@ -492,3 +493,308 @@ test "@tagName of @typeInfo" {
|
||||
const str = @tagName(@typeInfo(u8));
|
||||
try expect(std.mem.eql(u8, str, "Int"));
|
||||
}
|
||||
|
||||
test "static eval list init" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
try expect(static_vec3.data[2] == 1.0);
|
||||
try expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
|
||||
}
|
||||
const static_vec3 = vec3(0.0, 0.0, 1.0);
|
||||
pub const Vec3 = struct {
|
||||
data: [3]f32,
|
||||
};
|
||||
pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
|
||||
return Vec3{
|
||||
.data = [_]f32{ x, y, z },
|
||||
};
|
||||
}
|
||||
|
||||
test "inlined loop has array literal with elided runtime scope on first iteration but not second iteration" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
var runtime = [1]i32{3};
|
||||
comptime var i: usize = 0;
|
||||
inline while (i < 2) : (i += 1) {
|
||||
const result = if (i == 0) [1]i32{2} else runtime;
|
||||
_ = result;
|
||||
}
|
||||
comptime {
|
||||
try expect(i == 2);
|
||||
}
|
||||
}
|
||||
|
||||
test "eval @setFloatMode at compile-time" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const result = comptime fnWithFloatMode();
|
||||
try expect(result == 1234.0);
|
||||
}
|
||||
|
||||
fn fnWithFloatMode() f32 {
|
||||
@setFloatMode(std.builtin.FloatMode.Strict);
|
||||
return 1234.0;
|
||||
}
|
||||
|
||||
test "call method on bound fn referring to var instance" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
try expect(bound_fn() == 1237);
|
||||
}
|
||||
|
||||
const SimpleStruct = struct {
|
||||
field: i32,
|
||||
|
||||
fn method(self: *const SimpleStruct) i32 {
|
||||
return self.field + 3;
|
||||
}
|
||||
};
|
||||
|
||||
var simple_struct = SimpleStruct{ .field = 1234 };
|
||||
|
||||
const bound_fn = simple_struct.method;
|
||||
|
||||
test "ptr to local array argument at comptime" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
comptime {
|
||||
var bytes: [10]u8 = undefined;
|
||||
modifySomeBytes(bytes[0..]);
|
||||
try expect(bytes[0] == 'a');
|
||||
try expect(bytes[9] == 'b');
|
||||
}
|
||||
}
|
||||
|
||||
fn modifySomeBytes(bytes: []u8) void {
|
||||
bytes[0] = 'a';
|
||||
bytes[9] = 'b';
|
||||
}
|
||||
|
||||
test "comparisons 0 <= uint and 0 > uint should be comptime" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
testCompTimeUIntComparisons(1234);
|
||||
}
|
||||
fn testCompTimeUIntComparisons(x: u32) void {
|
||||
if (!(0 <= x)) {
|
||||
@compileError("this condition should be comptime known");
|
||||
}
|
||||
if (0 > x) {
|
||||
@compileError("this condition should be comptime known");
|
||||
}
|
||||
if (!(x >= 0)) {
|
||||
@compileError("this condition should be comptime known");
|
||||
}
|
||||
if (x < 0) {
|
||||
@compileError("this condition should be comptime known");
|
||||
}
|
||||
}
|
||||
|
||||
const hi1 = "hi";
|
||||
const hi2 = hi1;
|
||||
test "const global shares pointer with other same one" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
try assertEqualPtrs(&hi1[0], &hi2[0]);
|
||||
comptime try expect(&hi1[0] == &hi2[0]);
|
||||
}
|
||||
fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) !void {
|
||||
try expect(ptr1 == ptr2);
|
||||
}
|
||||
|
||||
test "float literal at compile time not lossy" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
try expect(16777216.0 + 1.0 == 16777217.0);
|
||||
try expect(9007199254740992.0 + 1.0 == 9007199254740993.0);
|
||||
}
|
||||
|
||||
test "f128 at compile time is lossy" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
|
||||
}
|
||||
|
||||
test "string literal used as comptime slice is memoized" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const a = "link";
|
||||
const b = "link";
|
||||
comptime try expect(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
|
||||
comptime try expect(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
|
||||
}
|
||||
|
||||
pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
|
||||
_ = field_name;
|
||||
return struct {
|
||||
pub const Node = struct {};
|
||||
};
|
||||
}
|
||||
|
||||
test "comptime function with mutable pointer is not memoized" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
comptime {
|
||||
var x: i32 = 1;
|
||||
const ptr = &x;
|
||||
increment(ptr);
|
||||
increment(ptr);
|
||||
try expect(x == 3);
|
||||
}
|
||||
}
|
||||
|
||||
fn increment(value: *i32) void {
|
||||
value.* += 1;
|
||||
}
|
||||
|
||||
test "const ptr to comptime mutable data is not memoized" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
comptime {
|
||||
var foo = SingleFieldStruct{ .x = 1 };
|
||||
try expect(foo.read_x() == 1);
|
||||
foo.x = 2;
|
||||
try expect(foo.read_x() == 2);
|
||||
}
|
||||
}
|
||||
|
||||
const SingleFieldStruct = struct {
|
||||
x: i32,
|
||||
|
||||
fn read_x(self: *const SingleFieldStruct) i32 {
|
||||
return self.x;
|
||||
}
|
||||
};
|
||||
|
||||
test "function which returns struct with type field causes implicit comptime" {
|
||||
const ty = wrap(i32).T;
|
||||
try expect(ty == i32);
|
||||
}
|
||||
|
||||
const Wrapper = struct {
|
||||
T: type,
|
||||
};
|
||||
|
||||
fn wrap(comptime T: type) Wrapper {
|
||||
return Wrapper{ .T = T };
|
||||
}
|
||||
|
||||
test "call method with comptime pass-by-non-copying-value self parameter" {
|
||||
const S = struct {
|
||||
a: u8,
|
||||
|
||||
fn b(comptime s: @This()) u8 {
|
||||
return s.a;
|
||||
}
|
||||
};
|
||||
|
||||
const s = S{ .a = 2 };
|
||||
var b = s.b();
|
||||
try expect(b == 2);
|
||||
}
|
||||
|
||||
test "setting backward branch quota just before a generic fn call" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
@setEvalBranchQuota(1001);
|
||||
loopNTimes(1001);
|
||||
}
|
||||
|
||||
fn loopNTimes(comptime n: usize) void {
|
||||
comptime var i = 0;
|
||||
inline while (i < n) : (i += 1) {}
|
||||
}
|
||||
|
||||
test "variable inside inline loop that has different types on different iterations" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
try testVarInsideInlineLoop(.{ true, @as(u32, 42) });
|
||||
}
|
||||
|
||||
fn testVarInsideInlineLoop(args: anytype) !void {
|
||||
comptime var i = 0;
|
||||
inline while (i < args.len) : (i += 1) {
|
||||
const x = args[i];
|
||||
if (i == 0) try expect(x);
|
||||
if (i == 1) try expect(x == 42);
|
||||
}
|
||||
}
|
||||
|
||||
test "bit shift a u1" {
|
||||
// note: when debugging this test case for stage2, be sure to run it
|
||||
// in valgrind. I noticed the rhs value is undefined in the lowering
|
||||
// of the const value.
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
var x: u1 = 1;
|
||||
var y = x << 0;
|
||||
try expect(y == 1);
|
||||
}
|
||||
|
||||
test "*align(1) u16 is the same as *align(1:0:2) u16" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
comptime {
|
||||
try expect(*align(1:0:2) u16 == *align(1) u16);
|
||||
try expect(*align(2:0:2) u16 == *u16);
|
||||
}
|
||||
}
|
||||
|
||||
test "array concatenation forces comptime" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
var a = oneItem(3) ++ oneItem(4);
|
||||
try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 4 }));
|
||||
}
|
||||
|
||||
test "array multiplication forces comptime" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
var a = oneItem(3) ** scalar(2);
|
||||
try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 3 }));
|
||||
}
|
||||
|
||||
fn oneItem(x: i32) [1]i32 {
|
||||
return [_]i32{x};
|
||||
}
|
||||
|
||||
fn scalar(x: u32) u32 {
|
||||
return x;
|
||||
}
|
||||
|
||||
test "comptime assign int to optional int" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
comptime {
|
||||
var x: ?i32 = null;
|
||||
x = 2;
|
||||
x.? *= 10;
|
||||
try expectEqual(20, x.?);
|
||||
}
|
||||
}
|
||||
|
||||
test "two comptime calls with array default initialized to undefined" {
|
||||
const S = struct {
|
||||
const CrossTarget = struct {
|
||||
dynamic_linker: DynamicLinker = DynamicLinker{},
|
||||
|
||||
pub fn parse() void {
|
||||
var result: CrossTarget = .{};
|
||||
result.getCpuArch();
|
||||
}
|
||||
|
||||
pub fn getCpuArch(self: CrossTarget) void {
|
||||
_ = self;
|
||||
}
|
||||
};
|
||||
|
||||
const DynamicLinker = struct {
|
||||
buffer: [255]u8 = undefined,
|
||||
};
|
||||
};
|
||||
|
||||
comptime {
|
||||
S.CrossTarget.parse();
|
||||
S.CrossTarget.parse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,266 +0,0 @@
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
|
||||
test "static eval list init" {
|
||||
try expect(static_vec3.data[2] == 1.0);
|
||||
try expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
|
||||
}
|
||||
const static_vec3 = vec3(0.0, 0.0, 1.0);
|
||||
pub const Vec3 = struct {
|
||||
data: [3]f32,
|
||||
};
|
||||
pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
|
||||
return Vec3{
|
||||
.data = [_]f32{ x, y, z },
|
||||
};
|
||||
}
|
||||
|
||||
test "inlined loop has array literal with elided runtime scope on first iteration but not second iteration" {
|
||||
var runtime = [1]i32{3};
|
||||
comptime var i: usize = 0;
|
||||
inline while (i < 2) : (i += 1) {
|
||||
const result = if (i == 0) [1]i32{2} else runtime;
|
||||
_ = result;
|
||||
}
|
||||
comptime {
|
||||
try expect(i == 2);
|
||||
}
|
||||
}
|
||||
|
||||
test "eval @setFloatMode at compile-time" {
|
||||
const result = comptime fnWithFloatMode();
|
||||
try expect(result == 1234.0);
|
||||
}
|
||||
|
||||
fn fnWithFloatMode() f32 {
|
||||
@setFloatMode(std.builtin.FloatMode.Strict);
|
||||
return 1234.0;
|
||||
}
|
||||
|
||||
const SimpleStruct = struct {
|
||||
field: i32,
|
||||
|
||||
fn method(self: *const SimpleStruct) i32 {
|
||||
return self.field + 3;
|
||||
}
|
||||
};
|
||||
|
||||
var simple_struct = SimpleStruct{ .field = 1234 };
|
||||
|
||||
const bound_fn = simple_struct.method;
|
||||
|
||||
test "call method on bound fn referring to var instance" {
|
||||
try expect(bound_fn() == 1237);
|
||||
}
|
||||
|
||||
test "ptr to local array argument at comptime" {
|
||||
comptime {
|
||||
var bytes: [10]u8 = undefined;
|
||||
modifySomeBytes(bytes[0..]);
|
||||
try expect(bytes[0] == 'a');
|
||||
try expect(bytes[9] == 'b');
|
||||
}
|
||||
}
|
||||
|
||||
fn modifySomeBytes(bytes: []u8) void {
|
||||
bytes[0] = 'a';
|
||||
bytes[9] = 'b';
|
||||
}
|
||||
|
||||
test "comparisons 0 <= uint and 0 > uint should be comptime" {
|
||||
testCompTimeUIntComparisons(1234);
|
||||
}
|
||||
fn testCompTimeUIntComparisons(x: u32) void {
|
||||
if (!(0 <= x)) {
|
||||
@compileError("this condition should be comptime known");
|
||||
}
|
||||
if (0 > x) {
|
||||
@compileError("this condition should be comptime known");
|
||||
}
|
||||
if (!(x >= 0)) {
|
||||
@compileError("this condition should be comptime known");
|
||||
}
|
||||
if (x < 0) {
|
||||
@compileError("this condition should be comptime known");
|
||||
}
|
||||
}
|
||||
|
||||
const hi1 = "hi";
|
||||
const hi2 = hi1;
|
||||
test "const global shares pointer with other same one" {
|
||||
try assertEqualPtrs(&hi1[0], &hi2[0]);
|
||||
comptime try expect(&hi1[0] == &hi2[0]);
|
||||
}
|
||||
fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) !void {
|
||||
try expect(ptr1 == ptr2);
|
||||
}
|
||||
|
||||
test "float literal at compile time not lossy" {
|
||||
try expect(16777216.0 + 1.0 == 16777217.0);
|
||||
try expect(9007199254740992.0 + 1.0 == 9007199254740993.0);
|
||||
}
|
||||
|
||||
test "f128 at compile time is lossy" {
|
||||
try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
|
||||
}
|
||||
|
||||
pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
|
||||
_ = field_name;
|
||||
return struct {
|
||||
pub const Node = struct {};
|
||||
};
|
||||
}
|
||||
|
||||
test "string literal used as comptime slice is memoized" {
|
||||
const a = "link";
|
||||
const b = "link";
|
||||
comptime try expect(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
|
||||
comptime try expect(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
|
||||
}
|
||||
|
||||
test "comptime function with mutable pointer is not memoized" {
|
||||
comptime {
|
||||
var x: i32 = 1;
|
||||
const ptr = &x;
|
||||
increment(ptr);
|
||||
increment(ptr);
|
||||
try expect(x == 3);
|
||||
}
|
||||
}
|
||||
|
||||
fn increment(value: *i32) void {
|
||||
value.* += 1;
|
||||
}
|
||||
|
||||
const SingleFieldStruct = struct {
|
||||
x: i32,
|
||||
|
||||
fn read_x(self: *const SingleFieldStruct) i32 {
|
||||
return self.x;
|
||||
}
|
||||
};
|
||||
test "const ptr to comptime mutable data is not memoized" {
|
||||
comptime {
|
||||
var foo = SingleFieldStruct{ .x = 1 };
|
||||
try expect(foo.read_x() == 1);
|
||||
foo.x = 2;
|
||||
try expect(foo.read_x() == 2);
|
||||
}
|
||||
}
|
||||
|
||||
const Wrapper = struct {
|
||||
T: type,
|
||||
};
|
||||
|
||||
fn wrap(comptime T: type) Wrapper {
|
||||
return Wrapper{ .T = T };
|
||||
}
|
||||
|
||||
test "function which returns struct with type field causes implicit comptime" {
|
||||
const ty = wrap(i32).T;
|
||||
try expect(ty == i32);
|
||||
}
|
||||
|
||||
test "call method with comptime pass-by-non-copying-value self parameter" {
|
||||
const S = struct {
|
||||
a: u8,
|
||||
|
||||
fn b(comptime s: @This()) u8 {
|
||||
return s.a;
|
||||
}
|
||||
};
|
||||
|
||||
const s = S{ .a = 2 };
|
||||
var b = s.b();
|
||||
try expect(b == 2);
|
||||
}
|
||||
|
||||
test "setting backward branch quota just before a generic fn call" {
|
||||
@setEvalBranchQuota(1001);
|
||||
loopNTimes(1001);
|
||||
}
|
||||
|
||||
fn loopNTimes(comptime n: usize) void {
|
||||
comptime var i = 0;
|
||||
inline while (i < n) : (i += 1) {}
|
||||
}
|
||||
|
||||
test "variable inside inline loop that has different types on different iterations" {
|
||||
try testVarInsideInlineLoop(.{ true, @as(u32, 42) });
|
||||
}
|
||||
|
||||
fn testVarInsideInlineLoop(args: anytype) !void {
|
||||
comptime var i = 0;
|
||||
inline while (i < args.len) : (i += 1) {
|
||||
const x = args[i];
|
||||
if (i == 0) try expect(x);
|
||||
if (i == 1) try expect(x == 42);
|
||||
}
|
||||
}
|
||||
|
||||
test "bit shift a u1" {
|
||||
var x: u1 = 1;
|
||||
var y = x << 0;
|
||||
try expect(y == 1);
|
||||
}
|
||||
|
||||
test "*align(1) u16 is the same as *align(1:0:2) u16" {
|
||||
comptime {
|
||||
try expect(*align(1:0:2) u16 == *align(1) u16);
|
||||
try expect(*align(2:0:2) u16 == *u16);
|
||||
}
|
||||
}
|
||||
|
||||
test "array concatenation forces comptime" {
|
||||
var a = oneItem(3) ++ oneItem(4);
|
||||
try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 4 }));
|
||||
}
|
||||
|
||||
test "array multiplication forces comptime" {
|
||||
var a = oneItem(3) ** scalar(2);
|
||||
try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 3 }));
|
||||
}
|
||||
|
||||
fn oneItem(x: i32) [1]i32 {
|
||||
return [_]i32{x};
|
||||
}
|
||||
|
||||
fn scalar(x: u32) u32 {
|
||||
return x;
|
||||
}
|
||||
|
||||
test "comptime assign int to optional int" {
|
||||
comptime {
|
||||
var x: ?i32 = null;
|
||||
x = 2;
|
||||
x.? *= 10;
|
||||
try expectEqual(20, x.?);
|
||||
}
|
||||
}
|
||||
|
||||
test "two comptime calls with array default initialized to undefined" {
|
||||
const S = struct {
|
||||
const CrossTarget = struct {
|
||||
dynamic_linker: DynamicLinker = DynamicLinker{},
|
||||
|
||||
pub fn parse() void {
|
||||
var result: CrossTarget = .{};
|
||||
result.getCpuArch();
|
||||
}
|
||||
|
||||
pub fn getCpuArch(self: CrossTarget) void {
|
||||
_ = self;
|
||||
}
|
||||
};
|
||||
|
||||
const DynamicLinker = struct {
|
||||
buffer: [255]u8 = undefined,
|
||||
};
|
||||
};
|
||||
|
||||
comptime {
|
||||
S.CrossTarget.parse();
|
||||
S.CrossTarget.parse();
|
||||
}
|
||||
}
|
||||
@@ -250,3 +250,101 @@ test "implicit cast fn call result to optional in field result" {
|
||||
try S.entry();
|
||||
comptime try S.entry();
|
||||
}
|
||||
|
||||
test "void parameters" {
|
||||
try voidFun(1, void{}, 2, {});
|
||||
}
|
||||
fn voidFun(a: i32, b: void, c: i32, d: void) !void {
|
||||
_ = d;
|
||||
const v = b;
|
||||
const vv: void = if (a == 1) v else {};
|
||||
try expect(a + c == 3);
|
||||
return vv;
|
||||
}
|
||||
|
||||
test "call function with empty string" {
|
||||
acceptsString("");
|
||||
}
|
||||
|
||||
fn acceptsString(foo: []u8) void {
|
||||
_ = foo;
|
||||
}
|
||||
|
||||
test "function pointers" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const fns = [_]@TypeOf(fn1){
|
||||
fn1,
|
||||
fn2,
|
||||
fn3,
|
||||
fn4,
|
||||
};
|
||||
for (fns) |f, i| {
|
||||
try expect(f() == @intCast(u32, i) + 5);
|
||||
}
|
||||
}
|
||||
fn fn1() u32 {
|
||||
return 5;
|
||||
}
|
||||
fn fn2() u32 {
|
||||
return 6;
|
||||
}
|
||||
fn fn3() u32 {
|
||||
return 7;
|
||||
}
|
||||
fn fn4() u32 {
|
||||
return 8;
|
||||
}
|
||||
|
||||
test "number literal as an argument" {
|
||||
try numberLiteralArg(3);
|
||||
comptime try numberLiteralArg(3);
|
||||
}
|
||||
|
||||
fn numberLiteralArg(a: anytype) !void {
|
||||
try expect(a == 3);
|
||||
}
|
||||
|
||||
test "function call with anon list literal" {
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
try consumeVec(.{ 9, 8, 7 });
|
||||
}
|
||||
|
||||
fn consumeVec(vec: [3]f32) !void {
|
||||
try expect(vec[0] == 9);
|
||||
try expect(vec[1] == 8);
|
||||
try expect(vec[2] == 7);
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "ability to give comptime types and non comptime types to same parameter" {
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var x: i32 = 1;
|
||||
try expect(foo(x) == 10);
|
||||
try expect(foo(i32) == 20);
|
||||
}
|
||||
|
||||
fn foo(arg: anytype) i32 {
|
||||
if (@typeInfo(@TypeOf(arg)) == .Type and arg == i32) return 20;
|
||||
return 9 + arg;
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "function with inferred error set but returning no error" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn foo() !void {}
|
||||
};
|
||||
|
||||
const return_ty = @typeInfo(@TypeOf(S.foo)).Fn.return_type.?;
|
||||
try expectEqual(0, @typeInfo(@typeInfo(return_ty).ErrorUnion.error_set).ErrorSet.?.len);
|
||||
}
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const testing = std.testing;
|
||||
const expect = testing.expect;
|
||||
const expectEqual = testing.expectEqual;
|
||||
|
||||
test "void parameters" {
|
||||
try voidFun(1, void{}, 2, {});
|
||||
}
|
||||
fn voidFun(a: i32, b: void, c: i32, d: void) !void {
|
||||
_ = d;
|
||||
const v = b;
|
||||
const vv: void = if (a == 1) v else {};
|
||||
try expect(a + c == 3);
|
||||
return vv;
|
||||
}
|
||||
|
||||
test "call function with empty string" {
|
||||
acceptsString("");
|
||||
}
|
||||
|
||||
fn acceptsString(foo: []u8) void {
|
||||
_ = foo;
|
||||
}
|
||||
|
||||
test "function pointers" {
|
||||
const fns = [_]@TypeOf(fn1){
|
||||
fn1,
|
||||
fn2,
|
||||
fn3,
|
||||
fn4,
|
||||
};
|
||||
for (fns) |f, i| {
|
||||
try expect(f() == @intCast(u32, i) + 5);
|
||||
}
|
||||
}
|
||||
fn fn1() u32 {
|
||||
return 5;
|
||||
}
|
||||
fn fn2() u32 {
|
||||
return 6;
|
||||
}
|
||||
fn fn3() u32 {
|
||||
return 7;
|
||||
}
|
||||
fn fn4() u32 {
|
||||
return 8;
|
||||
}
|
||||
|
||||
test "number literal as an argument" {
|
||||
try numberLiteralArg(3);
|
||||
comptime try numberLiteralArg(3);
|
||||
}
|
||||
|
||||
fn numberLiteralArg(a: anytype) !void {
|
||||
try expect(a == 3);
|
||||
}
|
||||
|
||||
test "function call with anon list literal" {
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
try consumeVec(.{ 9, 8, 7 });
|
||||
}
|
||||
|
||||
fn consumeVec(vec: [3]f32) !void {
|
||||
try expect(vec[0] == 9);
|
||||
try expect(vec[1] == 8);
|
||||
try expect(vec[2] == 7);
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "ability to give comptime types and non comptime types to same parameter" {
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var x: i32 = 1;
|
||||
try expect(foo(x) == 10);
|
||||
try expect(foo(i32) == 20);
|
||||
}
|
||||
|
||||
fn foo(arg: anytype) i32 {
|
||||
if (@typeInfo(@TypeOf(arg)) == .Type and arg == i32) return 20;
|
||||
return 9 + arg;
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "function with inferred error set but returning no error" {
|
||||
const S = struct {
|
||||
fn foo() !void {}
|
||||
};
|
||||
|
||||
const return_ty = @typeInfo(@TypeOf(S.foo)).Fn.return_type.?;
|
||||
try expectEqual(0, @typeInfo(@typeInfo(return_ty).ErrorUnion.error_set).ErrorSet.?.len);
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
@@ -133,3 +134,59 @@ test "2 break statements and an else" {
|
||||
try S.entry(true, false);
|
||||
comptime try S.entry(true, false);
|
||||
}
|
||||
|
||||
test "for loop with pointer elem var" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const source = "abcdefg";
|
||||
var target: [source.len]u8 = undefined;
|
||||
mem.copy(u8, target[0..], source);
|
||||
mangleString(target[0..]);
|
||||
try expect(mem.eql(u8, &target, "bcdefgh"));
|
||||
|
||||
for (source) |*c, i| {
|
||||
_ = i;
|
||||
try expect(@TypeOf(c) == *const u8);
|
||||
}
|
||||
for (target) |*c, i| {
|
||||
_ = i;
|
||||
try expect(@TypeOf(c) == *u8);
|
||||
}
|
||||
}
|
||||
|
||||
fn mangleString(s: []u8) void {
|
||||
for (s) |*c| {
|
||||
c.* += 1;
|
||||
}
|
||||
}
|
||||
|
||||
test "for copies its payload" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var x = [_]usize{ 1, 2, 3 };
|
||||
for (x) |value, i| {
|
||||
// Modify the original array
|
||||
x[i] += 99;
|
||||
try expectEqual(value, i + 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "for on slice with allowzero ptr" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest(slice: []const u8) !void {
|
||||
var ptr = @ptrCast([*]allowzero const u8, slice.ptr)[0..slice.len];
|
||||
for (ptr) |x, i| try expect(x == i + 1);
|
||||
for (ptr) |*x, i| try expect(x.* == i + 1);
|
||||
}
|
||||
};
|
||||
try S.doTheTest(&[_]u8{ 1, 2, 3, 4 });
|
||||
comptime try S.doTheTest(&[_]u8{ 1, 2, 3, 4 });
|
||||
}
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const mem = std.mem;
|
||||
|
||||
test "for loop with pointer elem var" {
|
||||
const source = "abcdefg";
|
||||
var target: [source.len]u8 = undefined;
|
||||
mem.copy(u8, target[0..], source);
|
||||
mangleString(target[0..]);
|
||||
try expect(mem.eql(u8, &target, "bcdefgh"));
|
||||
|
||||
for (source) |*c, i| {
|
||||
_ = i;
|
||||
try expect(@TypeOf(c) == *const u8);
|
||||
}
|
||||
for (target) |*c, i| {
|
||||
_ = i;
|
||||
try expect(@TypeOf(c) == *u8);
|
||||
}
|
||||
}
|
||||
|
||||
fn mangleString(s: []u8) void {
|
||||
for (s) |*c| {
|
||||
c.* += 1;
|
||||
}
|
||||
}
|
||||
|
||||
test "for copies its payload" {
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var x = [_]usize{ 1, 2, 3 };
|
||||
for (x) |value, i| {
|
||||
// Modify the original array
|
||||
x[i] += 99;
|
||||
try expectEqual(value, i + 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "for on slice with allowzero ptr" {
|
||||
const S = struct {
|
||||
fn doTheTest(slice: []const u8) !void {
|
||||
var ptr = @ptrCast([*]allowzero const u8, slice.ptr)[0..slice.len];
|
||||
for (ptr) |x, i| try expect(x == i + 1);
|
||||
for (ptr) |*x, i| try expect(x.* == i + 1);
|
||||
}
|
||||
};
|
||||
try S.doTheTest(&[_]u8{ 1, 2, 3, 4 });
|
||||
comptime try S.doTheTest(&[_]u8{ 1, 2, 3, 4 });
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
@@ -88,3 +89,21 @@ test "if copies its payload" {
|
||||
try S.doTheTest();
|
||||
comptime try S.doTheTest();
|
||||
}
|
||||
|
||||
test "if prongs cast to expected type instead of peer type resolution" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest(f: bool) !void {
|
||||
var x: i32 = 0;
|
||||
x = if (f) 1 else 2;
|
||||
try expect(x == 2);
|
||||
|
||||
var b = true;
|
||||
const y: i32 = if (b) 1 else 2;
|
||||
try expect(y == 1);
|
||||
}
|
||||
};
|
||||
try S.doTheTest(false);
|
||||
comptime try S.doTheTest(false);
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
|
||||
test "if prongs cast to expected type instead of peer type resolution" {
|
||||
const S = struct {
|
||||
fn doTheTest(f: bool) !void {
|
||||
var x: i32 = 0;
|
||||
x = if (f) 1 else 2;
|
||||
try expect(x == 2);
|
||||
|
||||
var b = true;
|
||||
const y: i32 = if (b) 1 else 2;
|
||||
try expect(y == 1);
|
||||
}
|
||||
};
|
||||
try S.doTheTest(false);
|
||||
comptime try S.doTheTest(false);
|
||||
}
|
||||
@@ -5,63 +5,6 @@ const expectEqualStrings = std.testing.expectEqualStrings;
|
||||
const mem = std.mem;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
fn emptyFn() void {}
|
||||
|
||||
const addr1 = @ptrCast(*const u8, emptyFn);
|
||||
test "comptime cast fn to ptr" {
|
||||
const addr2 = @ptrCast(*const u8, emptyFn);
|
||||
comptime try expect(addr1 == addr2);
|
||||
}
|
||||
|
||||
test "equality compare fn ptrs" {
|
||||
var a = emptyFn;
|
||||
try expect(a == a);
|
||||
}
|
||||
|
||||
test "string escapes" {
|
||||
try expectEqualStrings("\"", "\x22");
|
||||
try expectEqualStrings("\'", "\x27");
|
||||
try expectEqualStrings("\n", "\x0a");
|
||||
try expectEqualStrings("\r", "\x0d");
|
||||
try expectEqualStrings("\t", "\x09");
|
||||
try expectEqualStrings("\\", "\x5c");
|
||||
try expectEqualStrings("\u{1234}\u{069}\u{1}", "\xe1\x88\xb4\x69\x01");
|
||||
}
|
||||
|
||||
test "explicit cast optional pointers" {
|
||||
const a: ?*i32 = undefined;
|
||||
const b: ?*f32 = @ptrCast(?*f32, a);
|
||||
_ = b;
|
||||
}
|
||||
|
||||
test "pointer comparison" {
|
||||
const a = @as([]const u8, "a");
|
||||
const b = &a;
|
||||
try expect(ptrEql(b, b));
|
||||
}
|
||||
fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
|
||||
return a == b;
|
||||
}
|
||||
|
||||
test "string concatenation" {
|
||||
const a = "OK" ++ " IT " ++ "WORKED";
|
||||
const b = "OK IT WORKED";
|
||||
|
||||
comptime try expect(@TypeOf(a) == *const [12:0]u8);
|
||||
comptime try expect(@TypeOf(b) == *const [12:0]u8);
|
||||
|
||||
const len = mem.len(b);
|
||||
const len_with_null = len + 1;
|
||||
{
|
||||
var i: u32 = 0;
|
||||
while (i < len_with_null) : (i += 1) {
|
||||
try expect(a[i] == b[i]);
|
||||
}
|
||||
}
|
||||
try expect(a[len] == 0);
|
||||
try expect(b[len] == 0);
|
||||
}
|
||||
|
||||
// can't really run this test but we can make sure it has no compile error
|
||||
// and generates code
|
||||
const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000];
|
||||
@@ -91,76 +34,3 @@ export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion) void {
|
||||
b;
|
||||
}
|
||||
}
|
||||
|
||||
test "thread local variable" {
|
||||
const S = struct {
|
||||
threadlocal var t: i32 = 1234;
|
||||
};
|
||||
S.t += 1;
|
||||
try expect(S.t == 1235);
|
||||
}
|
||||
|
||||
fn maybe(x: bool) anyerror!?u32 {
|
||||
return switch (x) {
|
||||
true => @as(u32, 42),
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
|
||||
test "result location is optional inside error union" {
|
||||
const x = maybe(true) catch unreachable;
|
||||
try expect(x.? == 42);
|
||||
}
|
||||
|
||||
threadlocal var buffer: [11]u8 = undefined;
|
||||
|
||||
test "pointer to thread local array" {
|
||||
const s = "Hello world";
|
||||
std.mem.copy(u8, buffer[0..], s);
|
||||
try std.testing.expectEqualSlices(u8, buffer[0..], s);
|
||||
}
|
||||
|
||||
test "auto created variables have correct alignment" {
|
||||
const S = struct {
|
||||
fn foo(str: [*]const u8) u32 {
|
||||
for (@ptrCast([*]align(1) const u32, str)[0..1]) |v| {
|
||||
return v;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
try expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
|
||||
comptime try expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
|
||||
}
|
||||
|
||||
extern var opaque_extern_var: opaque {};
|
||||
var var_to_export: u32 = 42;
|
||||
test "extern variable with non-pointer opaque type" {
|
||||
@export(var_to_export, .{ .name = "opaque_extern_var" });
|
||||
try expect(@ptrCast(*align(1) u32, &opaque_extern_var).* == 42);
|
||||
}
|
||||
|
||||
test "lazy typeInfo value as generic parameter" {
|
||||
const S = struct {
|
||||
fn foo(args: anytype) void {
|
||||
_ = args;
|
||||
}
|
||||
};
|
||||
S.foo(@typeInfo(@TypeOf(.{})));
|
||||
}
|
||||
|
||||
test "variable name containing underscores does not shadow int primitive" {
|
||||
const _u0 = 0;
|
||||
const i_8 = 0;
|
||||
const u16_ = 0;
|
||||
const i3_2 = 0;
|
||||
const u6__4 = 0;
|
||||
const i2_04_8 = 0;
|
||||
|
||||
_ = _u0;
|
||||
_ = i_8;
|
||||
_ = u16_;
|
||||
_ = i3_2;
|
||||
_ = u6__4;
|
||||
_ = i2_04_8;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user