authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-12 01:40:31+00:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-11-12 01:40:31+00:00
log5502160bd23f14b91ac2bd3726a93bdd0b40cc53
tree81ced0f54f4c02eb7fd3bdd5d3d1248014f356a6
parentae0a219d1f5495acc4d82421fa24d84186c2a40d
parent0c315e7f7613b085a203e9c94d222e846b5b9e46
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #3652 from ziglang/anon-container-lit

implement anonymous struct literals and anonymous list literals

18 files changed, 783 insertions(+), 243 deletions(-)

doc/langref.html.in+112-1
......@@ -1734,6 +1734,43 @@ test "array initialization with function calls" {
17341734 {#code_end#}
17351735 {#see_also|for|Slices#}
17361736
1737 {#header_open|Anonymous List Literals#}
1738 <p>Similar to {#link|Enum Literals#} and {#link|Anonymous Struct Literals#}
1739 the type can be omitted from array literals:</p>
1740 {#code_begin|test|anon_list#}
1741const std = @import("std");
1742const assert = std.debug.assert;
1743
1744test "anonymous list literal syntax" {
1745 var array: [4]u8 = .{11, 22, 33, 44};
1746 assert(array[0] == 11);
1747 assert(array[1] == 22);
1748 assert(array[2] == 33);
1749 assert(array[3] == 44);
1750}
1751 {#code_end#}
1752 <p>
1753 If there is no type in the result location then an anonymous list literal actually
1754 turns into a {#link|struct#} with numbered field names:
1755 </p>
1756 {#code_begin|test|infer_list_literal#}
1757const std = @import("std");
1758const assert = std.debug.assert;
1759
1760test "fully anonymous list literal" {
1761 dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi"});
1762}
1763
1764fn dump(args: var) void {
1765 assert(args.@"0" == 1234);
1766 assert(args.@"1" == 12.34);
1767 assert(args.@"2");
1768 assert(args.@"3"[0] == 'h');
1769 assert(args.@"3"[1] == 'i');
1770}
1771 {#code_end#}
1772 {#header_close#}
1773
17371774 {#header_open|Multidimensional Arrays#}
17381775 <p>
17391776 Mutlidimensional arrays can be created by nesting arrays:
......@@ -2526,7 +2563,8 @@ test "overaligned pointer to packed struct" {
25262563 Don't worry, there will be a good solution for this use case in zig.
25272564 </p>
25282565 {#header_close#}
2529 {#header_open|struct Naming#}
2566
2567 {#header_open|Struct Naming#}
25302568 <p>Since all structs are anonymous, Zig infers the type name based on a few rules.</p>
25312569 <ul>
25322570 <li>If the struct is in the initialization expression of a variable, it gets named after
......@@ -2552,6 +2590,53 @@ fn List(comptime T: type) type {
25522590}
25532591 {#code_end#}
25542592 {#header_close#}
2593
2594 {#header_open|Anonymous Struct Literals#}
2595 <p>
2596 Zig allows omitting the struct type of a literal. When the result is {#link|coerced|Type Coercion#},
2597 the struct literal will directly instantiate the result location, with no copy:
2598 </p>
2599 {#code_begin|test|struct_result#}
2600const std = @import("std");
2601const assert = std.debug.assert;
2602
2603const Point = struct {x: i32, y: i32};
2604
2605test "anonymous struct literal" {
2606 var pt: Point = .{
2607 .x = 13,
2608 .y = 67,
2609 };
2610 assert(pt.x == 13);
2611 assert(pt.y == 67);
2612}
2613 {#code_end#}
2614 <p>
2615 The struct type can be inferred. Here the result location does not include a type, and
2616 so Zig infers the type:
2617 </p>
2618 {#code_begin|test|struct_anon#}
2619const std = @import("std");
2620const assert = std.debug.assert;
2621
2622test "fully anonymous struct" {
2623 dump(.{
2624 .int = @as(u32, 1234),
2625 .float = @as(f64, 12.34),
2626 .b = true,
2627 .s = "hi",
2628 });
2629}
2630
2631fn dump(args: var) void {
2632 assert(args.int == 1234);
2633 assert(args.float == 12.34);
2634 assert(args.b);
2635 assert(args.s[0] == 'h');
2636 assert(args.s[1] == 'i');
2637}
2638 {#code_end#}
2639 {#header_close#}
25552640 {#see_also|comptime|@fieldParentPtr#}
25562641 {#header_close#}
25572642 {#header_open|enum#}
......@@ -2906,6 +2991,32 @@ test "@tagName" {
29062991 <p>A {#syntax#}packed union{#endsyntax#} has well-defined in-memory layout and is eligible
29072992 to be in a {#link|packed struct#}.
29082993 {#header_close#}
2994
2995 {#header_open|Anonymous Union Literals#}
2996 <p>{#link|Anonymous Struct Literals#} syntax can be used to initialize unions without specifying
2997 the type:</p>
2998 {#code_begin|test|anon_union#}
2999const std = @import("std");
3000const assert = std.debug.assert;
3001
3002const Number = union {
3003 int: i32,
3004 float: f64,
3005};
3006
3007test "anonymous union literal syntax" {
3008 var i: Number = .{.int = 42};
3009 var f = makeNumber();
3010 assert(i.int == 42);
3011 assert(f.float == 12.34);
3012}
3013
3014fn makeNumber() Number {
3015 return .{.float = 12.34};
3016}
3017 {#code_end#}
3018 {#header_close#}
3019
29093020 {#header_close#}
29103021
29113022 {#header_open|blocks#}
lib/std/builtin.zig+2-31
......@@ -90,40 +90,11 @@ pub const Mode = enum {
9090 ReleaseSmall,
9191};
9292
93/// This data structure is used by the Zig language code generation and
94/// therefore must be kept in sync with the compiler implementation.
95pub const TypeId = enum {
96 Type,
97 Void,
98 Bool,
99 NoReturn,
100 Int,
101 Float,
102 Pointer,
103 Array,
104 Struct,
105 ComptimeFloat,
106 ComptimeInt,
107 Undefined,
108 Null,
109 Optional,
110 ErrorUnion,
111 ErrorSet,
112 Enum,
113 Union,
114 Fn,
115 BoundFn,
116 ArgTuple,
117 Opaque,
118 Frame,
119 AnyFrame,
120 Vector,
121 EnumLiteral,
122};
93pub const TypeId = @TagType(TypeInfo);
12394
12495/// This data structure is used by the Zig language code generation and
12596/// therefore must be kept in sync with the compiler implementation.
126pub const TypeInfo = union(TypeId) {
97pub const TypeInfo = union(enum) {
12798 Type: void,
12899 Void: void,
129100 Bool: void,
lib/std/zig/ast.zig+17-4
......@@ -1648,10 +1648,15 @@ pub const Node = struct {
16481648
16491649 pub const SuffixOp = struct {
16501650 base: Node,
1651 lhs: *Node,
1651 lhs: Lhs,
16521652 op: Op,
16531653 rtoken: TokenIndex,
16541654
1655 pub const Lhs = union(enum) {
1656 node: *Node,
1657 dot: TokenIndex,
1658 };
1659
16551660 pub const Op = union(enum) {
16561661 Call: Call,
16571662 ArrayAccess: *Node,
......@@ -1679,8 +1684,13 @@ pub const Node = struct {
16791684 pub fn iterate(self: *SuffixOp, index: usize) ?*Node {
16801685 var i = index;
16811686
1682 if (i < 1) return self.lhs;
1683 i -= 1;
1687 switch (self.lhs) {
1688 .node => |node| {
1689 if (i == 0) return node;
1690 i -= 1;
1691 },
1692 .dot => {},
1693 }
16841694
16851695 switch (self.op) {
16861696 .Call => |*call_info| {
......@@ -1721,7 +1731,10 @@ pub const Node = struct {
17211731 .Call => |*call_info| if (call_info.async_token) |async_token| return async_token,
17221732 else => {},
17231733 }
1724 return self.lhs.firstToken();
1734 switch (self.lhs) {
1735 .node => |node| return node.firstToken(),
1736 .dot => |dot| return dot,
1737 }
17251738 }
17261739
17271740 pub fn lastToken(self: *const SuffixOp) TokenIndex {
lib/std/zig/parse.zig+32-20
......@@ -1026,16 +1026,16 @@ fn parseWhileExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
10261026/// CurlySuffixExpr <- TypeExpr InitList?
10271027fn parseCurlySuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
10281028 const type_expr = (try parseTypeExpr(arena, it, tree)) orelse return null;
1029 const init_list = (try parseInitList(arena, it, tree)) orelse return type_expr;
1030 init_list.cast(Node.SuffixOp).?.lhs = type_expr;
1031 return init_list;
1029 const suffix_op = (try parseInitList(arena, it, tree)) orelse return type_expr;
1030 suffix_op.lhs.node = type_expr;
1031 return &suffix_op.base;
10321032}
10331033
10341034/// InitList
10351035/// <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE
10361036/// / LBRACE Expr (COMMA Expr)* COMMA? RBRACE
10371037/// / LBRACE RBRACE
1038fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1038fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.SuffixOp {
10391039 const lbrace = eatToken(it, .LBrace) orelse return null;
10401040 var init_list = Node.SuffixOp.Op.InitList.init(arena);
10411041
......@@ -1064,11 +1064,11 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
10641064 const node = try arena.create(Node.SuffixOp);
10651065 node.* = Node.SuffixOp{
10661066 .base = Node{ .id = .SuffixOp },
1067 .lhs = undefined, // set by caller
1067 .lhs = .{.node = undefined}, // set by caller
10681068 .op = op,
10691069 .rtoken = try expectToken(it, tree, .RBrace),
10701070 };
1071 return &node.base;
1071 return node;
10721072}
10731073
10741074/// TypeExpr <- PrefixTypeOp* ErrorUnionExpr
......@@ -1117,7 +1117,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
11171117
11181118 while (try parseSuffixOp(arena, it, tree)) |node| {
11191119 switch (node.id) {
1120 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res,
1120 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res},
11211121 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,
11221122 else => unreachable,
11231123 }
......@@ -1133,7 +1133,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
11331133 const node = try arena.create(Node.SuffixOp);
11341134 node.* = Node.SuffixOp{
11351135 .base = Node{ .id = .SuffixOp },
1136 .lhs = res,
1136 .lhs = .{.node = res},
11371137 .op = Node.SuffixOp.Op{
11381138 .Call = Node.SuffixOp.Op.Call{
11391139 .params = params.list,
......@@ -1150,7 +1150,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
11501150 while (true) {
11511151 if (try parseSuffixOp(arena, it, tree)) |node| {
11521152 switch (node.id) {
1153 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res,
1153 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res},
11541154 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,
11551155 else => unreachable,
11561156 }
......@@ -1161,7 +1161,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
11611161 const call = try arena.create(Node.SuffixOp);
11621162 call.* = Node.SuffixOp{
11631163 .base = Node{ .id = .SuffixOp },
1164 .lhs = res,
1164 .lhs = .{.node = res},
11651165 .op = Node.SuffixOp.Op{
11661166 .Call = Node.SuffixOp.Op.Call{
11671167 .params = params.list,
......@@ -1215,7 +1215,7 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
12151215 return &node.base;
12161216 }
12171217 if (try parseContainerDecl(arena, it, tree)) |node| return node;
1218 if (try parseEnumLiteral(arena, it, tree)) |node| return node;
1218 if (try parseAnonLiteral(arena, it, tree)) |node| return node;
12191219 if (try parseErrorSetDecl(arena, it, tree)) |node| return node;
12201220 if (try parseFloatLiteral(arena, it, tree)) |node| return node;
12211221 if (try parseFnProto(arena, it, tree)) |node| return node;
......@@ -1494,16 +1494,28 @@ fn parseAsmExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
14941494}
14951495
14961496/// DOT IDENTIFIER
1497fn parseEnumLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1497fn parseAnonLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
14981498 const dot = eatToken(it, .Period) orelse return null;
1499 const name = try expectToken(it, tree, .Identifier);
1500 const node = try arena.create(Node.EnumLiteral);
1501 node.* = Node.EnumLiteral{
1502 .base = Node{ .id = .EnumLiteral },
1503 .dot = dot,
1504 .name = name,
1505 };
1506 return &node.base;
1499
1500 // anon enum literal
1501 if (eatToken(it, .Identifier)) |name| {
1502 const node = try arena.create(Node.EnumLiteral);
1503 node.* = Node.EnumLiteral{
1504 .base = Node{ .id = .EnumLiteral },
1505 .dot = dot,
1506 .name = name,
1507 };
1508 return &node.base;
1509 }
1510
1511 // anon container literal
1512 if (try parseInitList(arena, it, tree)) |node| {
1513 node.lhs = .{.dot = dot};
1514 return &node.base;
1515 }
1516
1517 putBackToken(it, dot);
1518 return null;
15071519}
15081520
15091521/// AsmOutput <- COLON AsmOutputList AsmInput?
lib/std/zig/parser_test.zig+17
......@@ -1,3 +1,20 @@
1test "zig fmt: anon struct literal syntax" {
2 try testCanonical(
3 \\const x = .{
4 \\ .a = b,
5 \\ .c = d,
6 \\};
7 \\
8 );
9}
10
11test "zig fmt: anon list literal syntax" {
12 try testCanonical(
13 \\const x = .{ a, b, c };
14 \\
15 );
16}
17
118test "zig fmt: async function" {
219 try testCanonical(
320 \\pub const Server = struct {
lib/std/zig/render.zig+42-15
......@@ -538,9 +538,9 @@ fn renderExpression(
538538 try renderToken(tree, stream, async_token, indent, start_col, Space.Space);
539539 }
540540
541 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
541 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None);
542542
543 const lparen = tree.nextToken(suffix_op.lhs.lastToken());
543 const lparen = tree.nextToken(suffix_op.lhs.node.lastToken());
544544
545545 if (call_info.params.len == 0) {
546546 try renderToken(tree, stream, lparen, indent, start_col, Space.None);
......@@ -598,7 +598,7 @@ fn renderExpression(
598598 const lbracket = tree.prevToken(index_expr.firstToken());
599599 const rbracket = tree.nextToken(index_expr.lastToken());
600600
601 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
601 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None);
602602 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
603603
604604 const starts_with_comment = tree.tokens.at(lbracket + 1).id == .LineComment;
......@@ -616,18 +616,18 @@ fn renderExpression(
616616 },
617617
618618 ast.Node.SuffixOp.Op.Deref => {
619 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
619 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None);
620620 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // .*
621621 },
622622
623623 ast.Node.SuffixOp.Op.UnwrapOptional => {
624 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
624 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None);
625625 try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, start_col, Space.None); // .
626626 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ?
627627 },
628628
629629 @TagType(ast.Node.SuffixOp.Op).Slice => |range| {
630 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
630 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None);
631631
632632 const lbracket = tree.prevToken(range.start.firstToken());
633633 const dotdot = tree.nextToken(range.start.lastToken());
......@@ -647,10 +647,16 @@ fn renderExpression(
647647 },
648648
649649 ast.Node.SuffixOp.Op.StructInitializer => |*field_inits| {
650 const lbrace = tree.nextToken(suffix_op.lhs.lastToken());
650 const lbrace = switch (suffix_op.lhs) {
651 .dot => |dot| tree.nextToken(dot),
652 .node => |node| tree.nextToken(node.lastToken()),
653 };
651654
652655 if (field_inits.len == 0) {
653 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
656 switch (suffix_op.lhs) {
657 .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None),
658 .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None),
659 }
654660 try renderToken(tree, stream, lbrace, indent + indent_delta, start_col, Space.None);
655661 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
656662 }
......@@ -691,7 +697,10 @@ fn renderExpression(
691697 break :blk;
692698 }
693699
694 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
700 switch (suffix_op.lhs) {
701 .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None),
702 .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None),
703 }
695704 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);
696705 try renderExpression(allocator, stream, tree, indent, start_col, &field_init.base, Space.Space);
697706 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
......@@ -699,7 +708,10 @@ fn renderExpression(
699708
700709 if (!src_has_trailing_comma and src_same_line and expr_outputs_one_line) {
701710 // render all on one line, no trailing comma
702 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
711 switch (suffix_op.lhs) {
712 .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None),
713 .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None),
714 }
703715 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);
704716
705717 var it = field_inits.iterator(0);
......@@ -719,7 +731,10 @@ fn renderExpression(
719731
720732 const new_indent = indent + indent_delta;
721733
722 try renderExpression(allocator, stream, tree, new_indent, start_col, suffix_op.lhs, Space.None);
734 switch (suffix_op.lhs) {
735 .dot => |dot| try renderToken(tree, stream, dot, new_indent, start_col, Space.None),
736 .node => |node| try renderExpression(allocator, stream, tree, new_indent, start_col, node, Space.None),
737 }
723738 try renderToken(tree, stream, lbrace, new_indent, start_col, Space.Newline);
724739
725740 var it = field_inits.iterator(0);
......@@ -743,23 +758,35 @@ fn renderExpression(
743758 },
744759
745760 ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| {
746 const lbrace = tree.nextToken(suffix_op.lhs.lastToken());
761 const lbrace = switch (suffix_op.lhs) {
762 .dot => |dot| tree.nextToken(dot),
763 .node => |node| tree.nextToken(node.lastToken()),
764 };
747765
748766 if (exprs.len == 0) {
749 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
767 switch (suffix_op.lhs) {
768 .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None),
769 .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None),
770 }
750771 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
751772 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
752773 }
753774 if (exprs.len == 1 and tree.tokens.at(exprs.at(0).*.lastToken() + 1).id == .RBrace) {
754775 const expr = exprs.at(0).*;
755776
756 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
777 switch (suffix_op.lhs) {
778 .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None),
779 .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None),
780 }
757781 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
758782 try renderExpression(allocator, stream, tree, indent, start_col, expr, Space.None);
759783 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
760784 }
761785
762 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
786 switch (suffix_op.lhs) {
787 .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None),
788 .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None),
789 }
763790
764791 // scan to find row size
765792 const maybe_row_size: ?usize = blk: {
src/all_types.hpp+17-3
......@@ -1187,10 +1187,22 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
11871187static const uint32_t VECTOR_INDEX_NONE = UINT32_MAX;
11881188static const uint32_t VECTOR_INDEX_RUNTIME = UINT32_MAX - 1;
11891189
1190struct InferredStructField {
1191 ZigType *inferred_struct_type;
1192 Buf *field_name;
1193};
1194
11901195struct ZigTypePointer {
11911196 ZigType *child_type;
11921197 ZigType *slice_parent;
11931198
1199 // Anonymous struct literal syntax uses this when the result location has
1200 // no type in it. This field is null if this pointer does not refer to
1201 // a field of a currently-being-inferred struct type.
1202 // When this is non-null, the pointer is pointing to the base of the inferred
1203 // struct.
1204 InferredStructField *inferred_struct_field;
1205
11941206 PtrLen ptr_len;
11951207 uint32_t explicit_alignment; // 0 means use ABI alignment
11961208
......@@ -1237,6 +1249,7 @@ struct TypeStructField {
12371249enum ResolveStatus {
12381250 ResolveStatusUnstarted,
12391251 ResolveStatusInvalid,
1252 ResolveStatusBeingInferred,
12401253 ResolveStatusZeroBitsKnown,
12411254 ResolveStatusAlignmentKnown,
12421255 ResolveStatusSizeKnown,
......@@ -1285,6 +1298,7 @@ struct ZigTypeStruct {
12851298 bool requires_comptime;
12861299 bool resolve_loop_flag_zero_bits;
12871300 bool resolve_loop_flag_other;
1301 bool is_inferred;
12881302};
12891303
12901304struct ZigTypeOptional {
......@@ -1741,6 +1755,7 @@ struct TypeId {
17411755 union {
17421756 struct {
17431757 ZigType *child_type;
1758 InferredStructField *inferred_struct_field;
17441759 PtrLen ptr_len;
17451760 uint32_t alignment;
17461761
......@@ -2812,7 +2827,7 @@ struct IrInstructionElemPtr {
28122827
28132828 IrInstruction *array_ptr;
28142829 IrInstruction *elem_index;
2815 IrInstruction *init_array_type;
2830 AstNode *init_array_type_source_node;
28162831 PtrLen ptr_len;
28172832 bool safety_check_on;
28182833};
......@@ -2909,11 +2924,11 @@ struct IrInstructionResizeSlice {
29092924struct IrInstructionContainerInitList {
29102925 IrInstruction base;
29112926
2912 IrInstruction *container_type;
29132927 IrInstruction *elem_type;
29142928 size_t item_count;
29152929 IrInstruction **elem_result_loc_list;
29162930 IrInstruction *result_loc;
2931 AstNode *init_array_type_source_node;
29172932};
29182933
29192934struct IrInstructionContainerInitFieldsField {
......@@ -2926,7 +2941,6 @@ struct IrInstructionContainerInitFieldsField {
29262941struct IrInstructionContainerInitFields {
29272942 IrInstruction base;
29282943
2929 IrInstruction *container_type;
29302944 size_t field_count;
29312945 IrInstructionContainerInitFieldsField *fields;
29322946 IrInstruction *result_loc;
src/analyze.cpp+91-40
......@@ -140,7 +140,6 @@ void init_scope(CodeGen *g, Scope *dest, ScopeId id, AstNode *source_node, Scope
140140static ScopeDecls *create_decls_scope(CodeGen *g, AstNode *node, Scope *parent, ZigType *container_type,
141141 ZigType *import, Buf *bare_name)
142142{
143 assert(node == nullptr || node->type == NodeTypeContainerDecl || node->type == NodeTypeFnCallExpr);
144143 ScopeDecls *scope = allocate<ScopeDecls>(1);
145144 init_scope(g, &scope->base, ScopeIdDecls, node, parent);
146145 scope->decl_table.init(4);
......@@ -346,6 +345,8 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
346345 switch (status) {
347346 case ResolveStatusInvalid:
348347 zig_unreachable();
348 case ResolveStatusBeingInferred:
349 zig_unreachable();
349350 case ResolveStatusUnstarted:
350351 case ResolveStatusZeroBitsKnown:
351352 return true;
......@@ -362,6 +363,8 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
362363 switch (status) {
363364 case ResolveStatusInvalid:
364365 zig_unreachable();
366 case ResolveStatusBeingInferred:
367 zig_unreachable();
365368 case ResolveStatusUnstarted:
366369 return true;
367370 case ResolveStatusZeroBitsKnown:
......@@ -483,7 +486,7 @@ ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {
483486ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const,
484487 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
485488 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero,
486 uint32_t vector_index)
489 uint32_t vector_index, InferredStructField *inferred_struct_field)
487490{
488491 assert(ptr_len != PtrLenC || allow_zero);
489492 assert(!type_is_invalid(child_type));
......@@ -506,7 +509,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
506509 TypeId type_id = {};
507510 ZigType **parent_pointer = nullptr;
508511 if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle ||
509 allow_zero || vector_index != VECTOR_INDEX_NONE)
512 allow_zero || vector_index != VECTOR_INDEX_NONE || inferred_struct_field != nullptr)
510513 {
511514 type_id.id = ZigTypeIdPointer;
512515 type_id.data.pointer.child_type = child_type;
......@@ -518,6 +521,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
518521 type_id.data.pointer.ptr_len = ptr_len;
519522 type_id.data.pointer.allow_zero = allow_zero;
520523 type_id.data.pointer.vector_index = vector_index;
524 type_id.data.pointer.inferred_struct_field = inferred_struct_field;
521525
522526 auto existing_entry = g->type_table.maybe_get(type_id);
523527 if (existing_entry)
......@@ -545,8 +549,15 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
545549 }
546550 buf_resize(&entry->name, 0);
547551 if (host_int_bytes == 0 && byte_alignment == 0 && vector_index == VECTOR_INDEX_NONE) {
548 buf_appendf(&entry->name, "%s%s%s%s%s",
549 star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
552 if (inferred_struct_field == nullptr) {
553 buf_appendf(&entry->name, "%s%s%s%s%s",
554 star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
555 } else {
556 buf_appendf(&entry->name, "(%s%s%s%s field '%s' of %s)",
557 star_str, const_str, volatile_str, allow_zero_str,
558 buf_ptr(inferred_struct_field->field_name),
559 buf_ptr(&inferred_struct_field->inferred_struct_type->name));
560 }
550561 } else if (host_int_bytes == 0 && vector_index == VECTOR_INDEX_NONE) {
551562 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
552563 const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
......@@ -603,6 +614,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
603614 entry->data.pointer.host_int_bytes = host_int_bytes;
604615 entry->data.pointer.allow_zero = allow_zero;
605616 entry->data.pointer.vector_index = vector_index;
617 entry->data.pointer.inferred_struct_field = inferred_struct_field;
606618
607619 if (parent_pointer) {
608620 *parent_pointer = entry;
......@@ -617,12 +629,12 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
617629 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero)
618630{
619631 return get_pointer_to_type_extra2(g, child_type, is_const, is_volatile, ptr_len,
620 byte_alignment, bit_offset_in_host, host_int_bytes, allow_zero, VECTOR_INDEX_NONE);
632 byte_alignment, bit_offset_in_host, host_int_bytes, allow_zero, VECTOR_INDEX_NONE, nullptr);
621633}
622634
623635ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) {
624636 return get_pointer_to_type_extra2(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0, false,
625 VECTOR_INDEX_NONE);
637 VECTOR_INDEX_NONE, nullptr);
626638}
627639
628640ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
......@@ -2079,7 +2091,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
20792091 }
20802092
20812093 assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0);
2082 assert(decl_node->type == NodeTypeContainerDecl);
2094 assert(decl_node->type == NodeTypeContainerDecl || decl_node->type == NodeTypeContainerInitExpr);
20832095
20842096 size_t field_count = struct_type->data.structure.src_field_count;
20852097
......@@ -2667,7 +2679,6 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
26672679 return ErrorNone;
26682680
26692681 AstNode *decl_node = struct_type->data.structure.decl_node;
2670 assert(decl_node->type == NodeTypeContainerDecl);
26712682
26722683 if (struct_type->data.structure.resolve_loop_flag_zero_bits) {
26732684 if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
......@@ -2678,29 +2689,46 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
26782689 }
26792690 return ErrorSemanticAnalyzeFail;
26802691 }
2681
26822692 struct_type->data.structure.resolve_loop_flag_zero_bits = true;
26832693
2684 assert(!struct_type->data.structure.fields);
2685 size_t field_count = decl_node->data.container_decl.fields.length;
2686 struct_type->data.structure.src_field_count = (uint32_t)field_count;
2687 struct_type->data.structure.fields = allocate<TypeStructField>(field_count);
2694 size_t field_count;
2695 if (decl_node->type == NodeTypeContainerDecl) {
2696 field_count = decl_node->data.container_decl.fields.length;
2697 struct_type->data.structure.src_field_count = (uint32_t)field_count;
2698
2699 src_assert(struct_type->data.structure.fields == nullptr, decl_node);
2700 struct_type->data.structure.fields = allocate<TypeStructField>(field_count);
2701 } else if (decl_node->type == NodeTypeContainerInitExpr) {
2702 src_assert(struct_type->data.structure.is_inferred, decl_node);
2703 src_assert(struct_type->data.structure.fields != nullptr, decl_node);
2704
2705 field_count = struct_type->data.structure.src_field_count;
2706 } else zig_unreachable();
2707
26882708 struct_type->data.structure.fields_by_name.init(field_count);
26892709
26902710 Scope *scope = &struct_type->data.structure.decls_scope->base;
26912711
26922712 size_t gen_field_index = 0;
26932713 for (size_t i = 0; i < field_count; i += 1) {
2694 AstNode *field_node = decl_node->data.container_decl.fields.at(i);
26952714 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
2696 type_struct_field->name = field_node->data.struct_field.name;
2697 type_struct_field->decl_node = field_node;
26982715
2699 if (field_node->data.struct_field.type == nullptr) {
2700 add_node_error(g, field_node, buf_sprintf("struct field missing type"));
2701 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2702 return ErrorSemanticAnalyzeFail;
2703 }
2716 AstNode *field_node;
2717 if (decl_node->type == NodeTypeContainerDecl) {
2718 field_node = decl_node->data.container_decl.fields.at(i);
2719 type_struct_field->name = field_node->data.struct_field.name;
2720 type_struct_field->decl_node = field_node;
2721
2722 if (field_node->data.struct_field.type == nullptr) {
2723 add_node_error(g, field_node, buf_sprintf("struct field missing type"));
2724 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2725 return ErrorSemanticAnalyzeFail;
2726 }
2727 } else if (decl_node->type == NodeTypeContainerInitExpr) {
2728 field_node = type_struct_field->decl_node;
2729
2730 src_assert(type_struct_field->type_entry != nullptr, field_node);
2731 } else zig_unreachable();
27042732
27052733 auto field_entry = struct_type->data.structure.fields_by_name.put_unique(type_struct_field->name, type_struct_field);
27062734 if (field_entry != nullptr) {
......@@ -2711,16 +2739,21 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
27112739 return ErrorSemanticAnalyzeFail;
27122740 }
27132741
2714 ConstExprValue *field_type_val = analyze_const_value(g, scope,
2715 field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef);
2716 if (type_is_invalid(field_type_val->type)) {
2717 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2718 return ErrorSemanticAnalyzeFail;
2719 }
2720 assert(field_type_val->special != ConstValSpecialRuntime);
2721 type_struct_field->type_val = field_type_val;
2722 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
2723 return ErrorSemanticAnalyzeFail;
2742 ConstExprValue *field_type_val;
2743 if (decl_node->type == NodeTypeContainerDecl) {
2744 field_type_val = analyze_const_value(g, scope,
2745 field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef);
2746 if (type_is_invalid(field_type_val->type)) {
2747 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2748 return ErrorSemanticAnalyzeFail;
2749 }
2750 assert(field_type_val->special != ConstValSpecialRuntime);
2751 type_struct_field->type_val = field_type_val;
2752 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
2753 return ErrorSemanticAnalyzeFail;
2754 } else if (decl_node->type == NodeTypeContainerInitExpr) {
2755 field_type_val = type_struct_field->type_val;
2756 } else zig_unreachable();
27242757
27252758 bool field_is_opaque_type;
27262759 if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) {
......@@ -2804,7 +2837,7 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
28042837 }
28052838
28062839 struct_type->data.structure.resolve_loop_flag_other = true;
2807 assert(decl_node->type == NodeTypeContainerDecl);
2840 assert(decl_node->type == NodeTypeContainerDecl || decl_node->type == NodeTypeContainerInitExpr);
28082841
28092842 size_t field_count = struct_type->data.structure.src_field_count;
28102843 bool packed = struct_type->data.structure.layout == ContainerLayoutPacked;
......@@ -2814,7 +2847,8 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
28142847 if (field->gen_index == SIZE_MAX)
28152848 continue;
28162849
2817 AstNode *align_expr = field->decl_node->data.struct_field.align_expr;
2850 AstNode *align_expr = (field->decl_node->type == NodeTypeStructField) ?
2851 field->decl_node->data.struct_field.align_expr : nullptr;
28182852 if (align_expr != nullptr) {
28192853 if (!analyze_const_align(g, &struct_type->data.structure.decls_scope->base, align_expr,
28202854 &field->align))
......@@ -5413,6 +5447,12 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
54135447 if (type_entry->one_possible_value != OnePossibleValueInvalid)
54145448 return type_entry->one_possible_value;
54155449
5450 if (type_entry->id == ZigTypeIdStruct &&
5451 type_entry->data.structure.resolve_status == ResolveStatusBeingInferred)
5452 {
5453 return OnePossibleValueNo;
5454 }
5455
54165456 Error err;
54175457 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
54185458 return OnePossibleValueInvalid;
......@@ -6132,6 +6172,8 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
61326172 continue;
61336173 if (instruction->ref_count == 0)
61346174 continue;
6175 if ((err = type_resolve(g, instruction->value.type, ResolveStatusZeroBitsKnown)))
6176 return ErrorSemanticAnalyzeFail;
61356177 if (!type_has_bits(instruction->value.type))
61366178 continue;
61376179 if (scope_needs_spill(instruction->scope)) {
......@@ -6271,6 +6313,8 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
62716313 switch (status) {
62726314 case ResolveStatusUnstarted:
62736315 return ErrorNone;
6316 case ResolveStatusBeingInferred:
6317 zig_unreachable();
62746318 case ResolveStatusInvalid:
62756319 zig_unreachable();
62766320 case ResolveStatusZeroBitsKnown:
......@@ -6995,7 +7039,16 @@ bool type_id_eql(TypeId a, TypeId b) {
69957039 a.data.pointer.alignment == b.data.pointer.alignment &&
69967040 a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&
69977041 a.data.pointer.vector_index == b.data.pointer.vector_index &&
6998 a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes;
7042 a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes &&
7043 (
7044 a.data.pointer.inferred_struct_field == b.data.pointer.inferred_struct_field ||
7045 (a.data.pointer.inferred_struct_field != nullptr &&
7046 b.data.pointer.inferred_struct_field != nullptr &&
7047 a.data.pointer.inferred_struct_field->inferred_struct_type ==
7048 b.data.pointer.inferred_struct_field->inferred_struct_type &&
7049 buf_eql_buf(a.data.pointer.inferred_struct_field->field_name,
7050 b.data.pointer.inferred_struct_field->field_name))
7051 );
69997052 case ZigTypeIdArray:
70007053 return a.data.array.child_type == b.data.array.child_type &&
70017054 a.data.array.size == b.data.array.size;
......@@ -7808,7 +7861,6 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
78087861 ZigLLVMDIScope *di_scope;
78097862 unsigned line;
78107863 if (decl_node != nullptr) {
7811 assert(decl_node->type == NodeTypeContainerDecl);
78127864 Scope *scope = &struct_type->data.structure.decls_scope->base;
78137865 ZigType *import = get_scope_import(scope);
78147866 di_file = import->data.structure.root_struct->di_file;
......@@ -8011,7 +8063,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
80118063 }
80128064 unsigned line;
80138065 if (decl_node != nullptr) {
8014 AstNode *field_node = decl_node->data.container_decl.fields.at(i);
8066 AstNode *field_node = field->decl_node;
80158067 line = field_node->line + 1;
80168068 } else {
80178069 line = 0;
......@@ -8307,12 +8359,12 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus
83078359 if (type->data.pointer.vector_index == VECTOR_INDEX_NONE) {
83088360 peer_type = get_pointer_to_type_extra2(g, elem_type, false, false,
83098361 PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false,
8310 VECTOR_INDEX_NONE);
8362 VECTOR_INDEX_NONE, nullptr);
83118363 } else {
83128364 uint32_t host_vec_len = type->data.pointer.host_int_bytes;
83138365 ZigType *host_vec_type = get_vector_type(g, host_vec_len, elem_type);
83148366 peer_type = get_pointer_to_type_extra2(g, host_vec_type, false, false,
8315 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE);
8367 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr);
83168368 }
83178369 type->llvm_type = get_llvm_type(g, peer_type);
83188370 type->llvm_di_type = get_llvm_di_type(g, peer_type);
......@@ -9038,4 +9090,3 @@ Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str,
90389090 *out_import = add_source_file(g, target_package, resolved_path, import_code, source_kind);
90399091 return ErrorNone;
90409092}
9041
src/analyze.hpp+1-1
......@@ -24,7 +24,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type,
2424ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type,
2525 bool is_const, bool is_volatile, PtrLen ptr_len,
2626 uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count,
27 bool allow_zero, uint32_t vector_index);
27 bool allow_zero, uint32_t vector_index, InferredStructField *inferred_struct_field);
2828uint64_t type_size(CodeGen *g, ZigType *type_entry);
2929uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);
3030ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
src/ast_render.cpp+3-1
......@@ -821,7 +821,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
821821 break;
822822 }
823823 case NodeTypeContainerInitExpr:
824 render_node_ungrouped(ar, node->data.container_init_expr.type);
824 if (node->data.container_init_expr.type != nullptr) {
825 render_node_ungrouped(ar, node->data.container_init_expr.type);
826 }
825827 if (node->data.container_init_expr.kind == ContainerInitKindStruct) {
826828 fprintf(ar->f, "{\n");
827829 ar->indent += ar->indent_size;
src/ir.cpp+313-109
......@@ -202,6 +202,10 @@ static Buf *get_anon_type_name(CodeGen *codegen, IrExecutable *exec, const char
202202 Scope *scope, AstNode *source_node, Buf *out_bare_name);
203203static ResultLocCast *ir_build_cast_result_loc(IrBuilder *irb, IrInstruction *dest_type,
204204 ResultLoc *parent_result_loc);
205static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction *source_instr,
206 TypeStructField *field, IrInstruction *struct_ptr, ZigType *struct_type, bool initializing);
207static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name,
208 IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type);
205209
206210static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
207211 assert(get_src_ptr_type(const_val->type) != nullptr);
......@@ -1350,18 +1354,17 @@ static IrInstruction *ir_build_return_ptr(IrAnalyze *ira, IrInstruction *source_
13501354
13511355static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
13521356 IrInstruction *array_ptr, IrInstruction *elem_index, bool safety_check_on, PtrLen ptr_len,
1353 IrInstruction *init_array_type)
1357 AstNode *init_array_type_source_node)
13541358{
13551359 IrInstructionElemPtr *instruction = ir_build_instruction<IrInstructionElemPtr>(irb, scope, source_node);
13561360 instruction->array_ptr = array_ptr;
13571361 instruction->elem_index = elem_index;
13581362 instruction->safety_check_on = safety_check_on;
13591363 instruction->ptr_len = ptr_len;
1360 instruction->init_array_type = init_array_type;
1364 instruction->init_array_type_source_node = init_array_type_source_node;
13611365
13621366 ir_ref_instruction(array_ptr, irb->current_basic_block);
13631367 ir_ref_instruction(elem_index, irb->current_basic_block);
1364 if (init_array_type != nullptr) ir_ref_instruction(init_array_type, irb->current_basic_block);
13651368
13661369 return &instruction->base;
13671370}
......@@ -1575,17 +1578,16 @@ static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *sour
15751578}
15761579
15771580static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node,
1578 IrInstruction *container_type, size_t item_count, IrInstruction **elem_result_loc_list,
1579 IrInstruction *result_loc)
1581 size_t item_count, IrInstruction **elem_result_loc_list, IrInstruction *result_loc,
1582 AstNode *init_array_type_source_node)
15801583{
15811584 IrInstructionContainerInitList *container_init_list_instruction =
15821585 ir_build_instruction<IrInstructionContainerInitList>(irb, scope, source_node);
1583 container_init_list_instruction->container_type = container_type;
15841586 container_init_list_instruction->item_count = item_count;
15851587 container_init_list_instruction->elem_result_loc_list = elem_result_loc_list;
15861588 container_init_list_instruction->result_loc = result_loc;
1589 container_init_list_instruction->init_array_type_source_node = init_array_type_source_node;
15871590
1588 ir_ref_instruction(container_type, irb->current_basic_block);
15891591 for (size_t i = 0; i < item_count; i += 1) {
15901592 ir_ref_instruction(elem_result_loc_list[i], irb->current_basic_block);
15911593 }
......@@ -1595,17 +1597,14 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope,
15951597}
15961598
15971599static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scope, AstNode *source_node,
1598 IrInstruction *container_type, size_t field_count, IrInstructionContainerInitFieldsField *fields,
1599 IrInstruction *result_loc)
1600 size_t field_count, IrInstructionContainerInitFieldsField *fields, IrInstruction *result_loc)
16001601{
16011602 IrInstructionContainerInitFields *container_init_fields_instruction =
16021603 ir_build_instruction<IrInstructionContainerInitFields>(irb, scope, source_node);
1603 container_init_fields_instruction->container_type = container_type;
16041604 container_init_fields_instruction->field_count = field_count;
16051605 container_init_fields_instruction->fields = fields;
16061606 container_init_fields_instruction->result_loc = result_loc;
16071607
1608 ir_ref_instruction(container_type, irb->current_basic_block);
16091608 for (size_t i = 0; i < field_count; i += 1) {
16101609 ir_ref_instruction(fields[i].result_loc, irb->current_basic_block);
16111610 }
......@@ -3084,7 +3083,7 @@ static IrInstruction *ir_build_resolve_result(IrBuilder *irb, Scope *scope, AstN
30843083 instruction->result_loc = result_loc;
30853084 instruction->ty = ty;
30863085
3087 ir_ref_instruction(ty, irb->current_basic_block);
3086 if (ty != nullptr) ir_ref_instruction(ty, irb->current_basic_block);
30883087
30893088 return &instruction->base;
30903089}
......@@ -6127,28 +6126,46 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
61276126 AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
61286127 ContainerInitKind kind = container_init_expr->kind;
61296128
6130 IrInstruction *container_type = nullptr;
6131 IrInstruction *elem_type = nullptr;
6132 if (container_init_expr->type->type == NodeTypeInferredArrayType) {
6133 elem_type = ir_gen_node(irb, container_init_expr->type->data.inferred_array_type.child_type, scope);
6134 if (elem_type == irb->codegen->invalid_instruction)
6135 return elem_type;
6136 } else {
6137 container_type = ir_gen_node(irb, container_init_expr->type, scope);
6138 if (container_type == irb->codegen->invalid_instruction)
6139 return container_type;
6140 }
6141
6142 switch (kind) {
6143 case ContainerInitKindStruct: {
6144 if (elem_type != nullptr) {
6129 ResultLocCast *result_loc_cast = nullptr;
6130 ResultLoc *child_result_loc;
6131 AstNode *init_array_type_source_node;
6132 if (container_init_expr->type != nullptr) {
6133 IrInstruction *container_type;
6134 if (container_init_expr->type->type == NodeTypeInferredArrayType) {
6135 if (kind == ContainerInitKindStruct) {
61456136 add_node_error(irb->codegen, container_init_expr->type,
61466137 buf_sprintf("initializing array with struct syntax"));
61476138 return irb->codegen->invalid_instruction;
61486139 }
6140 IrInstruction *elem_type = ir_gen_node(irb,
6141 container_init_expr->type->data.inferred_array_type.child_type, scope);
6142 if (elem_type == irb->codegen->invalid_instruction)
6143 return elem_type;
6144 size_t item_count = container_init_expr->entries.length;
6145 IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count);
6146 container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type);
6147 } else {
6148 container_type = ir_gen_node(irb, container_init_expr->type, scope);
6149 if (container_type == irb->codegen->invalid_instruction)
6150 return container_type;
6151 }
61496152
6150 IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc,
6151 container_type);
6153 result_loc_cast = ir_build_cast_result_loc(irb, container_type, parent_result_loc);
6154 child_result_loc = &result_loc_cast->base;
6155 init_array_type_source_node = container_type->source_node;
6156 } else {
6157 child_result_loc = parent_result_loc;
6158 if (parent_result_loc->source_instruction != nullptr) {
6159 init_array_type_source_node = parent_result_loc->source_instruction->source_node;
6160 } else {
6161 init_array_type_source_node = node;
6162 }
6163 }
6164
6165 switch (kind) {
6166 case ContainerInitKindStruct: {
6167 IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc,
6168 nullptr);
61526169
61536170 size_t field_count = container_init_expr->entries.length;
61546171 IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count);
......@@ -6176,29 +6193,27 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
61766193 fields[i].source_node = entry_node;
61776194 fields[i].result_loc = field_ptr;
61786195 }
6179 IrInstruction *init_fields = ir_build_container_init_fields(irb, scope, node, container_type,
6180 field_count, fields, container_ptr);
6196 IrInstruction *result = ir_build_container_init_fields(irb, scope, node, field_count,
6197 fields, container_ptr);
61816198
6182 return ir_lval_wrap(irb, scope, init_fields, lval, parent_result_loc);
6199 if (result_loc_cast != nullptr) {
6200 result = ir_build_implicit_cast(irb, scope, node, result, result_loc_cast);
6201 }
6202 return ir_lval_wrap(irb, scope, result, lval, parent_result_loc);
61836203 }
61846204 case ContainerInitKindArray: {
61856205 size_t item_count = container_init_expr->entries.length;
61866206
6187 if (container_type == nullptr) {
6188 IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count);
6189 container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type);
6190 }
6191
6192 IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc,
6193 container_type);
6207 IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc,
6208 nullptr);
61946209
61956210 IrInstruction **result_locs = allocate<IrInstruction *>(item_count);
61966211 for (size_t i = 0; i < item_count; i += 1) {
61976212 AstNode *expr_node = container_init_expr->entries.at(i);
61986213
61996214 IrInstruction *elem_index = ir_build_const_usize(irb, scope, expr_node, i);
6200 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr, elem_index,
6201 false, PtrLenSingle, container_type);
6215 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr,
6216 elem_index, false, PtrLenSingle, init_array_type_source_node);
62026217 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
62036218 result_loc_inst->base.id = ResultLocIdInstruction;
62046219 result_loc_inst->base.source_instruction = elem_ptr;
......@@ -6213,9 +6228,12 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
62136228
62146229 result_locs[i] = elem_ptr;
62156230 }
6216 IrInstruction *init_list = ir_build_container_init_list(irb, scope, node, container_type,
6217 item_count, result_locs, container_ptr);
6218 return ir_lval_wrap(irb, scope, init_list, lval, parent_result_loc);
6231 IrInstruction *result = ir_build_container_init_list(irb, scope, node, item_count,
6232 result_locs, container_ptr, init_array_type_source_node);
6233 if (result_loc_cast != nullptr) {
6234 result = ir_build_implicit_cast(irb, scope, node, result, result_loc_cast);
6235 }
6236 return ir_lval_wrap(irb, scope, result, lval, parent_result_loc);
62196237 }
62206238 }
62216239 zig_unreachable();
......@@ -7935,14 +7953,14 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o
79357953static Buf *get_anon_type_name(CodeGen *codegen, IrExecutable *exec, const char *kind_name,
79367954 Scope *scope, AstNode *source_node, Buf *out_bare_name)
79377955{
7938 if (exec->name) {
7956 if (exec != nullptr && exec->name) {
79397957 ZigType *import = get_scope_import(scope);
79407958 Buf *namespace_name = buf_alloc();
79417959 append_namespace_qualification(codegen, namespace_name, import);
79427960 buf_append_buf(namespace_name, exec->name);
79437961 buf_init_from_buf(out_bare_name, exec->name);
79447962 return namespace_name;
7945 } else if (exec->name_fn != nullptr) {
7963 } else if (exec != nullptr && exec->name_fn != nullptr) {
79467964 Buf *name = buf_alloc();
79477965 buf_append_buf(name, &exec->name_fn->symbol_name);
79487966 buf_appendf(name, "(");
......@@ -15541,11 +15559,7 @@ static bool ir_result_has_type(ResultLoc *result_loc) {
1554115559static IrInstruction *ir_resolve_no_result_loc(IrAnalyze *ira, IrInstruction *suspend_source_instr,
1554215560 ResultLoc *result_loc, ZigType *value_type, bool force_runtime, bool non_null_comptime)
1554315561{
15544 Error err;
15545
1554615562 IrInstructionAllocaGen *alloca_gen = ir_build_alloca_gen(ira, suspend_source_instr, 0, "");
15547 if ((err = type_resolve(ira->codegen, value_type, ResolveStatusZeroBitsKnown)))
15548 return ira->codegen->invalid_instruction;
1554915563 alloca_gen->base.value.type = get_pointer_to_type_extra(ira->codegen, value_type, false, false,
1555015564 PtrLenSingle, 0, 0, 0, false);
1555115565 set_up_result_loc_for_inferred_comptime(&alloca_gen->base);
......@@ -15750,6 +15764,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
1575015764 return casted_value;
1575115765 }
1575215766
15767 bool old_parent_result_loc_written = result_cast->parent->written;
1575315768 IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_cast->parent,
1575415769 dest_type, casted_value, force_runtime, non_null_comptime, true);
1575515770 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
......@@ -15775,6 +15790,22 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
1577515790 parent_ptr_type->data.pointer.is_const, parent_ptr_type->data.pointer.is_volatile, PtrLenSingle,
1577615791 parent_ptr_align, 0, 0, parent_ptr_type->data.pointer.allow_zero);
1577715792
15793 {
15794 // we also need to check that this cast is OK.
15795 ConstCastOnly const_cast_result = types_match_const_cast_only(ira,
15796 parent_result_loc->value.type, ptr_type,
15797 result_cast->base.source_instruction->source_node, false);
15798 if (const_cast_result.id == ConstCastResultIdInvalid)
15799 return ira->codegen->invalid_instruction;
15800 if (const_cast_result.id != ConstCastResultIdOk) {
15801 // We will not be able to provide a result location for this value. Create
15802 // a new result location.
15803 result_cast->parent->written = old_parent_result_loc_written;
15804 return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type,
15805 force_runtime, non_null_comptime);
15806 }
15807 }
15808
1577815809 result_loc->written = true;
1577915810 result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr, parent_result_loc,
1578015811 ptr_type, result_cast->base.source_instruction, false);
......@@ -15902,10 +15933,37 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
1590215933 return result_loc;
1590315934}
1590415935
15905static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrInstructionResolveResult *instruction) {
15906 ZigType *implicit_elem_type = ir_resolve_type(ira, instruction->ty->child);
15907 if (type_is_invalid(implicit_elem_type))
15908 return ira->codegen->invalid_instruction;
15936static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira,
15937 IrInstructionResolveResult *instruction)
15938{
15939 ZigType *implicit_elem_type;
15940 if (instruction->ty == nullptr) {
15941 if (instruction->result_loc->id == ResultLocIdCast) {
15942 implicit_elem_type = ir_resolve_type(ira,
15943 instruction->result_loc->source_instruction->child);
15944 if (type_is_invalid(implicit_elem_type))
15945 return ira->codegen->invalid_instruction;
15946 } else if (instruction->result_loc->id == ResultLocIdReturn) {
15947 implicit_elem_type = ira->explicit_return_type;
15948 if (type_is_invalid(implicit_elem_type))
15949 return ira->codegen->invalid_instruction;
15950 } else {
15951 Buf *bare_name = buf_alloc();
15952 Buf *name = get_anon_type_name(ira->codegen, nullptr, container_string(ContainerKindStruct),
15953 instruction->base.scope, instruction->base.source_node, bare_name);
15954
15955 ZigType *inferred_struct_type = get_partial_container_type(ira->codegen,
15956 instruction->base.scope, ContainerKindStruct, instruction->base.source_node,
15957 buf_ptr(name), bare_name, ContainerLayoutAuto);
15958 inferred_struct_type->data.structure.is_inferred = true;
15959 inferred_struct_type->data.structure.resolve_status = ResolveStatusBeingInferred;
15960 implicit_elem_type = inferred_struct_type;
15961 }
15962 } else {
15963 implicit_elem_type = ir_resolve_type(ira, instruction->ty->child);
15964 if (type_is_invalid(implicit_elem_type))
15965 return ira->codegen->invalid_instruction;
15966 }
1590915967 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
1591015968 implicit_elem_type, nullptr, false, true, true);
1591115969 if (result_loc != nullptr)
......@@ -16267,13 +16325,78 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
1626716325 return ir_const_void(ira, source_instr);
1626816326 }
1626916327
16270 ZigType *child_type = ptr->value.type->data.pointer.child_type;
16328 InferredStructField *isf = ptr->value.type->data.pointer.inferred_struct_field;
16329 if (allow_write_through_const && isf != nullptr) {
16330 // Now it's time to add the field to the struct type.
16331 uint32_t old_field_count = isf->inferred_struct_type->data.structure.src_field_count;
16332 uint32_t new_field_count = old_field_count + 1;
16333 isf->inferred_struct_type->data.structure.src_field_count = new_field_count;
16334 if (new_field_count > 16) {
16335 // This thing with 16 is a hack to allow this functionality to work without
16336 // modifying the ConstExprValue layout of structs. That reworking needs to be
16337 // done, but this hack lets us do it separately, in the future.
16338 zig_panic("TODO need to rework the layout of ZigTypeStruct. This realloc would have caused invalid pointer references");
16339 }
16340 if (isf->inferred_struct_type->data.structure.fields == nullptr) {
16341 isf->inferred_struct_type->data.structure.fields = allocate<TypeStructField>(16);
16342 }
16343
16344 // This reference can't live long, don't keep it around outside this block.
16345 TypeStructField *field = &isf->inferred_struct_type->data.structure.fields[old_field_count];
16346 field->name = isf->field_name;
16347 field->type_entry = uncasted_value->value.type;
16348 field->type_val = create_const_type(ira->codegen, field->type_entry);
16349 field->src_index = old_field_count;
16350 field->decl_node = uncasted_value->source_node;
16351
16352 ZigType *struct_ptr_type = get_pointer_to_type(ira->codegen, isf->inferred_struct_type, false);
16353 IrInstruction *casted_ptr;
16354 if (instr_is_comptime(ptr)) {
16355 casted_ptr = ir_const(ira, source_instr, struct_ptr_type);
16356 copy_const_val(&casted_ptr->value, &ptr->value, false);
16357 casted_ptr->value.type = struct_ptr_type;
16358 } else {
16359 casted_ptr = ir_build_cast(&ira->new_irb, source_instr->scope,
16360 source_instr->source_node, struct_ptr_type, ptr, CastOpNoop);
16361 casted_ptr->value.type = struct_ptr_type;
16362 }
16363 if (instr_is_comptime(casted_ptr)) {
16364 ConstExprValue *ptr_val = ir_resolve_const(ira, casted_ptr, UndefBad);
16365 if (!ptr_val)
16366 return ira->codegen->invalid_instruction;
16367 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
16368 ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val,
16369 source_instr->source_node);
16370 struct_val->special = ConstValSpecialStatic;
16371 if (new_field_count > 16) {
16372 // This thing with 16 is a hack to allow this functionality to work without
16373 // modifying the ConstExprValue layout of structs. That reworking needs to be
16374 // done, but this hack lets us do it separately, in the future.
16375 zig_panic("TODO need to rework the layout of ConstExprValue for structs. This realloc would have caused invalid pointer references");
16376 }
16377 if (struct_val->data.x_struct.fields == nullptr) {
16378 struct_val->data.x_struct.fields = create_const_vals(16);
16379 }
16380
16381 ConstExprValue *field_val = &struct_val->data.x_struct.fields[old_field_count];
16382 field_val->special = ConstValSpecialUndef;
16383 field_val->type = field->type_entry;
16384 field_val->parent.id = ConstParentIdStruct;
16385 field_val->parent.data.p_struct.struct_val = struct_val;
16386 field_val->parent.data.p_struct.field_index = old_field_count;
16387 }
16388 }
16389
16390 ptr = ir_analyze_struct_field_ptr(ira, source_instr, field, casted_ptr,
16391 isf->inferred_struct_type, true);
16392 }
1627116393
1627216394 if (ptr->value.type->data.pointer.is_const && !allow_write_through_const) {
1627316395 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
1627416396 return ira->codegen->invalid_instruction;
1627516397 }
1627616398
16399 ZigType *child_type = ptr->value.type->data.pointer.child_type;
1627716400 IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type);
1627816401 if (value == ira->codegen->invalid_instruction)
1627916402 return ira->codegen->invalid_instruction;
......@@ -17769,6 +17892,19 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1776917892 } else if (array_type->id == ZigTypeIdVector) {
1777017893 // This depends on whether the element index is comptime, so it is computed later.
1777117894 return_type = nullptr;
17895 } else if (elem_ptr_instruction->init_array_type_source_node != nullptr &&
17896 array_type->id == ZigTypeIdStruct &&
17897 array_type->data.structure.resolve_status == ResolveStatusBeingInferred)
17898 {
17899 ZigType *usize = ira->codegen->builtin_types.entry_usize;
17900 IrInstruction *casted_elem_index = ir_implicit_cast(ira, elem_index, usize);
17901 if (casted_elem_index == ira->codegen->invalid_instruction)
17902 return ira->codegen->invalid_instruction;
17903 ir_assert(instr_is_comptime(casted_elem_index), &elem_ptr_instruction->base);
17904 Buf *field_name = buf_alloc();
17905 bigint_append_buf(field_name, &casted_elem_index->value.data.x_bigint, 10);
17906 return ir_analyze_inferred_field_ptr(ira, field_name, &elem_ptr_instruction->base,
17907 array_ptr, array_type);
1777217908 } else {
1777317909 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
1777417910 buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name)));
......@@ -17799,7 +17935,8 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1779917935 return_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
1780017936 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
1780117937 elem_ptr_instruction->ptr_len,
17802 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index);
17938 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index,
17939 nullptr);
1780317940 } else if (return_type->data.pointer.explicit_alignment != 0) {
1780417941 // figure out the largest alignment possible
1780517942
......@@ -17837,7 +17974,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1783717974 if (array_ptr_val == nullptr)
1783817975 return ira->codegen->invalid_instruction;
1783917976
17840 if (array_ptr_val->special == ConstValSpecialUndef && elem_ptr_instruction->init_array_type != nullptr) {
17977 if (array_ptr_val->special == ConstValSpecialUndef &&
17978 elem_ptr_instruction->init_array_type_source_node != nullptr)
17979 {
1784117980 if (array_type->id == ZigTypeIdArray || array_type->id == ZigTypeIdVector) {
1784217981 array_ptr_val->data.x_array.special = ConstArraySpecialNone;
1784317982 array_ptr_val->data.x_array.data.s_none.elements = create_const_vals(array_type->data.array.len);
......@@ -17851,11 +17990,13 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1785117990 elem_val->parent.data.p_array.elem_index = i;
1785217991 }
1785317992 } else if (is_slice(array_type)) {
17854 ZigType *actual_array_type = ir_resolve_type(ira, elem_ptr_instruction->init_array_type->child);
17993 ir_assert(array_ptr->value.type->id == ZigTypeIdPointer, &elem_ptr_instruction->base);
17994 ZigType *actual_array_type = array_ptr->value.type->data.pointer.child_type;
17995
1785517996 if (type_is_invalid(actual_array_type))
1785617997 return ira->codegen->invalid_instruction;
1785717998 if (actual_array_type->id != ZigTypeIdArray) {
17858 ir_add_error(ira, elem_ptr_instruction->init_array_type,
17999 ir_add_error_node(ira, elem_ptr_instruction->init_array_type_source_node,
1785918000 buf_sprintf("expected array type or [_], found slice"));
1786018001 return ira->codegen->invalid_instruction;
1786118002 }
......@@ -17879,7 +18020,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1787918020 false);
1788018021 array_ptr_val->data.x_struct.fields[slice_ptr_index].data.x_ptr.mut = ConstPtrMutInfer;
1788118022 } else {
17882 ir_add_error(ira, elem_ptr_instruction->init_array_type,
18023 ir_add_error_node(ira, elem_ptr_instruction->init_array_type_source_node,
1788318024 buf_sprintf("expected array type or [_], found '%s'",
1788418025 buf_ptr(&array_type->name)));
1788518026 return ira->codegen->invalid_instruction;
......@@ -18012,7 +18153,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1801218153 if (orig_array_ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
1801318154 result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,
1801418155 elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index,
18015 false, elem_ptr_instruction->ptr_len, elem_ptr_instruction->init_array_type);
18156 false, elem_ptr_instruction->ptr_len, nullptr);
1801618157 result->value.type = return_type;
1801718158 result->value.special = ConstValSpecialStatic;
1801818159 } else {
......@@ -18036,7 +18177,8 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1803618177 return_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
1803718178 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
1803818179 elem_ptr_instruction->ptr_len,
18039 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, VECTOR_INDEX_RUNTIME);
18180 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, VECTOR_INDEX_RUNTIME,
18181 nullptr);
1804018182 } else {
1804118183 // runtime known element index
1804218184 switch (type_requires_comptime(ira->codegen, return_type)) {
......@@ -18073,7 +18215,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1807318215
1807418216 IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,
1807518217 elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, safety_check_on,
18076 elem_ptr_instruction->ptr_len, elem_ptr_instruction->init_array_type);
18218 elem_ptr_instruction->ptr_len, nullptr);
1807718219 result->value.type = return_type;
1807818220 return result;
1807918221}
......@@ -18152,31 +18294,34 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction
1815218294 case OnePossibleValueNo:
1815318295 break;
1815418296 }
18155 ResolveStatus needed_resolve_status =
18156 (struct_type->data.structure.layout == ContainerLayoutAuto) ?
18157 ResolveStatusZeroBitsKnown : ResolveStatusSizeKnown;
18158 if ((err = type_resolve(ira->codegen, struct_type, needed_resolve_status)))
18159 return ira->codegen->invalid_instruction;
18160 assert(struct_ptr->value.type->id == ZigTypeIdPointer);
18161 uint32_t ptr_bit_offset = struct_ptr->value.type->data.pointer.bit_offset_in_host;
18162 uint32_t ptr_host_int_bytes = struct_ptr->value.type->data.pointer.host_int_bytes;
18163 uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ?
18164 get_host_int_bytes(ira->codegen, struct_type, field) : ptr_host_int_bytes;
1816518297 bool is_const = struct_ptr->value.type->data.pointer.is_const;
1816618298 bool is_volatile = struct_ptr->value.type->data.pointer.is_volatile;
18167 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
18168 is_const, is_volatile, PtrLenSingle, field->align,
18169 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
18170 (uint32_t)host_int_bytes_for_result_type, false);
18299 ZigType *ptr_type;
18300 if (struct_type->data.structure.is_inferred) {
18301 ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
18302 is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
18303 } else {
18304 ResolveStatus needed_resolve_status =
18305 (struct_type->data.structure.layout == ContainerLayoutAuto) ?
18306 ResolveStatusZeroBitsKnown : ResolveStatusSizeKnown;
18307 if ((err = type_resolve(ira->codegen, struct_type, needed_resolve_status)))
18308 return ira->codegen->invalid_instruction;
18309 assert(struct_ptr->value.type->id == ZigTypeIdPointer);
18310 uint32_t ptr_bit_offset = struct_ptr->value.type->data.pointer.bit_offset_in_host;
18311 uint32_t ptr_host_int_bytes = struct_ptr->value.type->data.pointer.host_int_bytes;
18312 uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ?
18313 get_host_int_bytes(ira->codegen, struct_type, field) : ptr_host_int_bytes;
18314 ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
18315 is_const, is_volatile, PtrLenSingle, field->align,
18316 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
18317 (uint32_t)host_int_bytes_for_result_type, false);
18318 }
1817118319 if (instr_is_comptime(struct_ptr)) {
1817218320 ConstExprValue *ptr_val = ir_resolve_const(ira, struct_ptr, UndefBad);
1817318321 if (!ptr_val)
1817418322 return ira->codegen->invalid_instruction;
1817518323
1817618324 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
18177 if ((err = type_resolve(ira->codegen, struct_type, ResolveStatusSizeKnown)))
18178 return ira->codegen->invalid_instruction;
18179
1818018325 ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
1818118326 if (struct_val == nullptr)
1818218327 return ira->codegen->invalid_instruction;
......@@ -18188,7 +18333,8 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction
1818818333 for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) {
1818918334 ConstExprValue *field_val = &struct_val->data.x_struct.fields[i];
1819018335 field_val->special = ConstValSpecialUndef;
18191 field_val->type = struct_type->data.structure.fields[i].type_entry;
18336 field_val->type = resolve_struct_field_type(ira->codegen,
18337 &struct_type->data.structure.fields[i]);
1819218338 field_val->parent.id = ConstParentIdStruct;
1819318339 field_val->parent.data.p_struct.struct_val = struct_val;
1819418340 field_val->parent.data.p_struct.field_index = i;
......@@ -18217,12 +18363,53 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction
1821718363 return result;
1821818364}
1821918365
18366static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name,
18367 IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type)
18368{
18369 // The type of the field is not available until a store using this pointer happens.
18370 // So, here we create a special pointer type which has the inferred struct type and
18371 // field name encoded in the type. Later, when there is a store via this pointer,
18372 // the field type will then be available, and the field will be added to the inferred
18373 // struct.
18374
18375 ZigType *container_ptr_type = container_ptr->value.type;
18376 ir_assert(container_ptr_type->id == ZigTypeIdPointer, source_instr);
18377
18378 InferredStructField *inferred_struct_field = allocate<InferredStructField>(1, "InferredStructField");
18379 inferred_struct_field->inferred_struct_type = container_type;
18380 inferred_struct_field->field_name = field_name;
18381
18382 ZigType *elem_type = ira->codegen->builtin_types.entry_c_void;
18383 ZigType *field_ptr_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
18384 container_ptr_type->data.pointer.is_const, container_ptr_type->data.pointer.is_volatile,
18385 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, inferred_struct_field);
18386
18387 if (instr_is_comptime(container_ptr)) {
18388 IrInstruction *result = ir_const(ira, source_instr, field_ptr_type);
18389 copy_const_val(&result->value, &container_ptr->value, false);
18390 result->value.type = field_ptr_type;
18391 return result;
18392 }
18393
18394 IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope,
18395 source_instr->source_node, field_ptr_type, container_ptr, CastOpNoop);
18396 result->value.type = field_ptr_type;
18397 return result;
18398}
18399
1822018400static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
1822118401 IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing)
1822218402{
1822318403 Error err;
1822418404
1822518405 ZigType *bare_type = container_ref_type(container_type);
18406
18407 if (initializing && bare_type->id == ZigTypeIdStruct &&
18408 bare_type->data.structure.resolve_status == ResolveStatusBeingInferred)
18409 {
18410 return ir_analyze_inferred_field_ptr(ira, field_name, source_instr, container_ptr, bare_type);
18411 }
18412
1822618413 if ((err = type_resolve(ira->codegen, bare_type, ResolveStatusZeroBitsKnown)))
1822718414 return ira->codegen->invalid_instruction;
1822818415
......@@ -19997,6 +20184,11 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1999720184 return ira->codegen->invalid_instruction;
1999820185 }
1999920186
20187 if (container_type->data.structure.resolve_status == ResolveStatusBeingInferred) {
20188 // We're now done inferring the type.
20189 container_type->data.structure.resolve_status = ResolveStatusUnstarted;
20190 }
20191
2000020192 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
2000120193 return ira->codegen->invalid_instruction;
2000220194
......@@ -20066,8 +20258,12 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
2006620258 TypeStructField *field = &container_type->data.structure.fields[i];
2006720259 if (field->init_val == nullptr) {
2006820260 // it's not memoized. time to go analyze it
20069 assert(field->decl_node->type == NodeTypeStructField);
20070 AstNode *init_node = field->decl_node->data.struct_field.value;
20261 AstNode *init_node;
20262 if (field->decl_node->type == NodeTypeStructField) {
20263 init_node = field->decl_node->data.struct_field.value;
20264 } else {
20265 init_node = nullptr;
20266 }
2007120267 if (init_node == nullptr) {
2007220268 ir_add_error_node(ira, instruction->source_node,
2007320269 buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i].name)));
......@@ -20124,14 +20320,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
2012420320static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
2012520321 IrInstructionContainerInitList *instruction)
2012620322{
20127 ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
20128 if (type_is_invalid(container_type))
20129 return ira->codegen->invalid_instruction;
20323 ir_assert(instruction->result_loc != nullptr, &instruction->base);
20324 IrInstruction *result_loc = instruction->result_loc->child;
20325 if (type_is_invalid(result_loc->value.type))
20326 return result_loc;
20327 ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base);
20328
20329 ZigType *container_type = result_loc->value.type->data.pointer.child_type;
2013020330
2013120331 size_t elem_count = instruction->item_count;
2013220332
2013320333 if (is_slice(container_type)) {
20134 ir_add_error(ira, instruction->container_type,
20334 ir_add_error_node(ira, instruction->init_array_type_source_node,
2013520335 buf_sprintf("expected array type or [_], found slice"));
2013620336 return ira->codegen->invalid_instruction;
2013720337 }
......@@ -20153,29 +20353,28 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
2015320353 return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, result_loc);
2015420354 }
2015520355
20156 if (container_type->id != ZigTypeIdArray) {
20356 if (container_type->id == ZigTypeIdArray) {
20357 ZigType *child_type = container_type->data.array.child_type;
20358 if (container_type->data.array.len != elem_count) {
20359 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
20360
20361 ir_add_error(ira, &instruction->base,
20362 buf_sprintf("expected %s literal, found %s literal",
20363 buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
20364 return ira->codegen->invalid_instruction;
20365 }
20366 } else if (container_type->id == ZigTypeIdStruct &&
20367 container_type->data.structure.resolve_status == ResolveStatusBeingInferred)
20368 {
20369 // We're now done inferring the type.
20370 container_type->data.structure.resolve_status = ResolveStatusUnstarted;
20371 } else {
2015720372 ir_add_error_node(ira, instruction->base.source_node,
2015820373 buf_sprintf("type '%s' does not support array initialization",
2015920374 buf_ptr(&container_type->name)));
2016020375 return ira->codegen->invalid_instruction;
2016120376 }
2016220377
20163 ir_assert(instruction->result_loc != nullptr, &instruction->base);
20164 IrInstruction *result_loc = instruction->result_loc->child;
20165 if (type_is_invalid(result_loc->value.type))
20166 return result_loc;
20167 ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base);
20168
20169 ZigType *child_type = container_type->data.array.child_type;
20170 if (container_type->data.array.len != elem_count) {
20171 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
20172
20173 ir_add_error(ira, &instruction->base,
20174 buf_sprintf("expected %s literal, found %s literal",
20175 buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
20176 return ira->codegen->invalid_instruction;
20177 }
20178
2017920378 switch (type_has_one_possible_value(ira->codegen, container_type)) {
2018020379 case OnePossibleValueInvalid:
2018120380 return ira->codegen->invalid_instruction;
......@@ -20262,16 +20461,14 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
2026220461static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira,
2026320462 IrInstructionContainerInitFields *instruction)
2026420463{
20265 IrInstruction *container_type_value = instruction->container_type->child;
20266 ZigType *container_type = ir_resolve_type(ira, container_type_value);
20267 if (type_is_invalid(container_type))
20268 return ira->codegen->invalid_instruction;
20269
2027020464 ir_assert(instruction->result_loc != nullptr, &instruction->base);
2027120465 IrInstruction *result_loc = instruction->result_loc->child;
2027220466 if (type_is_invalid(result_loc->value.type))
2027320467 return result_loc;
2027420468
20469 ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base);
20470 ZigType *container_type = result_loc->value.type->data.pointer.child_type;
20471
2027520472 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
2027620473 instruction->field_count, instruction->fields, result_loc);
2027720474}
......@@ -24607,6 +24804,10 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
2460724804 ZigType *src_type = ptr->value.type;
2460824805 assert(!type_is_invalid(src_type));
2460924806
24807 if (src_type == dest_type) {
24808 return ptr;
24809 }
24810
2461024811 // We have a check for zero bits later so we use get_src_ptr_type to
2461124812 // validate src_type and dest_type.
2461224813
......@@ -24656,6 +24857,9 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
2465624857 IrInstruction *result;
2465724858 if (ptr->value.data.x_ptr.mut == ConstPtrMutInfer) {
2465824859 result = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on);
24860
24861 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
24862 return ira->codegen->invalid_instruction;
2465924863 } else {
2466024864 result = ir_const(ira, source_instr, dest_type);
2466124865 }
src/ir_print.cpp+4-4
......@@ -731,7 +731,6 @@ static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) {
731731}
732732
733733static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerInitList *instruction) {
734 ir_print_other_instruction(irp, instruction->container_type);
735734 fprintf(irp->f, "{");
736735 if (instruction->item_count > 50) {
737736 fprintf(irp->f, "...(%" ZIG_PRI_usize " items)...", instruction->item_count);
......@@ -743,11 +742,11 @@ static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerIni
743742 ir_print_other_instruction(irp, result_loc);
744743 }
745744 }
746 fprintf(irp->f, "}");
745 fprintf(irp->f, "}result=");
746 ir_print_other_instruction(irp, instruction->result_loc);
747747}
748748
749749static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerInitFields *instruction) {
750 ir_print_other_instruction(irp, instruction->container_type);
751750 fprintf(irp->f, "{");
752751 for (size_t i = 0; i < instruction->field_count; i += 1) {
753752 IrInstructionContainerInitFieldsField *field = &instruction->fields[i];
......@@ -755,7 +754,8 @@ static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerI
755754 fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field->name));
756755 ir_print_other_instruction(irp, field->result_loc);
757756 }
758 fprintf(irp->f, "} // container init");
757 fprintf(irp->f, "}result=");
758 ir_print_other_instruction(irp, instruction->result_loc);
759759}
760760
761761static void ir_print_unreachable(IrPrint *irp, IrInstructionUnreachable *instruction) {
src/parser.cpp+16-10
......@@ -81,7 +81,7 @@ static AstNode *ast_parse_for_type_expr(ParseContext *pc);
8181static AstNode *ast_parse_while_type_expr(ParseContext *pc);
8282static AstNode *ast_parse_switch_expr(ParseContext *pc);
8383static AstNode *ast_parse_asm_expr(ParseContext *pc);
84static AstNode *ast_parse_enum_lit(ParseContext *pc);
84static AstNode *ast_parse_anon_lit(ParseContext *pc);
8585static AstNode *ast_parse_asm_output(ParseContext *pc);
8686static AsmOutput *ast_parse_asm_output_item(ParseContext *pc);
8787static AstNode *ast_parse_asm_input(ParseContext *pc);
......@@ -1600,9 +1600,9 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {
16001600 if (container_decl != nullptr)
16011601 return container_decl;
16021602
1603 AstNode *enum_lit = ast_parse_enum_lit(pc);
1604 if (enum_lit != nullptr)
1605 return enum_lit;
1603 AstNode *anon_lit = ast_parse_anon_lit(pc);
1604 if (anon_lit != nullptr)
1605 return anon_lit;
16061606
16071607 AstNode *error_set_decl = ast_parse_error_set_decl(pc);
16081608 if (error_set_decl != nullptr)
......@@ -1876,16 +1876,22 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc) {
18761876 return res;
18771877}
18781878
1879static AstNode *ast_parse_enum_lit(ParseContext *pc) {
1879static AstNode *ast_parse_anon_lit(ParseContext *pc) {
18801880 Token *period = eat_token_if(pc, TokenIdDot);
18811881 if (period == nullptr)
18821882 return nullptr;
18831883
1884 Token *identifier = expect_token(pc, TokenIdSymbol);
1885 AstNode *res = ast_create_node(pc, NodeTypeEnumLiteral, period);
1886 res->data.enum_literal.period = period;
1887 res->data.enum_literal.identifier = identifier;
1888 return res;
1884 // anon enum literal
1885 Token *identifier = eat_token_if(pc, TokenIdSymbol);
1886 if (identifier != nullptr) {
1887 AstNode *res = ast_create_node(pc, NodeTypeEnumLiteral, period);
1888 res->data.enum_literal.period = period;
1889 res->data.enum_literal.identifier = identifier;
1890 return res;
1891 }
1892
1893 // anon container literal
1894 return ast_parse_init_list(pc);
18891895}
18901896
18911897// AsmOutput <- COLON AsmOutputList AsmInput?
test/compile_errors.zig+19-2
......@@ -2,6 +2,23 @@ const tests = @import("tests.zig");
22const builtin = @import("builtin");
33
44pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.add(
6 "missing const in slice with nested array type",
7 \\const Geo3DTex2D = struct { vertices: [][2]f32 };
8 \\pub fn getGeo3DTex2D() Geo3DTex2D {
9 \\ return Geo3DTex2D{
10 \\ .vertices = [_][2]f32{
11 \\ [_]f32{ -0.5, -0.5},
12 \\ },
13 \\ };
14 \\}
15 \\export fn entry() void {
16 \\ var geo_data = getGeo3DTex2D();
17 \\}
18 ,
19 "tmp.zig:4:30: error: expected type '[][2]f32', found '[1][2]f32'",
20 );
21
522 cases.add(
623 "slicing of global undefined pointer",
724 \\var buf: *[1]u8 = undefined;
......@@ -216,9 +233,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
216233 \\ const obj = AstObject{ .lhsExpr = lhsExpr };
217234 \\}
218235 ,
219 "tmp.zig:4:19: error: union 'AstObject' depends on itself",
220 "tmp.zig:2:5: note: while checking this field",
236 "tmp.zig:1:17: error: struct 'LhsExpr' depends on itself",
221237 "tmp.zig:5:5: note: while checking this field",
238 "tmp.zig:2:5: note: while checking this field",
222239 );
223240
224241 cases.add(
test/stage1/behavior/array.zig+14
......@@ -298,3 +298,17 @@ test "implicit cast zero sized array ptr to slice" {
298298 const c: []const u8 = &b;
299299 expect(c.len == 0);
300300}
301
302test "anonymous list literal syntax" {
303 const S = struct {
304 fn doTheTest() void {
305 var array: [4]u8 = .{1, 2, 3, 4};
306 expect(array[0] == 1);
307 expect(array[1] == 2);
308 expect(array[2] == 3);
309 expect(array[3] == 4);
310 }
311 };
312 S.doTheTest();
313 comptime S.doTheTest();
314}
test/stage1/behavior/async_fn.zig+2-2
......@@ -1214,7 +1214,7 @@ test "spill target expr in a for loop" {
12141214 }
12151215
12161216 const Foo = struct {
1217 slice: []i32,
1217 slice: []const i32,
12181218 };
12191219
12201220 fn atest(foo: *Foo) i32 {
......@@ -1245,7 +1245,7 @@ test "spill target expr in a for loop, with a var decl in the loop body" {
12451245 }
12461246
12471247 const Foo = struct {
1248 slice: []i32,
1248 slice: []const i32,
12491249 };
12501250
12511251 fn atest(foo: *Foo) i32 {
test/stage1/behavior/struct.zig+59
......@@ -709,3 +709,62 @@ test "packed struct field passed to generic function" {
709709 var loaded = S.genericReadPackedField(&p.b);
710710 expect(loaded == 29);
711711}
712
713test "anonymous struct literal syntax" {
714 const S = struct {
715 const Point = struct {
716 x: i32,
717 y: i32,
718 };
719
720 fn doTheTest() void {
721 var p: Point = .{
722 .x = 1,
723 .y = 2,
724 };
725 expect(p.x == 1);
726 expect(p.y == 2);
727 }
728 };
729 S.doTheTest();
730 comptime S.doTheTest();
731}
732
733test "fully anonymous struct" {
734 const S = struct {
735 fn doTheTest() void {
736 dump(.{
737 .int = @as(u32, 1234),
738 .float = @as(f64, 12.34),
739 .b = true,
740 .s = "hi",
741 });
742 }
743 fn dump(args: var) void {
744 expect(args.int == 1234);
745 expect(args.float == 12.34);
746 expect(args.b);
747 expect(args.s[0] == 'h');
748 expect(args.s[1] == 'i');
749 }
750 };
751 S.doTheTest();
752 comptime S.doTheTest();
753}
754
755test "fully anonymous list literal" {
756 const S = struct {
757 fn doTheTest() void {
758 dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi"});
759 }
760 fn dump(args: var) void {
761 expect(args.@"0" == 1234);
762 expect(args.@"1" == 12.34);
763 expect(args.@"2");
764 expect(args.@"3"[0] == 'h');
765 expect(args.@"3"[1] == 'i');
766 }
767 };
768 S.doTheTest();
769 comptime S.doTheTest();
770}
test/stage1/behavior/union.zig+22
......@@ -549,3 +549,25 @@ test "initialize global array of union" {
549549 expect(glbl_array[0].U0 == 1);
550550 expect(glbl_array[1].U1 == 2);
551551}
552
553test "anonymous union literal syntax" {
554 const S = struct {
555 const Number = union {
556 int: i32,
557 float: f64,
558 };
559
560 fn doTheTest() void {
561 var i: Number = .{.int = 42};
562 var f = makeNumber();
563 expect(i.int == 42);
564 expect(f.float == 12.34);
565 }
566
567 fn makeNumber() Number {
568 return .{.float = 12.34};
569 }
570 };
571 S.doTheTest();
572 comptime S.doTheTest();
573}