mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
Sema: fixes to fieldVal, resolveStructFully, Type.eql
fieldVal handles pointer to pointer to array. This can happen for example, if a pointer to an array is used as the condition expression of a for loop. resolveStructFully handles tuples (by doing nothing). fixed Type comparison for tuples to handle comptime fields properly.
This commit is contained in:
parent
64f7231f86
commit
95fbce2b95
5 changed files with 405 additions and 371 deletions
62
src/Sema.zig
62
src/Sema.zig
|
|
@ -12998,7 +12998,7 @@ fn fieldVal(
|
|||
.Array => {
|
||||
if (mem.eql(u8, field_name, "len")) {
|
||||
return sema.addConstant(
|
||||
Type.initTag(.comptime_int),
|
||||
Type.comptime_int,
|
||||
try Value.Tag.int_u64.create(arena, inner_ty.arrayLen()),
|
||||
);
|
||||
} else {
|
||||
|
|
@ -13010,26 +13010,43 @@ fn fieldVal(
|
|||
);
|
||||
}
|
||||
},
|
||||
.Pointer => if (inner_ty.isSlice()) {
|
||||
if (mem.eql(u8, field_name, "ptr")) {
|
||||
const slice = if (is_pointer_to)
|
||||
try sema.analyzeLoad(block, src, object, object_src)
|
||||
else
|
||||
object;
|
||||
return sema.analyzeSlicePtr(block, src, slice, inner_ty, object_src);
|
||||
} else if (mem.eql(u8, field_name, "len")) {
|
||||
const slice = if (is_pointer_to)
|
||||
try sema.analyzeLoad(block, src, object, object_src)
|
||||
else
|
||||
object;
|
||||
return sema.analyzeSliceLen(block, src, slice);
|
||||
} else {
|
||||
return sema.fail(
|
||||
block,
|
||||
field_name_src,
|
||||
"no member named '{s}' in '{}'",
|
||||
.{ field_name, object_ty },
|
||||
);
|
||||
.Pointer => {
|
||||
const ptr_info = inner_ty.ptrInfo().data;
|
||||
if (ptr_info.size == .Slice) {
|
||||
if (mem.eql(u8, field_name, "ptr")) {
|
||||
const slice = if (is_pointer_to)
|
||||
try sema.analyzeLoad(block, src, object, object_src)
|
||||
else
|
||||
object;
|
||||
return sema.analyzeSlicePtr(block, src, slice, inner_ty, object_src);
|
||||
} else if (mem.eql(u8, field_name, "len")) {
|
||||
const slice = if (is_pointer_to)
|
||||
try sema.analyzeLoad(block, src, object, object_src)
|
||||
else
|
||||
object;
|
||||
return sema.analyzeSliceLen(block, src, slice);
|
||||
} else {
|
||||
return sema.fail(
|
||||
block,
|
||||
field_name_src,
|
||||
"no member named '{s}' in '{}'",
|
||||
.{ field_name, object_ty },
|
||||
);
|
||||
}
|
||||
} else if (ptr_info.pointee_type.zigTypeTag() == .Array) {
|
||||
if (mem.eql(u8, field_name, "len")) {
|
||||
return sema.addConstant(
|
||||
Type.comptime_int,
|
||||
try Value.Tag.int_u64.create(arena, ptr_info.pointee_type.arrayLen()),
|
||||
);
|
||||
} else {
|
||||
return sema.fail(
|
||||
block,
|
||||
field_name_src,
|
||||
"no member named '{s}' in '{}'",
|
||||
.{ field_name, ptr_info.pointee_type },
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
.Type => {
|
||||
|
|
@ -16371,7 +16388,8 @@ fn resolveStructFully(
|
|||
try resolveStructLayout(sema, block, src, ty);
|
||||
|
||||
const resolved_ty = try sema.resolveTypeFields(block, src, ty);
|
||||
const struct_obj = resolved_ty.castTag(.@"struct").?.data;
|
||||
const payload = resolved_ty.castTag(.@"struct") orelse return;
|
||||
const struct_obj = payload.data;
|
||||
switch (struct_obj.status) {
|
||||
.none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
|
||||
.fully_resolved_wip, .fully_resolved => return,
|
||||
|
|
|
|||
14
src/type.zig
14
src/type.zig
|
|
@ -634,7 +634,19 @@ pub const Type = extern union {
|
|||
for (a_payload.data.values) |a_val, i| {
|
||||
const ty = a_payload.data.types[i];
|
||||
const b_val = b_payload.data.values[i];
|
||||
if (!Value.eql(a_val, b_val, ty)) return false;
|
||||
if (a_val.tag() == .unreachable_value) {
|
||||
if (b_val.tag() == .unreachable_value) {
|
||||
continue;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (b_val.tag() == .unreachable_value) {
|
||||
return false;
|
||||
} else {
|
||||
if (!Value.eql(a_val, b_val, ty)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -163,7 +163,6 @@ test {
|
|||
_ = @import("behavior/select.zig");
|
||||
_ = @import("behavior/shuffle.zig");
|
||||
_ = @import("behavior/sizeof_and_typeof_stage1.zig");
|
||||
_ = @import("behavior/slice_stage1.zig");
|
||||
_ = @import("behavior/struct_contains_null_ptr_itself.zig");
|
||||
_ = @import("behavior/struct_contains_slice_of_itself.zig");
|
||||
_ = @import("behavior/switch_prong_err_enum.zig");
|
||||
|
|
|
|||
|
|
@ -204,3 +204,355 @@ test "slice string literal has correct type" {
|
|||
const array = [_]i32{ 1, 2, 3, 4 };
|
||||
comptime try expect(@TypeOf(array[runtime_zero..]) == []const i32);
|
||||
}
|
||||
|
||||
test "result location zero sized array inside struct field implicit cast to slice" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
|
||||
const E = struct {
|
||||
entries: []u32,
|
||||
};
|
||||
var foo = E{ .entries = &[_]u32{} };
|
||||
try expect(foo.entries.len == 0);
|
||||
}
|
||||
|
||||
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 "C pointer" {
|
||||
var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
|
||||
var len: u32 = 10;
|
||||
var slice = buf[0..len];
|
||||
try expect(mem.eql(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 expect(@as(u32, 42) == cl.*);
|
||||
}
|
||||
}
|
||||
|
||||
test "comptime slices are disambiguated" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
try expect(sliceSum(&[_]u8{ 1, 2 }) == 3);
|
||||
try expect(sliceSum(&[_]u8{ 3, 4 }) == 7);
|
||||
}
|
||||
|
||||
fn sliceSum(comptime q: []const u8) i32 {
|
||||
comptime var result = 0;
|
||||
inline for (q) |item| {
|
||||
result += item;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
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 "obtaining a null terminated slice" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
|
||||
// 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" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
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" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
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" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
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 "type coercion of pointer to anon struct literal to pointer to slice" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
test "array concat of slices gives slice" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
comptime {
|
||||
var a: []const u8 = "aoeu";
|
||||
var b: []const u8 = "asdf";
|
||||
const c = a ++ b;
|
||||
try expect(std.mem.eql(u8, c, "aoeuasdf"));
|
||||
}
|
||||
}
|
||||
|
||||
test "slice bounds in comptime concatenation" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
const bs = comptime blk: {
|
||||
const b = "........1........";
|
||||
break :blk b[8..9];
|
||||
};
|
||||
const str = "" ++ bs;
|
||||
try expect(str.len == 1);
|
||||
try expect(std.mem.eql(u8, str, "1"));
|
||||
|
||||
const str2 = bs ++ "";
|
||||
try expect(str2.len == 1);
|
||||
try expect(std.mem.eql(u8, str2, "1"));
|
||||
}
|
||||
|
||||
test "slice sentinel access at comptime" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
{
|
||||
const str0 = &[_:0]u8{ '1', '2', '3' };
|
||||
const slice0: [:0]const u8 = str0;
|
||||
|
||||
try expect(slice0.len == 3);
|
||||
try expect(slice0[slice0.len] == 0);
|
||||
}
|
||||
{
|
||||
const str0 = "123";
|
||||
_ = &str0[0];
|
||||
const slice0: [:0]const u8 = str0;
|
||||
|
||||
try expect(slice0.len == 3);
|
||||
try expect(slice0[slice0.len] == 0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,347 +0,0 @@
|
|||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const expectEqualSlices = std.testing.expectEqualSlices;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const mem = std.mem;
|
||||
|
||||
test "result location zero sized array inside struct field implicit cast to slice" {
|
||||
const E = struct {
|
||||
entries: []u32,
|
||||
};
|
||||
var foo = E{ .entries = &[_]u32{} };
|
||||
try expect(foo.entries.len == 0);
|
||||
}
|
||||
|
||||
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 "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 "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 "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();
|
||||
}
|
||||
|
||||
test "array concat of slices gives slice" {
|
||||
comptime {
|
||||
var a: []const u8 = "aoeu";
|
||||
var b: []const u8 = "asdf";
|
||||
const c = a ++ b;
|
||||
try expect(std.mem.eql(u8, c, "aoeuasdf"));
|
||||
}
|
||||
}
|
||||
|
||||
test "slice bounds in comptime concatenation" {
|
||||
const bs = comptime blk: {
|
||||
const b = "........1........";
|
||||
break :blk b[8..9];
|
||||
};
|
||||
const str = "" ++ bs;
|
||||
try expect(str.len == 1);
|
||||
try expect(std.mem.eql(u8, str, "1"));
|
||||
|
||||
const str2 = bs ++ "";
|
||||
try expect(str2.len == 1);
|
||||
try expect(std.mem.eql(u8, str2, "1"));
|
||||
}
|
||||
|
||||
test "slice sentinel access at comptime" {
|
||||
{
|
||||
const str0 = &[_:0]u8{ '1', '2', '3' };
|
||||
const slice0: [:0]const u8 = str0;
|
||||
|
||||
try expect(slice0.len == 3);
|
||||
try expect(slice0[slice0.len] == 0);
|
||||
}
|
||||
{
|
||||
const str0 = "123";
|
||||
_ = &str0[0];
|
||||
const slice0: [:0]const u8 = str0;
|
||||
|
||||
try expect(slice0.len == 3);
|
||||
try expect(slice0[slice0.len] == 0);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue