Sema: implement comptime coerce_result_ptr and alloc

This is progress towards being able to use `builtin.cpu.arch` instead of
the `stage2_arch` workaround. The next blocker is comptime `elemVal`.
This commit is contained in:
Andrew Kelley 2021-10-13 14:16:01 -07:00
parent 2a701a92c4
commit e851d89113
4 changed files with 375 additions and 348 deletions

View File

@ -1340,29 +1340,50 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
const pointee_ty = try sema.resolveType(block, src, bin_inst.lhs);
const ptr = sema.resolveInst(bin_inst.rhs);
// Create a runtime bitcast instruction with exactly the type the pointer wants.
const ptr_ty = try Type.ptr(sema.arena, .{
.pointee_type = pointee_ty,
.@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
});
try sema.requireRuntimeBlock(block, src);
const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);
if (Air.refToIndex(ptr)) |ptr_inst| {
if (sema.air_instructions.items(.tag)[ptr_inst] == .constant) {
const air_datas = sema.air_instructions.items(.data);
const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload];
if (ptr_val.castTag(.inferred_alloc)) |inferred_alloc| {
// Add the stored instruction to the set we will use to resolve peer types
// for the inferred allocation.
// This instruction will not make it to codegen; it is only to participate
// in the `stored_inst_list` of the `inferred_alloc`.
const operand = try block.addTyOp(.bitcast, pointee_ty, .void_value);
try inferred_alloc.data.stored_inst_list.append(sema.arena, operand);
switch (ptr_val.tag()) {
.inferred_alloc => {
const inferred_alloc = &ptr_val.castTag(.inferred_alloc).?.data;
// Add the stored instruction to the set we will use to resolve peer types
// for the inferred allocation.
// This instruction will not make it to codegen; it is only to participate
// in the `stored_inst_list` of the `inferred_alloc`.
const operand = try block.addTyOp(.bitcast, pointee_ty, .void_value);
try inferred_alloc.stored_inst_list.append(sema.arena, operand);
},
.inferred_alloc_comptime => {
const iac = ptr_val.castTag(.inferred_alloc_comptime).?;
// There will be only one coerce_result_ptr because we are running at comptime.
// The alloc will turn into a Decl.
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
iac.data = try anon_decl.finish(
try pointee_ty.copy(anon_decl.arena()),
Value.undef,
);
return sema.addConstant(
ptr_ty,
try Value.Tag.decl_ref_mut.create(sema.arena, .{
.decl = iac.data,
.runtime_index = block.runtime_index,
}),
);
},
.decl_ref_mut => return sema.addConstant(ptr_ty, ptr_val),
else => {},
}
}
}
try sema.requireRuntimeBlock(block, src);
const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);
return bitcasted_ptr;
}
@ -1996,6 +2017,9 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node };
const var_decl_src = inst_data.src();
const var_type = try sema.resolveType(block, ty_src, inst_data.operand);
if (block.is_comptime) {
return sema.analyzeComptimeAlloc(block, var_type);
}
const ptr_type = try Type.ptr(sema.arena, .{
.pointee_type = var_type,
.@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
@ -13418,9 +13442,10 @@ fn analyzeComptimeAlloc(
defer anon_decl.deinit();
const decl = try anon_decl.finish(
try var_type.copy(anon_decl.arena()),
// AstGen guarantees there will be a store before the first load, so we put a value
// here indicating there is no valid value.
Value.initTag(.unreachable_value),
// There will be stores before the first load, but they may be to sub-elements or
// sub-fields. So we need to initialize with undef to allow the mechanism to expand
// into fields/elements and have those overridden with stored values.
Value.undef,
);
try sema.mod.declareDeclDependency(sema.owner_decl, decl);
return sema.addConstant(ptr_type, try Value.Tag.decl_ref_mut.create(sema.arena, .{

View File

@ -26,6 +26,7 @@ test {
_ = @import("behavior/math.zig");
_ = @import("behavior/member_func.zig");
_ = @import("behavior/pointers.zig");
_ = @import("behavior/slice.zig");
_ = @import("behavior/sizeof_and_typeof.zig");
_ = @import("behavior/struct.zig");
_ = @import("behavior/switch.zig");
@ -150,7 +151,7 @@ test {
_ = @import("behavior/shuffle.zig");
_ = @import("behavior/select.zig");
_ = @import("behavior/sizeof_and_typeof_stage1.zig");
_ = @import("behavior/slice.zig");
_ = @import("behavior/slice_stage1.zig");
_ = @import("behavior/slice_sentinel_comptime.zig");
_ = @import("behavior/struct_stage1.zig");
_ = @import("behavior/struct_contains_null_ptr_itself.zig");

View File

@ -3,336 +3,3 @@ const expect = std.testing.expect;
const expectEqualSlices = std.testing.expectEqualSlices;
const expectEqual = std.testing.expectEqual;
const mem = std.mem;
const x = @intToPtr([*]i32, 0x1000)[0..0x500];
const y = x[0x100..];
test "compile time slice of pointer to hard coded address" {
try expect(@ptrToInt(x) == 0x1000);
try expect(x.len == 0x500);
try expect(@ptrToInt(y) == 0x1100);
try expect(y.len == 0x400);
}
test "runtime safety lets us slice from len..len" {
var an_array = [_]u8{
1,
2,
3,
};
try expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
}
fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
return a_slice[start..end];
}
test "implicitly cast array of size 0 to slice" {
var msg = [_]u8{};
try assertLenIsZero(&msg);
}
fn assertLenIsZero(msg: []const u8) !void {
try expect(msg.len == 0);
}
test "C pointer" {
var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
var len: u32 = 10;
var slice = buf[0..len];
try expectEqualSlices(u8, "kjdhfkjdhf", slice);
}
test "C pointer slice access" {
var buf: [10]u32 = [1]u32{42} ** 10;
const c_ptr = @ptrCast([*c]const u32, &buf);
var runtime_zero: usize = 0;
comptime try expectEqual([]const u32, @TypeOf(c_ptr[runtime_zero..1]));
comptime try expectEqual(*const [1]u32, @TypeOf(c_ptr[0..1]));
for (c_ptr[0..5]) |*cl| {
try expectEqual(@as(u32, 42), cl.*);
}
}
fn sliceSum(comptime q: []const u8) i32 {
comptime var result = 0;
inline for (q) |item| {
result += item;
}
return result;
}
test "comptime slices are disambiguated" {
try expect(sliceSum(&[_]u8{ 1, 2 }) == 3);
try expect(sliceSum(&[_]u8{ 3, 4 }) == 7);
}
test "slice type with custom alignment" {
const LazilyResolvedType = struct {
anything: i32,
};
var slice: []align(32) LazilyResolvedType = undefined;
var array: [10]LazilyResolvedType align(32) = undefined;
slice = &array;
slice[1].anything = 42;
try expect(array[1].anything == 42);
}
test "access len index of sentinel-terminated slice" {
const S = struct {
fn doTheTest() !void {
var slice: [:0]const u8 = "hello";
try expect(slice.len == 5);
try expect(slice[5] == 0);
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "obtaining a null terminated slice" {
// here we have a normal array
var buf: [50]u8 = undefined;
buf[0] = 'a';
buf[1] = 'b';
buf[2] = 'c';
buf[3] = 0;
// now we obtain a null terminated slice:
const ptr = buf[0..3 :0];
_ = ptr;
var runtime_len: usize = 3;
const ptr2 = buf[0..runtime_len :0];
// ptr2 is a null-terminated slice
comptime try expect(@TypeOf(ptr2) == [:0]u8);
comptime try expect(@TypeOf(ptr2[0..2]) == *[2]u8);
var runtime_zero: usize = 0;
comptime try expect(@TypeOf(ptr2[runtime_zero..2]) == []u8);
}
test "empty array to slice" {
const S = struct {
fn doTheTest() !void {
const empty: []align(16) u8 = &[_]u8{};
const align_1: []align(1) u8 = empty;
const align_4: []align(4) u8 = empty;
const align_16: []align(16) u8 = empty;
try expectEqual(1, @typeInfo(@TypeOf(align_1)).Pointer.alignment);
try expectEqual(4, @typeInfo(@TypeOf(align_4)).Pointer.alignment);
try expectEqual(16, @typeInfo(@TypeOf(align_16)).Pointer.alignment);
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "@ptrCast slice to pointer" {
const S = struct {
fn doTheTest() !void {
var array align(@alignOf(u16)) = [5]u8{ 0xff, 0xff, 0xff, 0xff, 0xff };
var slice: []u8 = &array;
var ptr = @ptrCast(*u16, slice);
try expect(ptr.* == 65535);
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "slice syntax resulting in pointer-to-array" {
const S = struct {
fn doTheTest() !void {
try testArray();
try testArrayZ();
try testArray0();
try testArrayAlign();
try testPointer();
try testPointerZ();
try testPointer0();
try testPointerAlign();
try testSlice();
try testSliceZ();
try testSlice0();
try testSliceOpt();
try testSliceAlign();
}
fn testArray() !void {
var array = [5]u8{ 1, 2, 3, 4, 5 };
var slice = array[1..3];
comptime try expect(@TypeOf(slice) == *[2]u8);
try expect(slice[0] == 2);
try expect(slice[1] == 3);
}
fn testArrayZ() !void {
var array = [5:0]u8{ 1, 2, 3, 4, 5 };
comptime try expect(@TypeOf(array[1..3]) == *[2]u8);
comptime try expect(@TypeOf(array[1..5]) == *[4:0]u8);
comptime try expect(@TypeOf(array[1..]) == *[4:0]u8);
comptime try expect(@TypeOf(array[1..3 :4]) == *[2:4]u8);
}
fn testArray0() !void {
{
var array = [0]u8{};
var slice = array[0..0];
comptime try expect(@TypeOf(slice) == *[0]u8);
}
{
var array = [0:0]u8{};
var slice = array[0..0];
comptime try expect(@TypeOf(slice) == *[0:0]u8);
try expect(slice[0] == 0);
}
}
fn testArrayAlign() !void {
var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
var slice = array[4..5];
comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
try expect(slice[0] == 5);
comptime try expect(@TypeOf(array[0..2]) == *align(4) [2]u8);
}
fn testPointer() !void {
var array = [5]u8{ 1, 2, 3, 4, 5 };
var pointer: [*]u8 = &array;
var slice = pointer[1..3];
comptime try expect(@TypeOf(slice) == *[2]u8);
try expect(slice[0] == 2);
try expect(slice[1] == 3);
}
fn testPointerZ() !void {
var array = [5:0]u8{ 1, 2, 3, 4, 5 };
var pointer: [*:0]u8 = &array;
comptime try expect(@TypeOf(pointer[1..3]) == *[2]u8);
comptime try expect(@TypeOf(pointer[1..3 :4]) == *[2:4]u8);
}
fn testPointer0() !void {
var pointer: [*]const u0 = &[1]u0{0};
var slice = pointer[0..1];
comptime try expect(@TypeOf(slice) == *const [1]u0);
try expect(slice[0] == 0);
}
fn testPointerAlign() !void {
var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
var pointer: [*]align(4) u8 = &array;
var slice = pointer[4..5];
comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
try expect(slice[0] == 5);
comptime try expect(@TypeOf(pointer[0..2]) == *align(4) [2]u8);
}
fn testSlice() !void {
var array = [5]u8{ 1, 2, 3, 4, 5 };
var src_slice: []u8 = &array;
var slice = src_slice[1..3];
comptime try expect(@TypeOf(slice) == *[2]u8);
try expect(slice[0] == 2);
try expect(slice[1] == 3);
}
fn testSliceZ() !void {
var array = [5:0]u8{ 1, 2, 3, 4, 5 };
var slice: [:0]u8 = &array;
comptime try expect(@TypeOf(slice[1..3]) == *[2]u8);
comptime try expect(@TypeOf(slice[1..]) == [:0]u8);
comptime try expect(@TypeOf(slice[1..3 :4]) == *[2:4]u8);
}
fn testSliceOpt() !void {
var array: [2]u8 = [2]u8{ 1, 2 };
var slice: ?[]u8 = &array;
comptime try expect(@TypeOf(&array, slice) == ?[]u8);
comptime try expect(@TypeOf(slice.?[0..2]) == *[2]u8);
}
fn testSlice0() !void {
{
var array = [0]u8{};
var src_slice: []u8 = &array;
var slice = src_slice[0..0];
comptime try expect(@TypeOf(slice) == *[0]u8);
}
{
var array = [0:0]u8{};
var src_slice: [:0]u8 = &array;
var slice = src_slice[0..0];
comptime try expect(@TypeOf(slice) == *[0]u8);
}
}
fn testSliceAlign() !void {
var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
var src_slice: []align(4) u8 = &array;
var slice = src_slice[4..5];
comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
try expect(slice[0] == 5);
comptime try expect(@TypeOf(src_slice[0..2]) == *align(4) [2]u8);
}
fn testConcatStrLiterals() !void {
try expectEqualSlices("a"[0..] ++ "b"[0..], "ab");
try expectEqualSlices("a"[0.. :0] ++ "b"[0.. :0], "ab");
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "slice of hardcoded address to pointer" {
const S = struct {
fn doTheTest() !void {
const pointer = @intToPtr([*]u8, 0x04)[0..2];
comptime try expect(@TypeOf(pointer) == *[2]u8);
const slice: []const u8 = pointer;
try expect(@ptrToInt(slice.ptr) == 4);
try expect(slice.len == 2);
}
};
try S.doTheTest();
}
test "type coercion of pointer to anon struct literal to pointer to slice" {
const S = struct {
const U = union {
a: u32,
b: bool,
c: []const u8,
};
fn doTheTest() !void {
var x1: u8 = 42;
const t1 = &.{ x1, 56, 54 };
var slice1: []const u8 = t1;
try expect(slice1.len == 3);
try expect(slice1[0] == 42);
try expect(slice1[1] == 56);
try expect(slice1[2] == 54);
var x2: []const u8 = "hello";
const t2 = &.{ x2, ", ", "world!" };
// @compileLog(@TypeOf(t2));
var slice2: []const []const u8 = t2;
try expect(slice2.len == 3);
try expect(mem.eql(u8, slice2[0], "hello"));
try expect(mem.eql(u8, slice2[1], ", "));
try expect(mem.eql(u8, slice2[2], "world!"));
}
};
// try S.doTheTest();
comptime try S.doTheTest();
}

View File

@ -0,0 +1,334 @@
const std = @import("std");
const expect = std.testing.expect;
const expectEqualSlices = std.testing.expectEqualSlices;
const expectEqual = std.testing.expectEqual;
const mem = std.mem;
const x = @intToPtr([*]i32, 0x1000)[0..0x500];
const y = x[0x100..];
test "compile time slice of pointer to hard coded address" {
try expect(@ptrToInt(x) == 0x1000);
try expect(x.len == 0x500);
try expect(@ptrToInt(y) == 0x1100);
try expect(y.len == 0x400);
}
test "runtime safety lets us slice from len..len" {
var an_array = [_]u8{ 1, 2, 3 };
try expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
}
fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
return a_slice[start..end];
}
test "implicitly cast array of size 0 to slice" {
var msg = [_]u8{};
try assertLenIsZero(&msg);
}
fn assertLenIsZero(msg: []const u8) !void {
try expect(msg.len == 0);
}
test "C pointer" {
var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
var len: u32 = 10;
var slice = buf[0..len];
try expectEqualSlices(u8, "kjdhfkjdhf", slice);
}
test "C pointer slice access" {
var buf: [10]u32 = [1]u32{42} ** 10;
const c_ptr = @ptrCast([*c]const u32, &buf);
var runtime_zero: usize = 0;
comptime try expectEqual([]const u32, @TypeOf(c_ptr[runtime_zero..1]));
comptime try expectEqual(*const [1]u32, @TypeOf(c_ptr[0..1]));
for (c_ptr[0..5]) |*cl| {
try expectEqual(@as(u32, 42), cl.*);
}
}
fn sliceSum(comptime q: []const u8) i32 {
comptime var result = 0;
inline for (q) |item| {
result += item;
}
return result;
}
test "comptime slices are disambiguated" {
try expect(sliceSum(&[_]u8{ 1, 2 }) == 3);
try expect(sliceSum(&[_]u8{ 3, 4 }) == 7);
}
test "slice type with custom alignment" {
const LazilyResolvedType = struct {
anything: i32,
};
var slice: []align(32) LazilyResolvedType = undefined;
var array: [10]LazilyResolvedType align(32) = undefined;
slice = &array;
slice[1].anything = 42;
try expect(array[1].anything == 42);
}
test "access len index of sentinel-terminated slice" {
const S = struct {
fn doTheTest() !void {
var slice: [:0]const u8 = "hello";
try expect(slice.len == 5);
try expect(slice[5] == 0);
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "obtaining a null terminated slice" {
// here we have a normal array
var buf: [50]u8 = undefined;
buf[0] = 'a';
buf[1] = 'b';
buf[2] = 'c';
buf[3] = 0;
// now we obtain a null terminated slice:
const ptr = buf[0..3 :0];
_ = ptr;
var runtime_len: usize = 3;
const ptr2 = buf[0..runtime_len :0];
// ptr2 is a null-terminated slice
comptime try expect(@TypeOf(ptr2) == [:0]u8);
comptime try expect(@TypeOf(ptr2[0..2]) == *[2]u8);
var runtime_zero: usize = 0;
comptime try expect(@TypeOf(ptr2[runtime_zero..2]) == []u8);
}
test "empty array to slice" {
const S = struct {
fn doTheTest() !void {
const empty: []align(16) u8 = &[_]u8{};
const align_1: []align(1) u8 = empty;
const align_4: []align(4) u8 = empty;
const align_16: []align(16) u8 = empty;
try expectEqual(1, @typeInfo(@TypeOf(align_1)).Pointer.alignment);
try expectEqual(4, @typeInfo(@TypeOf(align_4)).Pointer.alignment);
try expectEqual(16, @typeInfo(@TypeOf(align_16)).Pointer.alignment);
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "@ptrCast slice to pointer" {
const S = struct {
fn doTheTest() !void {
var array align(@alignOf(u16)) = [5]u8{ 0xff, 0xff, 0xff, 0xff, 0xff };
var slice: []u8 = &array;
var ptr = @ptrCast(*u16, slice);
try expect(ptr.* == 65535);
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "slice syntax resulting in pointer-to-array" {
const S = struct {
fn doTheTest() !void {
try testArray();
try testArrayZ();
try testArray0();
try testArrayAlign();
try testPointer();
try testPointerZ();
try testPointer0();
try testPointerAlign();
try testSlice();
try testSliceZ();
try testSlice0();
try testSliceOpt();
try testSliceAlign();
}
fn testArray() !void {
var array = [5]u8{ 1, 2, 3, 4, 5 };
var slice = array[1..3];
comptime try expect(@TypeOf(slice) == *[2]u8);
try expect(slice[0] == 2);
try expect(slice[1] == 3);
}
fn testArrayZ() !void {
var array = [5:0]u8{ 1, 2, 3, 4, 5 };
comptime try expect(@TypeOf(array[1..3]) == *[2]u8);
comptime try expect(@TypeOf(array[1..5]) == *[4:0]u8);
comptime try expect(@TypeOf(array[1..]) == *[4:0]u8);
comptime try expect(@TypeOf(array[1..3 :4]) == *[2:4]u8);
}
fn testArray0() !void {
{
var array = [0]u8{};
var slice = array[0..0];
comptime try expect(@TypeOf(slice) == *[0]u8);
}
{
var array = [0:0]u8{};
var slice = array[0..0];
comptime try expect(@TypeOf(slice) == *[0:0]u8);
try expect(slice[0] == 0);
}
}
fn testArrayAlign() !void {
var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
var slice = array[4..5];
comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
try expect(slice[0] == 5);
comptime try expect(@TypeOf(array[0..2]) == *align(4) [2]u8);
}
fn testPointer() !void {
var array = [5]u8{ 1, 2, 3, 4, 5 };
var pointer: [*]u8 = &array;
var slice = pointer[1..3];
comptime try expect(@TypeOf(slice) == *[2]u8);
try expect(slice[0] == 2);
try expect(slice[1] == 3);
}
fn testPointerZ() !void {
var array = [5:0]u8{ 1, 2, 3, 4, 5 };
var pointer: [*:0]u8 = &array;
comptime try expect(@TypeOf(pointer[1..3]) == *[2]u8);
comptime try expect(@TypeOf(pointer[1..3 :4]) == *[2:4]u8);
}
fn testPointer0() !void {
var pointer: [*]const u0 = &[1]u0{0};
var slice = pointer[0..1];
comptime try expect(@TypeOf(slice) == *const [1]u0);
try expect(slice[0] == 0);
}
fn testPointerAlign() !void {
var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
var pointer: [*]align(4) u8 = &array;
var slice = pointer[4..5];
comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
try expect(slice[0] == 5);
comptime try expect(@TypeOf(pointer[0..2]) == *align(4) [2]u8);
}
fn testSlice() !void {
var array = [5]u8{ 1, 2, 3, 4, 5 };
var src_slice: []u8 = &array;
var slice = src_slice[1..3];
comptime try expect(@TypeOf(slice) == *[2]u8);
try expect(slice[0] == 2);
try expect(slice[1] == 3);
}
fn testSliceZ() !void {
var array = [5:0]u8{ 1, 2, 3, 4, 5 };
var slice: [:0]u8 = &array;
comptime try expect(@TypeOf(slice[1..3]) == *[2]u8);
comptime try expect(@TypeOf(slice[1..]) == [:0]u8);
comptime try expect(@TypeOf(slice[1..3 :4]) == *[2:4]u8);
}
fn testSliceOpt() !void {
var array: [2]u8 = [2]u8{ 1, 2 };
var slice: ?[]u8 = &array;
comptime try expect(@TypeOf(&array, slice) == ?[]u8);
comptime try expect(@TypeOf(slice.?[0..2]) == *[2]u8);
}
fn testSlice0() !void {
{
var array = [0]u8{};
var src_slice: []u8 = &array;
var slice = src_slice[0..0];
comptime try expect(@TypeOf(slice) == *[0]u8);
}
{
var array = [0:0]u8{};
var src_slice: [:0]u8 = &array;
var slice = src_slice[0..0];
comptime try expect(@TypeOf(slice) == *[0]u8);
}
}
fn testSliceAlign() !void {
var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
var src_slice: []align(4) u8 = &array;
var slice = src_slice[4..5];
comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
try expect(slice[0] == 5);
comptime try expect(@TypeOf(src_slice[0..2]) == *align(4) [2]u8);
}
fn testConcatStrLiterals() !void {
try expectEqualSlices("a"[0..] ++ "b"[0..], "ab");
try expectEqualSlices("a"[0.. :0] ++ "b"[0.. :0], "ab");
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "slice of hardcoded address to pointer" {
const S = struct {
fn doTheTest() !void {
const pointer = @intToPtr([*]u8, 0x04)[0..2];
comptime try expect(@TypeOf(pointer) == *[2]u8);
const slice: []const u8 = pointer;
try expect(@ptrToInt(slice.ptr) == 4);
try expect(slice.len == 2);
}
};
try S.doTheTest();
}
test "type coercion of pointer to anon struct literal to pointer to slice" {
const S = struct {
const U = union {
a: u32,
b: bool,
c: []const u8,
};
fn doTheTest() !void {
var x1: u8 = 42;
const t1 = &.{ x1, 56, 54 };
var slice1: []const u8 = t1;
try expect(slice1.len == 3);
try expect(slice1[0] == 42);
try expect(slice1[1] == 56);
try expect(slice1[2] == 54);
var x2: []const u8 = "hello";
const t2 = &.{ x2, ", ", "world!" };
// @compileLog(@TypeOf(t2));
var slice2: []const []const u8 = t2;
try expect(slice2.len == 3);
try expect(mem.eql(u8, slice2[0], "hello"));
try expect(mem.eql(u8, slice2[1], ", "));
try expect(mem.eql(u8, slice2[2], "world!"));
}
};
// try S.doTheTest();
comptime try S.doTheTest();
}