Skip to content

Commit 19fc5f4

Browse files
dweillermlugg
authored andcommitted
Sema: disallow slicing many-item pointer with different sentinel
This change prevents adding or changing the sentinel in the type of a many-item pointer via the slicing syntax `ptr[a.. :S]`.
1 parent bce6a7c commit 19fc5f4

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

src/Sema.zig

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31876,6 +31876,38 @@ fn analyzeSlice(
3187631876
break :e try sema.coerce(block, .usize, uncasted_end, end_src);
3187731877
} else break :e try sema.coerce(block, .usize, uncasted_end_opt, end_src);
3187831878
}
31879+
31880+
// when slicing a many-item pointer, if a sentinel `S` is provided as in `ptr[a.. :S]`, it
31881+
// must match the sentinel of `@TypeOf(ptr)`.
31882+
sentinel_check: {
31883+
if (sentinel_opt == .none) break :sentinel_check;
31884+
const provided = provided: {
31885+
const casted = try sema.coerce(block, elem_ty, sentinel_opt, sentinel_src);
31886+
try checkSentinelType(sema, block, sentinel_src, elem_ty);
31887+
break :provided try sema.resolveConstDefinedValue(
31888+
block,
31889+
sentinel_src,
31890+
casted,
31891+
.{ .simple = .slice_sentinel },
31892+
);
31893+
};
31894+
31895+
if (ptr_sentinel) |current| {
31896+
if (provided.toIntern() == current.toIntern()) break :sentinel_check;
31897+
}
31898+
31899+
return sema.failWithOwnedErrorMsg(block, msg: {
31900+
const msg = try sema.errMsg(sentinel_src, "sentinel-terminated slicing of many-item pointer must match existing sentinel", .{});
31901+
errdefer msg.destroy(sema.gpa);
31902+
if (ptr_sentinel) |current| {
31903+
try sema.errNote(sentinel_src, msg, "expected sentinel '{f}', found '{f}'", .{ current.fmtValue(pt), provided.fmtValue(pt) });
31904+
} else {
31905+
try sema.errNote(ptr_src, msg, "type '{f}' does not have a sentinel", .{slice_ty.fmt(pt)});
31906+
}
31907+
try sema.errNote(src, msg, "use @ptrCast to cast pointer sentinel", .{});
31908+
break :msg msg;
31909+
});
31910+
}
3187931911
return sema.analyzePtrArithmetic(block, src, ptr, start, .ptr_add, ptr_src, start_src);
3188031912
};
3188131913

test/behavior/slice.zig

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -628,9 +628,6 @@ test "slice syntax resulting in pointer-to-array" {
628628
comptime assert(@TypeOf(ptr[1..][0..2]) == *[2]u8);
629629
comptime assert(@TypeOf(ptr[1..][0..4]) == *[4]u8);
630630
comptime assert(@TypeOf(ptr[1..][0..2 :4]) == *[2:4]u8);
631-
comptime assert(@TypeOf(ptr[1.. :0][0..2]) == *[2]u8);
632-
comptime assert(@TypeOf(ptr[1.. :0][0..4]) == *[4]u8);
633-
comptime assert(@TypeOf(ptr[1.. :0][0..2 :4]) == *[2:4]u8);
634631

635632
var ptr_z: [*:0]u8 = &array;
636633
comptime assert(@TypeOf(ptr_z[1..][0..2]) == *[2]u8);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
comptime {
2+
var ptr: [*]const u8 = undefined;
3+
_ = ptr[0.. :0];
4+
}
5+
6+
comptime {
7+
var ptrz: [*:0]const u8 = undefined;
8+
_ = ptrz[0.. :1];
9+
}
10+
11+
// error
12+
//
13+
// :3:18: error: sentinel-terminated slicing of many-item pointer must match existing sentinel
14+
// :3:9: note: type '[*]const u8' does not have a sentinel
15+
// :3:12: note: use @ptrCast to cast pointer sentinel
16+
// :8:19: error: sentinel-terminated slicing of many-item pointer must match existing sentinel
17+
// :8:19: note: expected sentinel '0', found '1'
18+
// :8:13: note: use @ptrCast to cast pointer sentinel

0 commit comments

Comments
 (0)