sema: allow slicing *T with comptime known [0..1]
This commit is contained in:
76
src/Sema.zig
76
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 => {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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]
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user