diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index d00568e49f..e1fe07a57c 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -1509,6 +1509,8 @@ test "zig fmt: error set declaration" { \\const Error = error{OutOfMemory}; \\const Error = error{}; \\ + \\const Error = error{ OutOfMemory, OutOfTime }; + \\ ); } diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index a3a72fb23f..23dc9e02ac 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -1268,25 +1268,51 @@ fn renderExpression( } try renderToken(tree, stream, err_set_decl.error_token, indent, start_col, Space.None); // error - try renderToken(tree, stream, lbrace, indent, start_col, Space.Newline); // { - const new_indent = indent + indent_delta; - var it = err_set_decl.decls.iterator(0); - while (it.next()) |node| { - try stream.writeByteNTimes(' ', new_indent); + const src_has_trailing_comma = blk: { + const maybe_comma = tree.prevToken(err_set_decl.rbrace_token); + break :blk tree.tokens.at(maybe_comma).id == .Comma; + }; - if (it.peek()) |next_node| { - try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.None); - try renderToken(tree, stream, tree.nextToken(node.*.lastToken()), new_indent, start_col, Space.Newline); // , + if (src_has_trailing_comma) { + try renderToken(tree, stream, lbrace, indent, start_col, Space.Newline); // { + const new_indent = indent + indent_delta; - try renderExtraNewline(tree, stream, start_col, next_node.*); - } else { - try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.Comma); + var it = err_set_decl.decls.iterator(0); + while (it.next()) |node| { + try stream.writeByteNTimes(' ', new_indent); + + if (it.peek()) |next_node| { + try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.None); + try renderToken(tree, stream, tree.nextToken(node.*.lastToken()), new_indent, start_col, Space.Newline); // , + + try renderExtraNewline(tree, stream, start_col, next_node.*); + } else { + try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.Comma); + } } - } - try stream.writeByteNTimes(' ', indent); - return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space); // } + try stream.writeByteNTimes(' ', indent); + return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space); // } + } else { + try renderToken(tree, stream, lbrace, indent, start_col, Space.Space); // { + + var it = err_set_decl.decls.iterator(0); + while (it.next()) |node| { + if (it.peek()) |next_node| { + try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.None); + + const comma_token = tree.nextToken(node.*.lastToken()); + assert(tree.tokens.at(comma_token).id == .Comma); + try renderToken(tree, stream, comma_token, indent, start_col, Space.Space); // , + try renderExtraNewline(tree, stream, start_col, next_node.*); + } else { + try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.Space); + } + } + + return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space); // } + } }, .ErrorTag => { @@ -1589,8 +1615,7 @@ fn renderExpression( } } else { var it = switch_case.items.iterator(0); - while (true) { - const node = it.next().?; + while (it.next()) |node| { if (it.peek()) |next_node| { try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.None); @@ -1601,7 +1626,6 @@ fn renderExpression( } else { try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.Comma); try stream.writeByteNTimes(' ', indent); - break; } } } diff --git a/src/analyze.cpp b/src/analyze.cpp index 33d28269b9..fbd7d85ac1 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -803,13 +803,7 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, Zi } buf_appendf(&entry->name, "]%s", buf_ptr(&child_type->name)); - size_t full_array_size; - if (array_size == 0) { - full_array_size = 0; - } else { - full_array_size = array_size + ((sentinel != nullptr) ? 1 : 0); - } - + size_t full_array_size = array_size + ((sentinel != nullptr) ? 1 : 0); entry->size_in_bits = child_type->size_in_bits * full_array_size; entry->abi_align = child_type->abi_align; entry->abi_size = child_type->abi_size * full_array_size; @@ -1197,7 +1191,8 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent LazyValueArrayType *lazy_array_type = reinterpret_cast(type_val->data.x_lazy); - if (lazy_array_type->length < 1) { + // The sentinel counts as an extra element + if (lazy_array_type->length == 0 && lazy_array_type->sentinel == nullptr) { *is_zero_bits = true; return ErrorNone; } @@ -1452,7 +1447,7 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV case LazyValueIdArrayType: { LazyValueArrayType *lazy_array_type = reinterpret_cast(type_val->data.x_lazy); - if (lazy_array_type->length < 1) + if (lazy_array_type->length == 0) return OnePossibleValueYes; return type_val_resolve_has_one_possible_value(g, lazy_array_type->elem_type->value); } diff --git a/src/codegen.cpp b/src/codegen.cpp index dc6fe04cb4..75f3223250 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3584,7 +3584,9 @@ static bool value_is_all_undef(CodeGen *g, ZigValue *const_val) { } return true; } else if (const_val->type->id == ZigTypeIdArray) { - return value_is_all_undef_array(g, const_val, const_val->type->data.array.len); + const size_t full_len = const_val->type->data.array.len + + (const_val->type->data.array.sentinel != nullptr); + return value_is_all_undef_array(g, const_val, full_len); } else if (const_val->type->id == ZigTypeIdVector) { return value_is_all_undef_array(g, const_val, const_val->type->data.vector.len); } else { diff --git a/test/stage1/behavior/array.zig b/test/stage1/behavior/array.zig index da56864cc9..1f2d4a2f6b 100644 --- a/test/stage1/behavior/array.zig +++ b/test/stage1/behavior/array.zig @@ -376,3 +376,23 @@ test "type deduction for array subscript expression" { S.doTheTest(); comptime S.doTheTest(); } + +test "sentinel element count towards the ABI size calculation" { + const S = struct { + fn doTheTest() void { + const T = packed struct { + fill_pre: u8 = 0x55, + data: [0:0]u8 = undefined, + fill_post: u8 = 0xAA, + }; + var x = T{}; + var as_slice = mem.asBytes(&x); + expectEqual(@as(usize, 3), as_slice.len); + expectEqual(@as(u8, 0x55), as_slice[0]); + expectEqual(@as(u8, 0xAA), as_slice[2]); + } + }; + + S.doTheTest(); + comptime S.doTheTest(); +}