| author | |
| committer | |
| log | 19fc5f4fb29a525252b2eaf3f6388d07f97bd32f |
| tree | 2ef144edec2325d943ab8601c686aaab4ebacae5 |
| parent | bce6a7c21529e9b294a641b5d7472c000204aaef |
This change prevents adding or changing the sentinel in the type of a
many-item pointer via the slicing syntax `ptr[a.. :S]`.3 files changed, 50 insertions(+), 3 deletions(-)
src/Sema.zig+32| ... | @@ -31876,6 +31876,38 @@ fn analyzeSlice( | ... | @@ -31876,6 +31876,38 @@ fn analyzeSlice( |
| 31876 | break :e try sema.coerce(block, .usize, uncasted_end, end_src); | 31876 | break :e try sema.coerce(block, .usize, uncasted_end, end_src); |
| 31877 | } else break :e try sema.coerce(block, .usize, uncasted_end_opt, end_src); | 31877 | } else break :e try sema.coerce(block, .usize, uncasted_end_opt, end_src); |
| 31878 | } | 31878 | } |
| 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 | } | ||
| 31879 | return sema.analyzePtrArithmetic(block, src, ptr, start, .ptr_add, ptr_src, start_src); | 31911 | return sema.analyzePtrArithmetic(block, src, ptr, start, .ptr_add, ptr_src, start_src); |
| 31880 | }; | 31912 | }; |
| 31881 | 31913 |
test/behavior/slice.zig-3| ... | @@ -628,9 +628,6 @@ test "slice syntax resulting in pointer-to-array" { | ... | @@ -628,9 +628,6 @@ test "slice syntax resulting in pointer-to-array" { |
| 628 | comptime assert(@TypeOf(ptr[1..][0..2]) == *[2]u8); | 628 | comptime assert(@TypeOf(ptr[1..][0..2]) == *[2]u8); |
| 629 | comptime assert(@TypeOf(ptr[1..][0..4]) == *[4]u8); | 629 | comptime assert(@TypeOf(ptr[1..][0..4]) == *[4]u8); |
| 630 | comptime assert(@TypeOf(ptr[1..][0..2 :4]) == *[2:4]u8); | 630 | 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); | ||
| 634 | 631 | ||
| 635 | var ptr_z: [*:0]u8 = &array; | 632 | var ptr_z: [*:0]u8 = &array; |
| 636 | comptime assert(@TypeOf(ptr_z[1..][0..2]) == *[2]u8); | 633 | comptime assert(@TypeOf(ptr_z[1..][0..2]) == *[2]u8); |
test/cases/compile_errors/slice_of_many-item_pointer_preserves_sentinel.zig created+18| ... | @@ -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 | ||