Commit 81219586bc

dweiller <4678790+dweiller@users.noreply.github.com>
2023-11-07 10:19:59
sema: allow slicing [*]T without end
1 parent 03abac3
Changed files (3)
doc
src
test
behavior
doc/langref.html.in
@@ -2649,7 +2649,7 @@ test "Conversion between vectors, arrays, and slices" {
           <li>{#syntax#}[*]T{#endsyntax#} - many-item pointer to unknown number of items.
             <ul>
               <li>Supports index syntax: {#syntax#}ptr[i]{#endsyntax#}</li>
-              <li>Supports slice syntax: {#syntax#}ptr[start..end]{#endsyntax#}</li>
+              <li>Supports slice syntax: {#syntax#}ptr[start..end]{#endsyntax#} and {#syntax#}ptr[start..]{#endsyntax#}</li>
               <li>Supports pointer arithmetic: {#syntax#}ptr + x{#endsyntax#}, {#syntax#}ptr - x{#endsyntax#}</li>
               <li>{#syntax#}T{#endsyntax#} must have a known size, which means that it cannot be
               {#syntax#}anyopaque{#endsyntax#} or any other {#link|opaque type|opaque#}.</li>
@@ -2724,6 +2724,10 @@ test "pointer arithmetic with many-item pointer" {
     try expect(ptr[0] == 1);
     ptr += 1;
     try expect(ptr[0] == 2);
+
+    // slicing a many-item pointer without an end is equivalent to
+    // pointer arithmetic: `ptr[start..] == ptr + start`
+    try expect(ptr[1..] == ptr + 1);
 }
 
 test "pointer arithmetic with slices" {
src/Sema.zig
@@ -32182,7 +32182,7 @@ fn analyzeSlice(
                 break :e try sema.coerce(block, Type.usize, uncasted_end, end_src);
             } else break :e try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
         }
-        return sema.fail(block, src, "slice of pointer must include end value", .{});
+        return sema.analyzePtrArithmetic(block, src, ptr, start, .ptr_add, ptr_src, start_src);
     };
 
     const sentinel = s: {
test/behavior/slice.zig
@@ -348,6 +348,41 @@ test "@ptrCast slice to pointer" {
     try comptime S.doTheTest();
 }
 
+test "slice multi-pointer without end" {
+    const S = struct {
+        fn doTheTest() !void {
+            try testPointer();
+            try testPointerZ();
+        }
+
+        fn testPointer() !void {
+            var array = [5]u8{ 1, 2, 3, 4, 5 };
+            var pointer: [*]u8 = &array;
+            var slice = pointer[1..];
+            try comptime expect(@TypeOf(slice) == [*]u8);
+            try expect(slice[0] == 2);
+            try expect(slice[1] == 3);
+        }
+
+        fn testPointerZ() !void {
+            var array = [5:0]u8{ 1, 2, 3, 4, 5 };
+            var pointer: [*:0]u8 = &array;
+
+            try comptime expect(@TypeOf(pointer[1..3]) == *[2]u8);
+            try comptime expect(@TypeOf(pointer[1..3 :4]) == *[2:4]u8);
+            try comptime expect(@TypeOf(pointer[1..5 :0]) == *[4:0]u8);
+
+            var slice = pointer[1..];
+            try comptime expect(@TypeOf(slice) == [*:0]u8);
+            try expect(slice[0] == 2);
+            try expect(slice[1] == 3);
+        }
+    };
+
+    try S.doTheTest();
+    try comptime S.doTheTest();
+}
+
 test "slice syntax resulting in pointer-to-array" {
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO