Skip to content

Commit 5b6326e

Browse files
committed
fix slice of slice with sentinel on the lhs slice
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.
1 parent 5d51d44 commit 5b6326e

File tree

4 files changed

+57
-11
lines changed

4 files changed

+57
-11
lines changed

lib/std/zig/AstGen.zig

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -881,21 +881,14 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
881881
.slice_sentinel,
882882
=> {
883883
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);
888884
if (full.ast.end != 0 and
889-
lhs_is_open_slice and
885+
node_tags[full.ast.sliced] == .slice_open and
890886
nodeIsTriviallyZero(tree, full.ast.start))
891887
{
892-
const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[full.ast.sliced].lhs);
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);
888+
const lhs_extra = tree.sliceOpen(full.ast.sliced).ast;
898889

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);
899892
const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
900893
const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.end);
901894
const sentinel = if (full.ast.sentinel != 0) try expr(gz, scope, .{ .rl = .none }, full.ast.sentinel) else .none;

test/behavior/slice.zig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,23 @@ test "open slice of open slice with sentinel" {
115115
try expect(slice[1..][0.. :0][4] == 0);
116116
}
117117

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+
118135
test "slice of type" {
119136
comptime {
120137
var types_array = [_]type{ i32, f64, type };
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

0 commit comments

Comments
 (0)