authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-24 02:14:21-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-24 02:14:21-05:00
log4c7b52503b064b8be2f2afd4152311aff1941d92
tree3f8ea590d0dc73dbfd94b0863aa1bb8c32e4d0b9
parent2dd20aa04a35f46a189d0aaa5d2d628e46a77999
signaturelock-open Commit is signed but in an unrecognized format.

all tests passing


7 files changed, 53 insertions(+), 61 deletions(-)

doc/docgen.zig-2
...@@ -954,8 +954,6 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok...@@ -954,8 +954,6 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
954 .AngleBracketAngleBracketRight,954 .AngleBracketAngleBracketRight,
955 .AngleBracketAngleBracketRightEqual,955 .AngleBracketAngleBracketRightEqual,
956 .Tilde,956 .Tilde,
957 .BracketStarBracket,
958 .BracketStarCBracket,
959 => try writeEscaped(out, src[token.start..token.end]),957 => try writeEscaped(out, src[token.start..token.end]),
960958
961 .Invalid, .Invalid_ampersands => return parseError(959 .Invalid, .Invalid_ampersands => return parseError(
doc/langref.html.in+12-28
...@@ -563,7 +563,7 @@ const mem = @import("std").mem;...@@ -563,7 +563,7 @@ const mem = @import("std").mem;
563563
564test "string literals" {564test "string literals" {
565 const bytes = "hello";565 const bytes = "hello";
566 assert(@typeOf(bytes) == *const [5]null u8);566 assert(@typeOf(bytes) == *const [5:0]u8);
567 assert(bytes.len == 5);567 assert(bytes.len == 5);
568 assert(bytes[1] == 'e');568 assert(bytes[1] == 'e');
569 assert(bytes[5] == 0);569 assert(bytes[5] == 0);
...@@ -1795,7 +1795,7 @@ test "null terminated array" {...@@ -1795,7 +1795,7 @@ test "null terminated array" {
17951795
1796 assert(@typeOf(array) == [4:0]u8);1796 assert(@typeOf(array) == [4:0]u8);
1797 assert(array.len == 4);1797 assert(array.len == 4);
1798 assert(slice[4] == 0);1798 assert(array[4] == 0);
1799}1799}
1800 {#code_end#}1800 {#code_end#}
1801 {#see_also|Sentinel-Terminated Pointers|Sentinel-Terminated Slices#}1801 {#see_also|Sentinel-Terminated Pointers|Sentinel-Terminated Slices#}
...@@ -4863,7 +4863,7 @@ const assert = std.debug.assert;...@@ -4863,7 +4863,7 @@ const assert = std.debug.assert;
4863const mem = std.mem;4863const mem = std.mem;
48644864
4865test "cast *[1][*]const u8 to [*]const ?[*]const u8" {4865test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
4866 const window_name = [1][*]const u8{c"window name"};4866 const window_name = [1][*]const u8{"window name"};
4867 const x: [*]const ?[*]const u8 = &window_name;4867 const x: [*]const ?[*]const u8 = &window_name;
4868 assert(mem.eql(u8, std.mem.toSliceConst(u8, x[0].?), "window name"));4868 assert(mem.eql(u8, std.mem.toSliceConst(u8, x[0].?), "window name"));
4869}4869}
...@@ -4905,7 +4905,7 @@ test "float widening" {...@@ -4905,7 +4905,7 @@ test "float widening" {
4905 {#code_end#}4905 {#code_end#}
4906 {#header_close#}4906 {#header_close#}
4907 {#header_open|Type Coercion: Arrays and Pointers#}4907 {#header_open|Type Coercion: Arrays and Pointers#}
4908 {#code_begin|test#}4908 {#code_begin|test|coerce_arrays_and_ptrs#}
4909const std = @import("std");4909const std = @import("std");
4910const assert = std.debug.assert;4910const assert = std.debug.assert;
49114911
...@@ -4944,7 +4944,7 @@ test "[N]T to ?[]const T" {...@@ -4944,7 +4944,7 @@ test "[N]T to ?[]const T" {
49444944
4945// In this cast, the array length becomes the slice length.4945// In this cast, the array length becomes the slice length.
4946test "*[N]T to []T" {4946test "*[N]T to []T" {
4947 var buf: [5]u8 = "hello";4947 var buf: [5]u8 = "hello".*;
4948 const x: []u8 = &buf;4948 const x: []u8 = &buf;
4949 assert(std.mem.eql(u8, x, "hello"));4949 assert(std.mem.eql(u8, x, "hello"));
49504950
...@@ -4956,7 +4956,7 @@ test "*[N]T to []T" {...@@ -4956,7 +4956,7 @@ test "*[N]T to []T" {
4956// Single-item pointers to arrays can be coerced to4956// Single-item pointers to arrays can be coerced to
4957// unknown length pointers.4957// unknown length pointers.
4958test "*[N]T to [*]T" {4958test "*[N]T to [*]T" {
4959 var buf: [5]u8 = "hello";4959 var buf: [5]u8 = "hello".*;
4960 const x: [*]u8 = &buf;4960 const x: [*]u8 = &buf;
4961 assert(x[4] == 'o');4961 assert(x[4] == 'o');
4962 // x[5] would be an uncaught out of bounds pointer dereference!4962 // x[5] would be an uncaught out of bounds pointer dereference!
...@@ -4964,7 +4964,7 @@ test "*[N]T to [*]T" {...@@ -4964,7 +4964,7 @@ test "*[N]T to [*]T" {
49644964
4965// Likewise, it works when the destination type is an optional.4965// Likewise, it works when the destination type is an optional.
4966test "*[N]T to ?[*]T" {4966test "*[N]T to ?[*]T" {
4967 var buf: [5]u8 = "hello";4967 var buf: [5]u8 = "hello".*;
4968 const x: ?[*]u8 = &buf;4968 const x: ?[*]u8 = &buf;
4969 assert(x.?[4] == 'o');4969 assert(x.?[4] == 'o');
4970}4970}
...@@ -5135,7 +5135,7 @@ test "coercion of zero bit types" {...@@ -5135,7 +5135,7 @@ test "coercion of zero bit types" {
5135 This kind of type resolution chooses a type that all peer types can coerce into. Here are5135 This kind of type resolution chooses a type that all peer types can coerce into. Here are
5136 some examples:5136 some examples:
5137 </p>5137 </p>
5138 {#code_begin|test#}5138 {#code_begin|test|peer_type_resolution#}
5139const std = @import("std");5139const std = @import("std");
5140const assert = std.debug.assert;5140const assert = std.debug.assert;
5141const mem = std.mem;5141const mem = std.mem;
...@@ -5202,13 +5202,13 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {...@@ -5202,13 +5202,13 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
5202}5202}
5203test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {5203test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
5204 {5204 {
5205 var data = "hi";5205 var data = "hi".*;
5206 const slice = data[0..];5206 const slice = data[0..];
5207 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);5207 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
5208 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);5208 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
5209 }5209 }
5210 comptime {5210 comptime {
5211 var data = "hi";5211 var data = "hi".*;
5212 const slice = data[0..];5212 const slice = data[0..];
5213 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);5213 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
5214 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);5214 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
...@@ -8673,7 +8673,7 @@ pub fn main() void {...@@ -8673,7 +8673,7 @@ pub fn main() void {
8673 <p>At compile-time:</p>8673 <p>At compile-time:</p>
8674 {#code_begin|test_err|index 5 outside array of size 5#}8674 {#code_begin|test_err|index 5 outside array of size 5#}
8675comptime {8675comptime {
8676 const array = "hello";8676 const array: [5]u8 = "hello".*;
8677 const garbage = array[5];8677 const garbage = array[5];
8678}8678}
8679 {#code_end#}8679 {#code_end#}
...@@ -9649,22 +9649,6 @@ test "assert in release fast mode" {...@@ -9649,22 +9649,6 @@ test "assert in release fast mode" {
9649 </ul>9649 </ul>
9650 {#see_also|Primitive Types#}9650 {#see_also|Primitive Types#}
9651 {#header_close#}9651 {#header_close#}
9652 {#header_open|C String Literals#}
9653 {#code_begin|exe#}
9654 {#link_libc#}
9655extern fn puts([*]const u8) void;
9656
9657pub fn main() void {
9658 puts(c"this has a null terminator");
9659 puts(
9660 c\\and so
9661 c\\does this
9662 c\\multiline C string literal
9663 );
9664}
9665 {#code_end#}
9666 {#see_also|String Literals and Character Literals#}
9667 {#header_close#}
96689652
9669 {#header_open|Import from C Header File#}9653 {#header_open|Import from C Header File#}
9670 <p>9654 <p>
...@@ -9679,7 +9663,7 @@ const c = @cImport({...@@ -9679,7 +9663,7 @@ const c = @cImport({
9679 @cInclude("stdio.h");9663 @cInclude("stdio.h");
9680});9664});
9681pub fn main() void {9665pub fn main() void {
9682 _ = c.printf(c"hello\n");9666 _ = c.printf("hello\n");
9683}9667}
9684 {#code_end#}9668 {#code_end#}
9685 <p>9669 <p>
src/analyze.cpp+1-17
...@@ -496,7 +496,7 @@ static void append_ptr_type_attrs(Buf *type_name, ZigType *ptr_type) {...@@ -496,7 +496,7 @@ static void append_ptr_type_attrs(Buf *type_name, ZigType *ptr_type) {
496 } else if (ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE) {496 } else if (ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE) {
497 buf_appendf(type_name, ":%" PRIu32, ptr_type->data.pointer.vector_index);497 buf_appendf(type_name, ":%" PRIu32, ptr_type->data.pointer.vector_index);
498 }498 }
499 buf_appendf(type_name, ")");499 buf_appendf(type_name, ") ");
500 }500 }
501 buf_appendf(type_name, "%s%s%s", const_str, volatile_str, allow_zero_str);501 buf_appendf(type_name, "%s%s%s", const_str, volatile_str, allow_zero_str);
502 if (ptr_type->data.pointer.inferred_struct_field != nullptr) {502 if (ptr_type->data.pointer.inferred_struct_field != nullptr) {
...@@ -861,22 +861,6 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {...@@ -861,22 +861,6 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
861 entry->data.structure.fields[slice_len_index]->gen_index = 0;861 entry->data.structure.fields[slice_len_index]->gen_index = 0;
862 }862 }
863863
864 ZigType *child_type = ptr_type->data.pointer.child_type;
865 if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile ||
866 ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.allow_zero)
867 {
868 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
869 PtrLenUnknown, 0, 0, 0, false);
870 ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type);
871
872 entry->size_in_bits = peer_slice_type->size_in_bits;
873 entry->abi_size = peer_slice_type->abi_size;
874 entry->abi_align = peer_slice_type->abi_align;
875
876 *parent_pointer = entry;
877 return entry;
878 }
879
880 if (type_has_bits(ptr_type)) {864 if (type_has_bits(ptr_type)) {
881 entry->size_in_bits = ptr_type->size_in_bits + g->builtin_types.entry_usize->size_in_bits;865 entry->size_in_bits = ptr_type->size_in_bits + g->builtin_types.entry_usize->size_in_bits;
882 entry->abi_size = ptr_type->abi_size + g->builtin_types.entry_usize->abi_size;866 entry->abi_size = ptr_type->abi_size + g->builtin_types.entry_usize->abi_size;
src/codegen.cpp+3-2
...@@ -3752,7 +3752,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI...@@ -3752,7 +3752,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
3752 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);3752 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
3753 assert(array_type->data.structure.is_slice);3753 assert(array_type->data.structure.is_slice);
37543754
3755 ZigType *ptr_type = instruction->base.value.type;3755 ZigType *ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry;
3756 if (!type_has_bits(ptr_type)) {3756 if (!type_has_bits(ptr_type)) {
3757 if (safety_check_on) {3757 if (safety_check_on) {
3758 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMIntegerTypeKind);3758 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMIntegerTypeKind);
...@@ -3769,7 +3769,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI...@@ -3769,7 +3769,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
3769 assert(len_index != SIZE_MAX);3769 assert(len_index != SIZE_MAX);
3770 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)len_index, "");3770 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)len_index, "");
3771 LLVMValueRef len = gen_load_untyped(g, len_ptr, 0, false, "");3771 LLVMValueRef len = gen_load_untyped(g, len_ptr, 0, false, "");
3772 add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, len);3772 LLVMIntPredicate upper_op = (ptr_type->data.pointer.sentinel != nullptr) ? LLVMIntULE : LLVMIntULT;
3773 add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, upper_op, len);
3773 }3774 }
37743775
3775 size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index;3776 size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index;
src/ir.cpp+15-4
...@@ -18244,13 +18244,16 @@ static IrInstruction *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructi...@@ -18244,13 +18244,16 @@ static IrInstruction *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructi
1824418244
18245static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align) {18245static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align) {
18246 assert(ptr_type->id == ZigTypeIdPointer);18246 assert(ptr_type->id == ZigTypeIdPointer);
18247 return get_pointer_to_type_extra(g,18247 return get_pointer_to_type_extra2(g,
18248 ptr_type->data.pointer.child_type,18248 ptr_type->data.pointer.child_type,
18249 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,18249 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
18250 ptr_type->data.pointer.ptr_len,18250 ptr_type->data.pointer.ptr_len,
18251 new_align,18251 new_align,
18252 ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,18252 ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,
18253 ptr_type->data.pointer.allow_zero);18253 ptr_type->data.pointer.allow_zero,
18254 ptr_type->data.pointer.vector_index,
18255 ptr_type->data.pointer.inferred_struct_field,
18256 ptr_type->data.pointer.sentinel);
18254}18257}
1825518258
18256static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align) {18259static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align) {
...@@ -18595,8 +18598,11 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -18595,8 +18598,11 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
18595 ConstExprValue *len_field = array_ptr_val->data.x_struct.fields[slice_len_index];18598 ConstExprValue *len_field = array_ptr_val->data.x_struct.fields[slice_len_index];
18596 IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type);18599 IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type);
18597 ConstExprValue *out_val = &result->value;18600 ConstExprValue *out_val = &result->value;
18601 ZigType *slice_ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry;
18598 uint64_t slice_len = bigint_as_u64(&len_field->data.x_bigint);18602 uint64_t slice_len = bigint_as_u64(&len_field->data.x_bigint);
18599 if (index >= slice_len) {18603 uint64_t full_slice_len = slice_len +
18604 ((slice_ptr_type->data.pointer.sentinel != nullptr) ? 1 : 0);
18605 if (index >= full_slice_len) {
18600 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,18606 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
18601 buf_sprintf("index %" ZIG_PRI_u64 " outside slice of size %" ZIG_PRI_u64,18607 buf_sprintf("index %" ZIG_PRI_u64 " outside slice of size %" ZIG_PRI_u64,
18602 index, slice_len));18608 index, slice_len));
...@@ -18615,8 +18621,13 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -18615,8 +18621,13 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
18615 {18621 {
18616 size_t offset = ptr_field->data.x_ptr.data.base_array.elem_index;18622 size_t offset = ptr_field->data.x_ptr.data.base_array.elem_index;
18617 uint64_t new_index = offset + index;18623 uint64_t new_index = offset + index;
18618 ir_assert(new_index < ptr_field->data.x_ptr.data.base_array.array_val->type->data.array.len,18624 if (ptr_field->data.x_ptr.data.base_array.array_val->data.x_array.special !=
18625 ConstArraySpecialBuf)
18626 {
18627 ir_assert(new_index <
18628 ptr_field->data.x_ptr.data.base_array.array_val->type->data.array.len,
18619 &elem_ptr_instruction->base);18629 &elem_ptr_instruction->base);
18630 }
18620 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;18631 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
18621 out_val->data.x_ptr.data.base_array.array_val =18632 out_val->data.x_ptr.data.base_array.array_val =
18622 ptr_field->data.x_ptr.data.base_array.array_val;18633 ptr_field->data.x_ptr.data.base_array.array_val;
test/compile_errors.zig+9-8
...@@ -70,14 +70,14 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -70,14 +70,14 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
7070
71 cases.add(71 cases.add(
72 "disallow coercion from non-null-terminated pointer to null-terminated pointer",72 "disallow coercion from non-null-terminated pointer to null-terminated pointer",
73 \\extern fn puts(s: [*]null const u8) c_int;73 \\extern fn puts(s: [*:0]const u8) c_int;
74 \\pub fn main() void {74 \\pub fn main() void {
75 \\ const no_zero_array = [_]u8{'h', 'e', 'l', 'l', 'o'};75 \\ const no_zero_array = [_]u8{'h', 'e', 'l', 'l', 'o'};
76 \\ const no_zero_ptr: [*]const u8 = &no_zero_array;76 \\ const no_zero_ptr: [*]const u8 = &no_zero_array;
77 \\ _ = puts(no_zero_ptr);77 \\ _ = puts(no_zero_ptr);
78 \\}78 \\}
79 ,79 ,
80 "tmp.zig:5:14: error: expected type '[*]null const u8', found '[*]const u8'",80 "tmp.zig:5:14: error: expected type '[*:0]const u8', found '[*]const u8'",
81 );81 );
8282
83 cases.add(83 cases.add(
...@@ -784,7 +784,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -784,7 +784,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
784 \\ strValue = strValue orelse "";784 \\ strValue = strValue orelse "";
785 \\}785 \\}
786 ,786 ,
787 "tmp.zig:3:32: error: expected type '[*c]u8', found '*const [0]null u8'",787 "tmp.zig:3:32: error: expected type '[*c]u8', found '*const [0:0]u8'",
788 "tmp.zig:3:32: note: cast discards const qualifier",788 "tmp.zig:3:32: note: cast discards const qualifier",
789 );789 );
790790
...@@ -2442,12 +2442,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2442,12 +2442,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2442 );2442 );
24432443
2444 cases.add(2444 cases.add(
2445 "var not allowed in structs",2445 "var makes structs required to be comptime known",
2446 \\export fn entry() void {2446 \\export fn entry() void {
2447 \\ var s = (struct{v: var}){.v=@as(i32, 10)};2447 \\ const S = struct{v: var};
2448 \\ var s = S{.v=@as(i32, 10)};
2448 \\}2449 \\}
2449 ,2450 ,
2450 "tmp.zig:2:23: error: invalid token: 'var'",2451 "tmp.zig:3:4: error: variable of type 'S' must be const or comptime",
2451 );2452 );
24522453
2453 cases.add(2454 cases.add(
...@@ -3357,7 +3358,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3357,7 +3358,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3357 \\ return a;3358 \\ return a;
3358 \\}3359 \\}
3359 ,3360 ,
3360 "tmp.zig:3:12: error: expected type 'i32', found '*const [1]null u8'",3361 "tmp.zig:3:12: error: expected type 'i32', found '*const [1:0]u8'",
3361 );3362 );
33623363
3363 cases.add(3364 cases.add(
...@@ -6212,7 +6213,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -6212,7 +6213,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
6212 \\}6213 \\}
6213 \\pub extern fn foo(format: *const u8, ...) void;6214 \\pub extern fn foo(format: *const u8, ...) void;
6214 ,6215 ,
6215 "tmp.zig:2:16: error: expected type '*const u8', found '[5]null u8'",6216 "tmp.zig:2:16: error: expected type '*const u8', found '[5:0]u8'",
6216 );6217 );
62176218
6218 cases.add(6219 cases.add(
test/stage1/behavior/slice.zig+13
...@@ -65,3 +65,16 @@ test "slice type with custom alignment" {...@@ -65,3 +65,16 @@ test "slice type with custom alignment" {
65 slice[1].anything = 42;65 slice[1].anything = 42;
66 expect(array[1].anything == 42);66 expect(array[1].anything == 42);
67}67}
68
69test "access len index of sentinel-terminated slice" {
70 const S = struct {
71 fn doTheTest() void {
72 var slice: [:0]const u8 = "hello";
73
74 expect(slice.len == 5);
75 expect(slice[5] == 0);
76 }
77 };
78 S.doTheTest();
79 comptime S.doTheTest();
80}