From e2020d51324a7961ac6627acbe0730451e0e68e6 Mon Sep 17 00:00:00 2001 From: Michael Byrne Date: Sat, 23 Oct 2021 19:50:22 +1100 Subject: [PATCH 1/4] Add documentation for sentinel-terminated slicing --- doc/langref.html.in | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/doc/langref.html.in b/doc/langref.html.in index 9e5edee9f883..10f0a2cafa0d 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2914,6 +2914,42 @@ test "null terminated slice" { try expect(slice.len == 5); try expect(slice[5] == 0); +} + {#code_end#} +

+ Sentinel-terminated slices can also be created using a variation of the slice syntax + {#syntax#}data[start..end :x]{#endsyntax#}, where {#syntax#}data{#endsyntax#} is a many-item pointer, + array or slice and {#syntax#}x{#endsyntax#} is the sentinel value. +

+ {#code_begin|test|null_terminated_slicing#} +const std = @import("std"); +const expect = std.testing.expect; + +test "null terminated slicing" { + var array = [_]u8{ 3, 2, 1, 0, 3, 2, 1, 0 }; + var runtime_length: usize = 3; + const slice = array[0..runtime_length :0]; + + try expect(@TypeOf(slice) == [:0]u8); + try expect(slice.len == 3); +} + {#code_end#} +

+ Sentinel-terminated slicing assumes that the element in the sentinel position of the backing data is + actually the sentinel value. If this is not the case a runtime error will result. +

+ {#code_begin|exe_err|illegal_null_terminated_slicing#} +pub fn main() void { + var array = [_]u8{ 3, 2, 1, 0 }; + + // Creating a sentinel-terminated slice from the array with a length of 2 + // will result in the value `1` occupying the sentinel element position. + // This does not match the indicated sentinel value of `0` and will lead + // to a runtime panic. + var runtime_length: usize = 2; + const slice = array[0..runtime_length :0]; + + _ = slice; } {#code_end#} {#see_also|Sentinel-Terminated Pointers|Sentinel-Terminated Arrays#} From d5525b2d6183bcc1f42babcd068a3bd656eaff0c Mon Sep 17 00:00:00 2001 From: Michael Byrne Date: Thu, 28 Oct 2021 07:19:03 +1100 Subject: [PATCH 2/4] Change 'assumes' to 'asserts' Co-authored-by: Andrew Kelley --- doc/langref.html.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 10f0a2cafa0d..5b25b0b50b09 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2935,7 +2935,7 @@ test "null terminated slicing" { } {#code_end#}

- Sentinel-terminated slicing assumes that the element in the sentinel position of the backing data is + Sentinel-terminated slicing asserts that the element in the sentinel position of the backing data is actually the sentinel value. If this is not the case a runtime error will result.

{#code_begin|exe_err|illegal_null_terminated_slicing#} From 06ded47dceaaa8a272c7a5f069bc313de068af77 Mon Sep 17 00:00:00 2001 From: Michael Byrne Date: Thu, 28 Oct 2021 07:19:58 +1100 Subject: [PATCH 3/4] Use more standard terminology for undefined behaviour Co-authored-by: Andrew Kelley --- doc/langref.html.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 5b25b0b50b09..372b66b8e1f8 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2936,7 +2936,7 @@ test "null terminated slicing" { {#code_end#}

Sentinel-terminated slicing asserts that the element in the sentinel position of the backing data is - actually the sentinel value. If this is not the case a runtime error will result. + actually the sentinel value. If this is not the case, safety-protected {#link|Undefined Behavior#} results.

{#code_begin|exe_err|illegal_null_terminated_slicing#} pub fn main() void { From e15c9e9e5d2563fa8a1bc5aac09f7d94eefe3a93 Mon Sep 17 00:00:00 2001 From: Michael Byrne Date: Thu, 28 Oct 2021 07:40:11 +1100 Subject: [PATCH 4/4] Switch illegal slicing example to a test --- doc/langref.html.in | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 372b66b8e1f8..5003e1b90739 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2938,10 +2938,13 @@ test "null terminated slicing" { Sentinel-terminated slicing asserts that the element in the sentinel position of the backing data is actually the sentinel value. If this is not the case, safety-protected {#link|Undefined Behavior#} results.

- {#code_begin|exe_err|illegal_null_terminated_slicing#} -pub fn main() void { - var array = [_]u8{ 3, 2, 1, 0 }; + {#code_begin|test_safety|sentinel mismatch#} +const std = @import("std"); +const expect = std.testing.expect; +test "sentinel mismatch" { + var array = [_]u8{ 3, 2, 1, 0 }; + // Creating a sentinel-terminated slice from the array with a length of 2 // will result in the value `1` occupying the sentinel element position. // This does not match the indicated sentinel value of `0` and will lead