Commit 8afafa717f
Changed files (4)
src
test
behavior
cases
src/Sema.zig
@@ -32572,14 +32572,86 @@ fn analyzeSlice(
.Pointer => switch (ptr_ptr_child_ty.ptrSize(mod)) {
.One => {
const double_child_ty = ptr_ptr_child_ty.childType(mod);
+ ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src);
if (double_child_ty.zigTypeTag(mod) == .Array) {
ptr_sentinel = double_child_ty.sentinel(mod);
- ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src);
slice_ty = ptr_ptr_child_ty;
array_ty = double_child_ty;
elem_ty = double_child_ty.childType(mod);
} else {
- return sema.fail(block, src, "slice of single-item pointer", .{});
+ const bounds_error_message = "slice of single-item pointer must have comptime-known bounds [0..0], [0..1], or [1..1]";
+ if (uncasted_end_opt == .none) {
+ return sema.fail(block, src, bounds_error_message, .{});
+ }
+ const start_value = try sema.resolveConstDefinedValue(
+ block,
+ start_src,
+ uncasted_start,
+ .{ .needed_comptime_reason = bounds_error_message },
+ );
+
+ const end_value = try sema.resolveConstDefinedValue(
+ block,
+ end_src,
+ uncasted_end_opt,
+ .{ .needed_comptime_reason = bounds_error_message },
+ );
+
+ if (try sema.compareScalar(start_value, .neq, end_value, Type.comptime_int)) {
+ if (try sema.compareScalar(start_value, .neq, InternPool.Index.zero.toValue(), Type.comptime_int)) {
+ const err_msg = try sema.errMsg(block, start_src, bounds_error_message, .{});
+ try sema.errNote(
+ block,
+ start_src,
+ err_msg,
+ "expected '{}', found '{}'",
+ .{
+ Value.zero_comptime_int.fmtValue(Type.comptime_int, mod),
+ start_value.fmtValue(Type.comptime_int, mod),
+ },
+ );
+ return sema.failWithOwnedErrorMsg(block, err_msg);
+ } else if (try sema.compareScalar(end_value, .neq, InternPool.Index.one.toValue(), Type.comptime_int)) {
+ const err_msg = try sema.errMsg(block, end_src, bounds_error_message, .{});
+ try sema.errNote(
+ block,
+ end_src,
+ err_msg,
+ "expected '{}', found '{}'",
+ .{
+ Value.one_comptime_int.fmtValue(Type.comptime_int, mod),
+ end_value.fmtValue(Type.comptime_int, mod),
+ },
+ );
+ return sema.failWithOwnedErrorMsg(block, err_msg);
+ }
+ } else {
+ if (try sema.compareScalar(end_value, .gt, InternPool.Index.one.toValue(), Type.comptime_int)) {
+ return sema.fail(
+ block,
+ end_src,
+ "end index {} out of bounds for slice of single-item pointer",
+ .{end_value.fmtValue(Type.comptime_int, mod)},
+ );
+ }
+ }
+
+ array_ty = try mod.arrayType(.{
+ .len = 1,
+ .child = double_child_ty.toIntern(),
+ });
+ const ptr_info = ptr_ptr_child_ty.ptrInfo(mod);
+ slice_ty = try mod.ptrType(.{
+ .child = array_ty.toIntern(),
+ .flags = .{
+ .alignment = ptr_info.flags.alignment,
+ .is_const = ptr_info.flags.is_const,
+ .is_allowzero = ptr_info.flags.is_allowzero,
+ .is_volatile = ptr_info.flags.is_volatile,
+ .address_space = ptr_info.flags.address_space,
+ },
+ });
+ elem_ty = double_child_ty;
}
},
.Many, .C => {
test/behavior/slice.zig
@@ -416,6 +416,7 @@ test "slice syntax resulting in pointer-to-array" {
try testArrayLengthZ();
try testMultiPointer();
try testMultiPointerLengthZ();
+ try testSingleItemPointer();
}
fn testArray() !void {
@@ -591,6 +592,17 @@ test "slice syntax resulting in pointer-to-array" {
try comptime expect(@TypeOf(ptr_z[1.. :0][0..4]) == *[4]u8);
try comptime expect(@TypeOf(ptr_z[1.. :0][0..2 :4]) == *[2:4]u8);
}
+
+ fn testSingleItemPointer() !void {
+ var value: u8 = 1;
+ var ptr = &value;
+
+ const slice = ptr[0..1];
+ try comptime expect(@TypeOf(slice) == *[1]u8);
+ try expect(slice[0] == 1);
+
+ try comptime expect(@TypeOf(ptr[0..0]) == *[0]u8);
+ }
};
try S.doTheTest();
test/cases/compile_errors/slice_of_single-item_pointer_bounds.zig
@@ -0,0 +1,41 @@
+const value: u8 = 1;
+const ptr = &value;
+
+comptime {
+ _ = ptr[0..];
+}
+
+comptime {
+ _ = ptr[1..2];
+}
+
+comptime {
+ _ = ptr[0..2];
+}
+
+comptime {
+ _ = ptr[2..2];
+}
+
+export fn entry1() void {
+ var start: usize = 0;
+ _ = ptr[start..2];
+}
+
+export fn entry2() void {
+ var end: usize = 0;
+ _ = ptr[0..end];
+}
+
+// error
+//
+// :5:12: error: slice of single-item pointer must have comptime-known bounds [0..0], [0..1], or [1..1]
+// :9:13: error: slice of single-item pointer must have comptime-known bounds [0..0], [0..1], or [1..1]
+// :9:13: note: expected '0', found '1'
+// :13:16: error: slice of single-item pointer must have comptime-known bounds [0..0], [0..1], or [1..1]
+// :13:16: note: expected '1', found '2'
+// :17:16: error: end index 2 out of bounds for slice of single-item pointer
+// :22:13: error: unable to resolve comptime value
+// :22:13: note: slice of single-item pointer must have comptime-known bounds [0..0], [0..1], or [1..1]
+// :27:16: error: unable to resolve comptime value
+// :27:16: note: slice of single-item pointer must have comptime-known bounds [0..0], [0..1], or [1..1]
test/cases/compile_errors/slicing_single-item_pointer.zig
@@ -1,10 +0,0 @@
-export fn entry(ptr: *i32) void {
- const slice = ptr[0..2];
- _ = slice;
-}
-
-// error
-// backend=stage2
-// target=native
-//
-// :2:22: error: slice of single-item pointer