sema: allow slicing *T with comptime known [0..1]

This commit is contained in:
dweiller
2023-11-09 23:30:53 +11:00
committed by Andrew Kelley
parent 4debd4338c
commit 8afafa717f
4 changed files with 127 additions and 12 deletions

View File

@@ -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 => {

View File

@@ -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();

View File

@@ -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]

View File

@@ -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