diff --git a/src/ir.cpp b/src/ir.cpp index 2f9e3638f8..1e3fe67b2b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -26583,7 +26583,6 @@ done_with_return_type: if (parent_ptr == nullptr) return ira->codegen->invalid_inst_gen; - if (parent_ptr->special == ConstValSpecialUndef) { array_val = nullptr; abs_offset = 0; @@ -26746,6 +26745,113 @@ done_with_return_type: return ira->codegen->invalid_inst_gen; } + // check sentinel when target is comptime-known + { + if (!sentinel_val) + goto exit_check_sentinel; + + switch (ptr_ptr->value->data.x_ptr.mut) { + case ConstPtrMutComptimeConst: + case ConstPtrMutComptimeVar: + break; + case ConstPtrMutRuntimeVar: + case ConstPtrMutInfer: + goto exit_check_sentinel; + } + + // prepare check parameters + ZigValue *target = const_ptr_pointee(ira, ira->codegen, ptr_ptr->value, instruction->base.base.source_node); + if (target == nullptr) + return ira->codegen->invalid_inst_gen; + + uint64_t target_len = 0; + ZigValue *target_sentinel = nullptr; + ZigValue *target_elements = nullptr; + + for (;;) { + if (target->type->id == ZigTypeIdArray) { + // handle `[N]T` + target_len = target->type->data.array.len; + target_sentinel = target->type->data.array.sentinel; + target_elements = target->data.x_array.data.s_none.elements; + break; + } else if (target->type->id == ZigTypeIdPointer && target->type->data.pointer.child_type->id == ZigTypeIdArray) { + // handle `*[N]T` + target = const_ptr_pointee(ira, ira->codegen, target, instruction->base.base.source_node); + if (target == nullptr) + return ira->codegen->invalid_inst_gen; + assert(target->type->id == ZigTypeIdArray); + continue; + } else if (target->type->id == ZigTypeIdPointer) { + // handle `[*]T` + // handle `[*c]T` + switch (target->data.x_ptr.special) { + case ConstPtrSpecialInvalid: + case ConstPtrSpecialDiscard: + zig_unreachable(); + case ConstPtrSpecialRef: + target = target->data.x_ptr.data.ref.pointee; + assert(target->type->id == ZigTypeIdArray); + continue; + case ConstPtrSpecialBaseArray: + case ConstPtrSpecialSubArray: + target = target->data.x_ptr.data.base_array.array_val; + assert(target->type->id == ZigTypeIdArray); + continue; + case ConstPtrSpecialBaseStruct: + zig_panic("TODO slice const inner struct"); + case ConstPtrSpecialBaseErrorUnionCode: + zig_panic("TODO slice const inner error union code"); + case ConstPtrSpecialBaseErrorUnionPayload: + zig_panic("TODO slice const inner error union payload"); + case ConstPtrSpecialBaseOptionalPayload: + zig_panic("TODO slice const inner optional payload"); + case ConstPtrSpecialHardCodedAddr: + // skip check + goto exit_check_sentinel; + case ConstPtrSpecialFunction: + zig_panic("TODO slice of ptr cast from function"); + case ConstPtrSpecialNull: + zig_panic("TODO slice of null ptr"); + } + break; + } else if (is_slice(target->type)) { + // handle `[]T` + target = target->data.x_struct.fields[slice_ptr_index]; + assert(target->type->id == ZigTypeIdPointer); + continue; + } + + zig_unreachable(); + } + + // perform check + if (target_sentinel == nullptr) { + if (end_scalar >= target_len) { + ir_add_error(ira, &instruction->base.base, buf_sprintf("slice-sentinel is out of bounds")); + return ira->codegen->invalid_inst_gen; + } + if (!const_values_equal(ira->codegen, sentinel_val, &target_elements[end_scalar])) { + ir_add_error(ira, &instruction->base.base, buf_sprintf("slice-sentinel does not match memory at target index")); + return ira->codegen->invalid_inst_gen; + } + } else { + assert(end_scalar <= target_len); + if (end_scalar == target_len) { + if (!const_values_equal(ira->codegen, sentinel_val, target_sentinel)) { + ir_add_error(ira, &instruction->base.base, buf_sprintf("slice-sentinel does not match target-sentinel")); + return ira->codegen->invalid_inst_gen; + } + } else { + if (!const_values_equal(ira->codegen, sentinel_val, &target_elements[end_scalar])) { + ir_add_error(ira, &instruction->base.base, buf_sprintf("slice-sentinel does not match memory at target index")); + return ira->codegen->invalid_inst_gen; + } + } + } + } + exit_check_sentinel: + IrInstGen *result = ir_const(ira, &instruction->base.base, return_type); ZigValue *ptr_val; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index e54f6591b5..a3c29e0dd6 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -6857,4 +6857,299 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:7:32: error: destination type 'u16' has size 2 but source type '[]u8' has size 16", "tmp.zig:7:37: note: referenced here", }); + + cases.add("comptime slice-sentinel is out of bounds (unterminated)", + \\export fn foo_array() void { + \\ comptime { + \\ var target = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ const slice = target[0..14 :0]; + \\ } + \\} + \\export fn foo_ptr_array() void { + \\ comptime { + \\ var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target = &buf; + \\ const slice = target[0..14 :0]; + \\ } + \\} + \\export fn foo_vector_ConstPtrSpecialBaseArray() void { + \\ comptime { + \\ var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*]u8 = &buf; + \\ const slice = target[0..14 :0]; + \\ } + \\} + \\export fn foo_vector_ConstPtrSpecialRef() void { + \\ comptime { + \\ var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*]u8 = @ptrCast([*]u8, &buf); + \\ const slice = target[0..14 :0]; + \\ } + \\} + \\export fn foo_cvector_ConstPtrSpecialBaseArray() void { + \\ comptime { + \\ var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*c]u8 = &buf; + \\ const slice = target[0..14 :0]; + \\ } + \\} + \\export fn foo_cvector_ConstPtrSpecialRef() void { + \\ comptime { + \\ var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*c]u8 = @ptrCast([*c]u8, &buf); + \\ const slice = target[0..14 :0]; + \\ } + \\} + \\export fn foo_slice() void { + \\ comptime { + \\ var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: []u8 = &buf; + \\ const slice = target[0..14 :0]; + \\ } + \\} + , &[_][]const u8{ + ":4:29: error: slice-sentinel is out of bounds", + ":11:29: error: slice-sentinel is out of bounds", + ":18:29: error: slice-sentinel is out of bounds", + ":25:29: error: slice-sentinel is out of bounds", + ":32:29: error: slice-sentinel is out of bounds", + ":39:29: error: slice-sentinel is out of bounds", + ":46:29: error: slice-sentinel is out of bounds", + }); + + cases.add("comptime slice-sentinel is out of bounds (terminated)", + \\export fn foo_array() void { + \\ comptime { + \\ var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ const slice = target[0..15 :1]; + \\ } + \\} + \\export fn foo_ptr_array() void { + \\ comptime { + \\ var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target = &buf; + \\ const slice = target[0..15 :0]; + \\ } + \\} + \\export fn foo_vector_ConstPtrSpecialBaseArray() void { + \\ comptime { + \\ var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*]u8 = &buf; + \\ const slice = target[0..15 :0]; + \\ } + \\} + \\export fn foo_vector_ConstPtrSpecialRef() void { + \\ comptime { + \\ var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*]u8 = @ptrCast([*]u8, &buf); + \\ const slice = target[0..15 :0]; + \\ } + \\} + \\export fn foo_cvector_ConstPtrSpecialBaseArray() void { + \\ comptime { + \\ var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*c]u8 = &buf; + \\ const slice = target[0..15 :0]; + \\ } + \\} + \\export fn foo_cvector_ConstPtrSpecialRef() void { + \\ comptime { + \\ var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*c]u8 = @ptrCast([*c]u8, &buf); + \\ const slice = target[0..15 :0]; + \\ } + \\} + \\export fn foo_slice() void { + \\ comptime { + \\ var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: []u8 = &buf; + \\ const slice = target[0..15 :0]; + \\ } + \\} + , &[_][]const u8{ + ":4:29: error: out of bounds slice", + ":11:29: error: out of bounds slice", + ":18:29: error: out of bounds slice", + ":25:29: error: out of bounds slice", + ":32:29: error: out of bounds slice", + ":39:29: error: out of bounds slice", + ":46:29: error: out of bounds slice", + }); + + cases.add("comptime slice-sentinel does not match memory at target index (unterminated)", + \\export fn foo_array() void { + \\ comptime { + \\ var target = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ const slice = target[0..3 :0]; + \\ } + \\} + \\export fn foo_ptr_array() void { + \\ comptime { + \\ var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target = &buf; + \\ const slice = target[0..3 :0]; + \\ } + \\} + \\export fn foo_vector_ConstPtrSpecialBaseArray() void { + \\ comptime { + \\ var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*]u8 = &buf; + \\ const slice = target[0..3 :0]; + \\ } + \\} + \\export fn foo_vector_ConstPtrSpecialRef() void { + \\ comptime { + \\ var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*]u8 = @ptrCast([*]u8, &buf); + \\ const slice = target[0..3 :0]; + \\ } + \\} + \\export fn foo_cvector_ConstPtrSpecialBaseArray() void { + \\ comptime { + \\ var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*c]u8 = &buf; + \\ const slice = target[0..3 :0]; + \\ } + \\} + \\export fn foo_cvector_ConstPtrSpecialRef() void { + \\ comptime { + \\ var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*c]u8 = @ptrCast([*c]u8, &buf); + \\ const slice = target[0..3 :0]; + \\ } + \\} + \\export fn foo_slice() void { + \\ comptime { + \\ var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: []u8 = &buf; + \\ const slice = target[0..3 :0]; + \\ } + \\} + , &[_][]const u8{ + ":4:29: error: slice-sentinel does not match memory at target index", + ":11:29: error: slice-sentinel does not match memory at target index", + ":18:29: error: slice-sentinel does not match memory at target index", + ":25:29: error: slice-sentinel does not match memory at target index", + ":32:29: error: slice-sentinel does not match memory at target index", + ":39:29: error: slice-sentinel does not match memory at target index", + ":46:29: error: slice-sentinel does not match memory at target index", + }); + + cases.add("comptime slice-sentinel does not match memory at target index (terminated)", + \\export fn foo_array() void { + \\ comptime { + \\ var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ const slice = target[0..3 :0]; + \\ } + \\} + \\export fn foo_ptr_array() void { + \\ comptime { + \\ var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target = &buf; + \\ const slice = target[0..3 :0]; + \\ } + \\} + \\export fn foo_vector_ConstPtrSpecialBaseArray() void { + \\ comptime { + \\ var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*]u8 = &buf; + \\ const slice = target[0..3 :0]; + \\ } + \\} + \\export fn foo_vector_ConstPtrSpecialRef() void { + \\ comptime { + \\ var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*]u8 = @ptrCast([*]u8, &buf); + \\ const slice = target[0..3 :0]; + \\ } + \\} + \\export fn foo_cvector_ConstPtrSpecialBaseArray() void { + \\ comptime { + \\ var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*c]u8 = &buf; + \\ const slice = target[0..3 :0]; + \\ } + \\} + \\export fn foo_cvector_ConstPtrSpecialRef() void { + \\ comptime { + \\ var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*c]u8 = @ptrCast([*c]u8, &buf); + \\ const slice = target[0..3 :0]; + \\ } + \\} + \\export fn foo_slice() void { + \\ comptime { + \\ var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: []u8 = &buf; + \\ const slice = target[0..3 :0]; + \\ } + \\} + , &[_][]const u8{ + ":4:29: error: slice-sentinel does not match memory at target index", + ":11:29: error: slice-sentinel does not match memory at target index", + ":18:29: error: slice-sentinel does not match memory at target index", + ":25:29: error: slice-sentinel does not match memory at target index", + ":32:29: error: slice-sentinel does not match memory at target index", + ":39:29: error: slice-sentinel does not match memory at target index", + ":46:29: error: slice-sentinel does not match memory at target index", + }); + + cases.add("comptime slice-sentinel does not match target-sentinel", + \\export fn foo_array() void { + \\ comptime { + \\ var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ const slice = target[0..14 :255]; + \\ } + \\} + \\export fn foo_ptr_array() void { + \\ comptime { + \\ var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target = &buf; + \\ const slice = target[0..14 :255]; + \\ } + \\} + \\export fn foo_vector_ConstPtrSpecialBaseArray() void { + \\ comptime { + \\ var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*]u8 = &buf; + \\ const slice = target[0..14 :255]; + \\ } + \\} + \\export fn foo_vector_ConstPtrSpecialRef() void { + \\ comptime { + \\ var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*]u8 = @ptrCast([*]u8, &buf); + \\ const slice = target[0..14 :255]; + \\ } + \\} + \\export fn foo_cvector_ConstPtrSpecialBaseArray() void { + \\ comptime { + \\ var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*c]u8 = &buf; + \\ const slice = target[0..14 :255]; + \\ } + \\} + \\export fn foo_cvector_ConstPtrSpecialRef() void { + \\ comptime { + \\ var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: [*c]u8 = @ptrCast([*c]u8, &buf); + \\ const slice = target[0..14 :255]; + \\ } + \\} + \\export fn foo_slice() void { + \\ comptime { + \\ var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + \\ var target: []u8 = &buf; + \\ const slice = target[0..14 :255]; + \\ } + \\} + , &[_][]const u8{ + ":4:29: error: slice-sentinel does not match target-sentinel", + ":11:29: error: slice-sentinel does not match target-sentinel", + ":18:29: error: slice-sentinel does not match target-sentinel", + ":25:29: error: slice-sentinel does not match target-sentinel", + ":32:29: error: slice-sentinel does not match target-sentinel", + ":39:29: error: slice-sentinel does not match target-sentinel", + ":46:29: error: slice-sentinel does not match target-sentinel", + }); } diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index c3407db3e6..52ce5979e1 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -96,6 +96,7 @@ comptime { _ = @import("behavior/shuffle.zig"); _ = @import("behavior/sizeof_and_typeof.zig"); _ = @import("behavior/slice.zig"); + _ = @import("behavior/slice_sentinel_comptime.zig"); _ = @import("behavior/struct.zig"); _ = @import("behavior/struct_contains_null_ptr_itself.zig"); _ = @import("behavior/struct_contains_slice_of_itself.zig"); diff --git a/test/stage1/behavior/slice_sentinel_comptime.zig b/test/stage1/behavior/slice_sentinel_comptime.zig new file mode 100644 index 0000000000..79da5d3c52 --- /dev/null +++ b/test/stage1/behavior/slice_sentinel_comptime.zig @@ -0,0 +1,199 @@ +test "comptime slice-sentinel in bounds (unterminated)" { + // array + comptime { + var target = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + const slice = target[0..3 :'d']; + } + + // ptr_array + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target = &buf; + const slice = target[0..3 :'d']; + } + + // vector_ConstPtrSpecialBaseArray + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*]u8 = &buf; + const slice = target[0..3 :'d']; + } + + // vector_ConstPtrSpecialRef + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*]u8 = @ptrCast([*]u8, &buf); + const slice = target[0..3 :'d']; + } + + // cvector_ConstPtrSpecialBaseArray + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*c]u8 = &buf; + const slice = target[0..3 :'d']; + } + + // cvector_ConstPtrSpecialRef + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*c]u8 = @ptrCast([*c]u8, &buf); + const slice = target[0..3 :'d']; + } + + // slice + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: []u8 = &buf; + const slice = target[0..3 :'d']; + } +} + +test "comptime slice-sentinel in bounds (end,unterminated)" { + // array + comptime { + var target = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10; + const slice = target[0..13 :0xff]; + } + + // ptr_array + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10; + var target = &buf; + const slice = target[0..13 :0xff]; + } + + // vector_ConstPtrSpecialBaseArray + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10; + var target: [*]u8 = &buf; + const slice = target[0..13 :0xff]; + } + + // vector_ConstPtrSpecialRef + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10; + var target: [*]u8 = @ptrCast([*]u8, &buf); + const slice = target[0..13 :0xff]; + } + + // cvector_ConstPtrSpecialBaseArray + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10; + var target: [*c]u8 = &buf; + const slice = target[0..13 :0xff]; + } + + // cvector_ConstPtrSpecialRef + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10; + var target: [*c]u8 = @ptrCast([*c]u8, &buf); + const slice = target[0..13 :0xff]; + } + + // slice + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10; + var target: []u8 = &buf; + const slice = target[0..13 :0xff]; + } +} + +test "comptime slice-sentinel in bounds (terminated)" { + // array + comptime { + var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + const slice = target[0..3 :'d']; + } + + // ptr_array + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target = &buf; + const slice = target[0..3 :'d']; + } + + // vector_ConstPtrSpecialBaseArray + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*]u8 = &buf; + const slice = target[0..3 :'d']; + } + + // vector_ConstPtrSpecialRef + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*]u8 = @ptrCast([*]u8, &buf); + const slice = target[0..3 :'d']; + } + + // cvector_ConstPtrSpecialBaseArray + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*c]u8 = &buf; + const slice = target[0..3 :'d']; + } + + // cvector_ConstPtrSpecialRef + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*c]u8 = @ptrCast([*c]u8, &buf); + const slice = target[0..3 :'d']; + } + + // slice + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: []u8 = &buf; + const slice = target[0..3 :'d']; + } +} + +test "comptime slice-sentinel in bounds (on target sentinel)" { + // array + comptime { + var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + const slice = target[0..14 :0]; + } + + // ptr_array + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target = &buf; + const slice = target[0..14 :0]; + } + + // vector_ConstPtrSpecialBaseArray + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*]u8 = &buf; + const slice = target[0..14 :0]; + } + + // vector_ConstPtrSpecialRef + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*]u8 = @ptrCast([*]u8, &buf); + const slice = target[0..14 :0]; + } + + // cvector_ConstPtrSpecialBaseArray + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*c]u8 = &buf; + const slice = target[0..14 :0]; + } + + // cvector_ConstPtrSpecialRef + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*c]u8 = @ptrCast([*c]u8, &buf); + const slice = target[0..14 :0]; + } + + // slice + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: []u8 = &buf; + const slice = target[0..14 :0]; + } +}