| author | |
| committer | |
| log | 5b6326ec6540d1b7af8de1176f657672be72a1e4 |
| tree | 60d3a3c3ad1f5c68d12c33ae7b4181af9331fc1c |
| parent | 5d51d4474a0c61f08c264c03ecbdf651d91afe82 |
| signature |
example:
```zig
test {
var foo: [2:0]u8 = .{ 1, 2 };
_ = foo[0.. :1][0..2];
}
```
A `.slice_open` ast node will not have a end index nor sentinel.4 files changed, 57 insertions(+), 11 deletions(-)
lib/std/zig/AstGen.zig+4-11| ... | @@ -881,21 +881,14 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE | ... | @@ -881,21 +881,14 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 881 | .slice_sentinel, | 881 | .slice_sentinel, |
| 882 | => { | 882 | => { |
| 883 | const full = tree.fullSlice(node).?; | 883 | const full = tree.fullSlice(node).?; |
| 884 | const lhs_tag = node_tags[full.ast.sliced]; | ||
| 885 | const lhs_is_slice_sentinel = lhs_tag == .slice_sentinel; | ||
| 886 | const lhs_is_open_slice = lhs_tag == .slice_open or | ||
| 887 | (lhs_is_slice_sentinel and tree.fullSlice(full.ast.sliced).?.ast.end == 0); | ||
| 888 | if (full.ast.end != 0 and | 884 | if (full.ast.end != 0 and |
| 889 | lhs_is_open_slice and | 885 | node_tags[full.ast.sliced] == .slice_open and |
| 890 | nodeIsTriviallyZero(tree, full.ast.start)) | 886 | nodeIsTriviallyZero(tree, full.ast.start)) |
| 891 | { | 887 | { |
| 892 | const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[full.ast.sliced].lhs); | 888 | const lhs_extra = tree.sliceOpen(full.ast.sliced).ast; |
| 893 | |||
| 894 | const start = if (lhs_is_slice_sentinel) start: { | ||
| 895 | const lhs_extra = tree.extraData(node_datas[full.ast.sliced].rhs, Ast.Node.SliceSentinel); | ||
| 896 | break :start try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, lhs_extra.start); | ||
| 897 | } else try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[full.ast.sliced].rhs); | ||
| 898 | 889 | ||
| 890 | const lhs = try expr(gz, scope, .{ .rl = .ref }, lhs_extra.sliced); | ||
| 891 | const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, lhs_extra.start); | ||
| 899 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); | 892 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); |
| 900 | const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.end); | 893 | const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.end); |
| 901 | const sentinel = if (full.ast.sentinel != 0) try expr(gz, scope, .{ .rl = .none }, full.ast.sentinel) else .none; | 894 | const sentinel = if (full.ast.sentinel != 0) try expr(gz, scope, .{ .rl = .none }, full.ast.sentinel) else .none; |
test/behavior/slice.zig+17| ... | @@ -115,6 +115,23 @@ test "open slice of open slice with sentinel" { | ... | @@ -115,6 +115,23 @@ test "open slice of open slice with sentinel" { |
| 115 | try expect(slice[1..][0.. :0][4] == 0); | 115 | try expect(slice[1..][0.. :0][4] == 0); |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | test "open slice with sentinel of slice with end index" { | ||
| 119 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | ||
| 120 | |||
| 121 | var slice: [:0]const u8 = "hello"; | ||
| 122 | _ = &slice; | ||
| 123 | |||
| 124 | comptime assert(@TypeOf(slice[0.. :0][0..5]) == *const [5]u8); | ||
| 125 | try expect(slice[0.. :0][0..5].len == 5); | ||
| 126 | try expect(slice[0.. :0][0..5][0] == 'h'); | ||
| 127 | try expect(slice[0.. :0][0..5][4] == 'o'); | ||
| 128 | |||
| 129 | comptime assert(@TypeOf(slice[0.. :0][0..5 :0]) == *const [5:0]u8); | ||
| 130 | try expect(slice[0.. :0][0..5 :0].len == 5); | ||
| 131 | try expect(slice[0.. :0][0..5 :0][0] == 'h'); | ||
| 132 | try expect(slice[0.. :0][0..5 :0][5] == 0); | ||
| 133 | } | ||
| 134 | |||
| 118 | test "slice of type" { | 135 | test "slice of type" { |
| 119 | comptime { | 136 | comptime { |
| 120 | var types_array = [_]type{ i32, f64, type }; | 137 | var types_array = [_]type{ i32, f64, type }; |
test/cases/safety/slice by length sentinel mismatch on lhs.zig	 created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "sentinel mismatch: expected 1, found 3")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | pub fn main() !void { | ||
| 11 | var buf: [4:0]u8 = .{ 1, 2, 3, 4 }; | ||
| 12 | const slice = buf[0..][0..2 :1]; | ||
| 13 | _ = slice; | ||
| 14 | return error.TestFailed; | ||
| 15 | } | ||
| 16 | // run | ||
| 17 | // backend=llvm | ||
| 18 | // target=native | ||
test/cases/safety/slice by length sentinel mismatch on rhs.zig	 created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "sentinel mismatch: expected 1, found 0")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | pub fn main() !void { | ||
| 11 | var buf: [4:0]u8 = .{ 1, 2, 3, 4 }; | ||
| 12 | const slice = buf[0.. :1][0..2]; | ||
| 13 | _ = slice; | ||
| 14 | return error.TestFailed; | ||
| 15 | } | ||
| 16 | // run | ||
| 17 | // backend=llvm | ||
| 18 | // target=native | ||