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" {...@@ -1734,6 +1734,43 @@ test "array initialization with function calls" {
1734 {#code_end#}1734 {#code_end#}
1735 {#see_also|for|Slices#}1735 {#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
1737 {#header_open|Multidimensional Arrays#}1774 {#header_open|Multidimensional Arrays#}
1738 <p>1775 <p>
1739 Mutlidimensional arrays can be created by nesting arrays:1776 Mutlidimensional arrays can be created by nesting arrays:
...@@ -2526,7 +2563,8 @@ test "overaligned pointer to packed struct" {...@@ -2526,7 +2563,8 @@ test "overaligned pointer to packed struct" {
2526 Don't worry, there will be a good solution for this use case in zig.2563 Don't worry, there will be a good solution for this use case in zig.
2527 </p>2564 </p>
2528 {#header_close#}2565 {#header_close#}
2529 {#header_open|struct Naming#}2566
2567 {#header_open|Struct Naming#}
2530 <p>Since all structs are anonymous, Zig infers the type name based on a few rules.</p>2568 <p>Since all structs are anonymous, Zig infers the type name based on a few rules.</p>
2531 <ul>2569 <ul>
2532 <li>If the struct is in the initialization expression of a variable, it gets named after2570 <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 {...@@ -2552,6 +2590,53 @@ fn List(comptime T: type) type {
2552}2590}
2553 {#code_end#}2591 {#code_end#}
2554 {#header_close#}2592 {#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#}
2555 {#see_also|comptime|@fieldParentPtr#}2640 {#see_also|comptime|@fieldParentPtr#}
2556 {#header_close#}2641 {#header_close#}
2557 {#header_open|enum#}2642 {#header_open|enum#}
...@@ -2906,6 +2991,32 @@ test "@tagName" {...@@ -2906,6 +2991,32 @@ test "@tagName" {
2906 <p>A {#syntax#}packed union{#endsyntax#} has well-defined in-memory layout and is eligible2991 <p>A {#syntax#}packed union{#endsyntax#} has well-defined in-memory layout and is eligible
2907 to be in a {#link|packed struct#}.2992 to be in a {#link|packed struct#}.
2908 {#header_close#}2993 {#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
2909 {#header_close#}3020 {#header_close#}
29103021
2911 {#header_open|blocks#}3022 {#header_open|blocks#}
lib/std/builtin.zig+2-31
...@@ -90,40 +90,11 @@ pub const Mode = enum {...@@ -90,40 +90,11 @@ pub const Mode = enum {
90 ReleaseSmall,90 ReleaseSmall,
91};91};
9292
93/// This data structure is used by the Zig language code generation and93pub const TypeId = @TagType(TypeInfo);
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};
12394
124/// This data structure is used by the Zig language code generation and95/// This data structure is used by the Zig language code generation and
125/// therefore must be kept in sync with the compiler implementation.96/// therefore must be kept in sync with the compiler implementation.
126pub const TypeInfo = union(TypeId) {97pub const TypeInfo = union(enum) {
127 Type: void,98 Type: void,
128 Void: void,99 Void: void,
129 Bool: void,100 Bool: void,
lib/std/zig/ast.zig+17-4
...@@ -1648,10 +1648,15 @@ pub const Node = struct {...@@ -1648,10 +1648,15 @@ pub const Node = struct {
16481648
1649 pub const SuffixOp = struct {1649 pub const SuffixOp = struct {
1650 base: Node,1650 base: Node,
1651 lhs: *Node,1651 lhs: Lhs,
1652 op: Op,1652 op: Op,
1653 rtoken: TokenIndex,1653 rtoken: TokenIndex,
16541654
1655 pub const Lhs = union(enum) {
1656 node: *Node,
1657 dot: TokenIndex,
1658 };
1659
1655 pub const Op = union(enum) {1660 pub const Op = union(enum) {
1656 Call: Call,1661 Call: Call,
1657 ArrayAccess: *Node,1662 ArrayAccess: *Node,
...@@ -1679,8 +1684,13 @@ pub const Node = struct {...@@ -1679,8 +1684,13 @@ pub const Node = struct {
1679 pub fn iterate(self: *SuffixOp, index: usize) ?*Node {1684 pub fn iterate(self: *SuffixOp, index: usize) ?*Node {
1680 var i = index;1685 var i = index;
16811686
1682 if (i < 1) return self.lhs;1687 switch (self.lhs) {
1683 i -= 1;1688 .node => |node| {
1689 if (i == 0) return node;
1690 i -= 1;
1691 },
1692 .dot => {},
1693 }
16841694
1685 switch (self.op) {1695 switch (self.op) {
1686 .Call => |*call_info| {1696 .Call => |*call_info| {
...@@ -1721,7 +1731,10 @@ pub const Node = struct {...@@ -1721,7 +1731,10 @@ pub const Node = struct {
1721 .Call => |*call_info| if (call_info.async_token) |async_token| return async_token,1731 .Call => |*call_info| if (call_info.async_token) |async_token| return async_token,
1722 else => {},1732 else => {},
1723 }1733 }
1724 return self.lhs.firstToken();1734 switch (self.lhs) {
1735 .node => |node| return node.firstToken(),
1736 .dot => |dot| return dot,
1737 }
1725 }1738 }
17261739
1727 pub fn lastToken(self: *const SuffixOp) TokenIndex {1740 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 {...@@ -1026,16 +1026,16 @@ fn parseWhileExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1026/// CurlySuffixExpr <- TypeExpr InitList?1026/// CurlySuffixExpr <- TypeExpr InitList?
1027fn parseCurlySuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {1027fn parseCurlySuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1028 const type_expr = (try parseTypeExpr(arena, it, tree)) orelse return null;1028 const type_expr = (try parseTypeExpr(arena, it, tree)) orelse return null;
1029 const init_list = (try parseInitList(arena, it, tree)) orelse return type_expr;1029 const suffix_op = (try parseInitList(arena, it, tree)) orelse return type_expr;
1030 init_list.cast(Node.SuffixOp).?.lhs = type_expr;1030 suffix_op.lhs.node = type_expr;
1031 return init_list;1031 return &suffix_op.base;
1032}1032}
10331033
1034/// InitList1034/// InitList
1035/// <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE1035/// <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE
1036/// / LBRACE Expr (COMMA Expr)* COMMA? RBRACE1036/// / LBRACE Expr (COMMA Expr)* COMMA? RBRACE
1037/// / LBRACE RBRACE1037/// / LBRACE RBRACE
1038fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {1038fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.SuffixOp {
1039 const lbrace = eatToken(it, .LBrace) orelse return null;1039 const lbrace = eatToken(it, .LBrace) orelse return null;
1040 var init_list = Node.SuffixOp.Op.InitList.init(arena);1040 var init_list = Node.SuffixOp.Op.InitList.init(arena);
10411041
...@@ -1064,11 +1064,11 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1064,11 +1064,11 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1064 const node = try arena.create(Node.SuffixOp);1064 const node = try arena.create(Node.SuffixOp);
1065 node.* = Node.SuffixOp{1065 node.* = Node.SuffixOp{
1066 .base = Node{ .id = .SuffixOp },1066 .base = Node{ .id = .SuffixOp },
1067 .lhs = undefined, // set by caller1067 .lhs = .{.node = undefined}, // set by caller
1068 .op = op,1068 .op = op,
1069 .rtoken = try expectToken(it, tree, .RBrace),1069 .rtoken = try expectToken(it, tree, .RBrace),
1070 };1070 };
1071 return &node.base;1071 return node;
1072}1072}
10731073
1074/// TypeExpr <- PrefixTypeOp* ErrorUnionExpr1074/// TypeExpr <- PrefixTypeOp* ErrorUnionExpr
...@@ -1117,7 +1117,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1117,7 +1117,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
11171117
1118 while (try parseSuffixOp(arena, it, tree)) |node| {1118 while (try parseSuffixOp(arena, it, tree)) |node| {
1119 switch (node.id) {1119 switch (node.id) {
1120 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res,1120 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res},
1121 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,1121 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,
1122 else => unreachable,1122 else => unreachable,
1123 }1123 }
...@@ -1133,7 +1133,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1133,7 +1133,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1133 const node = try arena.create(Node.SuffixOp);1133 const node = try arena.create(Node.SuffixOp);
1134 node.* = Node.SuffixOp{1134 node.* = Node.SuffixOp{
1135 .base = Node{ .id = .SuffixOp },1135 .base = Node{ .id = .SuffixOp },
1136 .lhs = res,1136 .lhs = .{.node = res},
1137 .op = Node.SuffixOp.Op{1137 .op = Node.SuffixOp.Op{
1138 .Call = Node.SuffixOp.Op.Call{1138 .Call = Node.SuffixOp.Op.Call{
1139 .params = params.list,1139 .params = params.list,
...@@ -1150,7 +1150,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1150,7 +1150,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1150 while (true) {1150 while (true) {
1151 if (try parseSuffixOp(arena, it, tree)) |node| {1151 if (try parseSuffixOp(arena, it, tree)) |node| {
1152 switch (node.id) {1152 switch (node.id) {
1153 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res,1153 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res},
1154 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,1154 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,
1155 else => unreachable,1155 else => unreachable,
1156 }1156 }
...@@ -1161,7 +1161,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1161,7 +1161,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1161 const call = try arena.create(Node.SuffixOp);1161 const call = try arena.create(Node.SuffixOp);
1162 call.* = Node.SuffixOp{1162 call.* = Node.SuffixOp{
1163 .base = Node{ .id = .SuffixOp },1163 .base = Node{ .id = .SuffixOp },
1164 .lhs = res,1164 .lhs = .{.node = res},
1165 .op = Node.SuffixOp.Op{1165 .op = Node.SuffixOp.Op{
1166 .Call = Node.SuffixOp.Op.Call{1166 .Call = Node.SuffixOp.Op.Call{
1167 .params = params.list,1167 .params = params.list,
...@@ -1215,7 +1215,7 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N...@@ -1215,7 +1215,7 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
1215 return &node.base;1215 return &node.base;
1216 }1216 }
1217 if (try parseContainerDecl(arena, it, tree)) |node| return node;1217 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;
1219 if (try parseErrorSetDecl(arena, it, tree)) |node| return node;1219 if (try parseErrorSetDecl(arena, it, tree)) |node| return node;
1220 if (try parseFloatLiteral(arena, it, tree)) |node| return node;1220 if (try parseFloatLiteral(arena, it, tree)) |node| return node;
1221 if (try parseFnProto(arena, it, tree)) |node| return node;1221 if (try parseFnProto(arena, it, tree)) |node| return node;
...@@ -1494,16 +1494,28 @@ fn parseAsmExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1494,16 +1494,28 @@ fn parseAsmExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1494}1494}
14951495
1496/// DOT IDENTIFIER1496/// DOT IDENTIFIER
1497fn parseEnumLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {1497fn parseAnonLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1498 const dot = eatToken(it, .Period) orelse return null;1498 const dot = eatToken(it, .Period) orelse return null;
1499 const name = try expectToken(it, tree, .Identifier);1499
1500 const node = try arena.create(Node.EnumLiteral);1500 // anon enum literal
1501 node.* = Node.EnumLiteral{1501 if (eatToken(it, .Identifier)) |name| {
1502 .base = Node{ .id = .EnumLiteral },1502 const node = try arena.create(Node.EnumLiteral);
1503 .dot = dot,1503 node.* = Node.EnumLiteral{
1504 .name = name,1504 .base = Node{ .id = .EnumLiteral },
1505 };1505 .dot = dot,
1506 return &node.base;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;
1507}1519}
15081520
1509/// AsmOutput <- COLON AsmOutputList AsmInput?1521/// AsmOutput <- COLON AsmOutputList AsmInput?
lib/std/zig/parser_test.zig+17
...@@ -1,3 +1,20 @@...@@ -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
1test "zig fmt: async function" {18test "zig fmt: async function" {
2 try testCanonical(19 try testCanonical(
3 \\pub const Server = struct {20 \\pub const Server = struct {
lib/std/zig/render.zig+42-15
...@@ -538,9 +538,9 @@ fn renderExpression(...@@ -538,9 +538,9 @@ fn renderExpression(
538 try renderToken(tree, stream, async_token, indent, start_col, Space.Space);538 try renderToken(tree, stream, async_token, indent, start_col, Space.Space);
539 }539 }
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
545 if (call_info.params.len == 0) {545 if (call_info.params.len == 0) {
546 try renderToken(tree, stream, lparen, indent, start_col, Space.None);546 try renderToken(tree, stream, lparen, indent, start_col, Space.None);
...@@ -598,7 +598,7 @@ fn renderExpression(...@@ -598,7 +598,7 @@ fn renderExpression(
598 const lbracket = tree.prevToken(index_expr.firstToken());598 const lbracket = tree.prevToken(index_expr.firstToken());
599 const rbracket = tree.nextToken(index_expr.lastToken());599 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);
602 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [602 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
603603
604 const starts_with_comment = tree.tokens.at(lbracket + 1).id == .LineComment;604 const starts_with_comment = tree.tokens.at(lbracket + 1).id == .LineComment;
...@@ -616,18 +616,18 @@ fn renderExpression(...@@ -616,18 +616,18 @@ fn renderExpression(
616 },616 },
617617
618 ast.Node.SuffixOp.Op.Deref => {618 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);
620 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // .*620 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // .*
621 },621 },
622622
623 ast.Node.SuffixOp.Op.UnwrapOptional => {623 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);
625 try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, start_col, Space.None); // .625 try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, start_col, Space.None); // .
626 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ?626 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ?
627 },627 },
628628
629 @TagType(ast.Node.SuffixOp.Op).Slice => |range| {629 @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
632 const lbracket = tree.prevToken(range.start.firstToken());632 const lbracket = tree.prevToken(range.start.firstToken());
633 const dotdot = tree.nextToken(range.start.lastToken());633 const dotdot = tree.nextToken(range.start.lastToken());
...@@ -647,10 +647,16 @@ fn renderExpression(...@@ -647,10 +647,16 @@ fn renderExpression(
647 },647 },
648648
649 ast.Node.SuffixOp.Op.StructInitializer => |*field_inits| {649 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
652 if (field_inits.len == 0) {655 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 }
654 try renderToken(tree, stream, lbrace, indent + indent_delta, start_col, Space.None);660 try renderToken(tree, stream, lbrace, indent + indent_delta, start_col, Space.None);
655 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);661 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
656 }662 }
...@@ -691,7 +697,10 @@ fn renderExpression(...@@ -691,7 +697,10 @@ fn renderExpression(
691 break :blk;697 break :blk;
692 }698 }
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 }
695 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);704 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);
696 try renderExpression(allocator, stream, tree, indent, start_col, &field_init.base, Space.Space);705 try renderExpression(allocator, stream, tree, indent, start_col, &field_init.base, Space.Space);
697 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);706 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
...@@ -699,7 +708,10 @@ fn renderExpression(...@@ -699,7 +708,10 @@ fn renderExpression(
699708
700 if (!src_has_trailing_comma and src_same_line and expr_outputs_one_line) {709 if (!src_has_trailing_comma and src_same_line and expr_outputs_one_line) {
701 // render all on one line, no trailing comma710 // 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 }
703 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);715 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);
704716
705 var it = field_inits.iterator(0);717 var it = field_inits.iterator(0);
...@@ -719,7 +731,10 @@ fn renderExpression(...@@ -719,7 +731,10 @@ fn renderExpression(
719731
720 const new_indent = indent + indent_delta;732 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 }
723 try renderToken(tree, stream, lbrace, new_indent, start_col, Space.Newline);738 try renderToken(tree, stream, lbrace, new_indent, start_col, Space.Newline);
724739
725 var it = field_inits.iterator(0);740 var it = field_inits.iterator(0);
...@@ -743,23 +758,35 @@ fn renderExpression(...@@ -743,23 +758,35 @@ fn renderExpression(
743 },758 },
744759
745 ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| {760 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
748 if (exprs.len == 0) {766 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 }
750 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);771 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
751 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);772 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
752 }773 }
753 if (exprs.len == 1 and tree.tokens.at(exprs.at(0).*.lastToken() + 1).id == .RBrace) {774 if (exprs.len == 1 and tree.tokens.at(exprs.at(0).*.lastToken() + 1).id == .RBrace) {
754 const expr = exprs.at(0).*;775 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 }
757 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);781 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
758 try renderExpression(allocator, stream, tree, indent, start_col, expr, Space.None);782 try renderExpression(allocator, stream, tree, indent, start_col, expr, Space.None);
759 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);783 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
760 }784 }
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
764 // scan to find row size791 // scan to find row size
765 const maybe_row_size: ?usize = blk: {792 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);...@@ -1187,10 +1187,22 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
1187static const uint32_t VECTOR_INDEX_NONE = UINT32_MAX;1187static const uint32_t VECTOR_INDEX_NONE = UINT32_MAX;
1188static const uint32_t VECTOR_INDEX_RUNTIME = UINT32_MAX - 1;1188static const uint32_t VECTOR_INDEX_RUNTIME = UINT32_MAX - 1;
11891189
1190struct InferredStructField {
1191 ZigType *inferred_struct_type;
1192 Buf *field_name;
1193};
1194
1190struct ZigTypePointer {1195struct ZigTypePointer {
1191 ZigType *child_type;1196 ZigType *child_type;
1192 ZigType *slice_parent;1197 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
1194 PtrLen ptr_len;1206 PtrLen ptr_len;
1195 uint32_t explicit_alignment; // 0 means use ABI alignment1207 uint32_t explicit_alignment; // 0 means use ABI alignment
11961208
...@@ -1237,6 +1249,7 @@ struct TypeStructField {...@@ -1237,6 +1249,7 @@ struct TypeStructField {
1237enum ResolveStatus {1249enum ResolveStatus {
1238 ResolveStatusUnstarted,1250 ResolveStatusUnstarted,
1239 ResolveStatusInvalid,1251 ResolveStatusInvalid,
1252 ResolveStatusBeingInferred,
1240 ResolveStatusZeroBitsKnown,1253 ResolveStatusZeroBitsKnown,
1241 ResolveStatusAlignmentKnown,1254 ResolveStatusAlignmentKnown,
1242 ResolveStatusSizeKnown,1255 ResolveStatusSizeKnown,
...@@ -1285,6 +1298,7 @@ struct ZigTypeStruct {...@@ -1285,6 +1298,7 @@ struct ZigTypeStruct {
1285 bool requires_comptime;1298 bool requires_comptime;
1286 bool resolve_loop_flag_zero_bits;1299 bool resolve_loop_flag_zero_bits;
1287 bool resolve_loop_flag_other;1300 bool resolve_loop_flag_other;
1301 bool is_inferred;
1288};1302};
12891303
1290struct ZigTypeOptional {1304struct ZigTypeOptional {
...@@ -1741,6 +1755,7 @@ struct TypeId {...@@ -1741,6 +1755,7 @@ struct TypeId {
1741 union {1755 union {
1742 struct {1756 struct {
1743 ZigType *child_type;1757 ZigType *child_type;
1758 InferredStructField *inferred_struct_field;
1744 PtrLen ptr_len;1759 PtrLen ptr_len;
1745 uint32_t alignment;1760 uint32_t alignment;
17461761
...@@ -2812,7 +2827,7 @@ struct IrInstructionElemPtr {...@@ -2812,7 +2827,7 @@ struct IrInstructionElemPtr {
28122827
2813 IrInstruction *array_ptr;2828 IrInstruction *array_ptr;
2814 IrInstruction *elem_index;2829 IrInstruction *elem_index;
2815 IrInstruction *init_array_type;2830 AstNode *init_array_type_source_node;
2816 PtrLen ptr_len;2831 PtrLen ptr_len;
2817 bool safety_check_on;2832 bool safety_check_on;
2818};2833};
...@@ -2909,11 +2924,11 @@ struct IrInstructionResizeSlice {...@@ -2909,11 +2924,11 @@ struct IrInstructionResizeSlice {
2909struct IrInstructionContainerInitList {2924struct IrInstructionContainerInitList {
2910 IrInstruction base;2925 IrInstruction base;
29112926
2912 IrInstruction *container_type;
2913 IrInstruction *elem_type;2927 IrInstruction *elem_type;
2914 size_t item_count;2928 size_t item_count;
2915 IrInstruction **elem_result_loc_list;2929 IrInstruction **elem_result_loc_list;
2916 IrInstruction *result_loc;2930 IrInstruction *result_loc;
2931 AstNode *init_array_type_source_node;
2917};2932};
29182933
2919struct IrInstructionContainerInitFieldsField {2934struct IrInstructionContainerInitFieldsField {
...@@ -2926,7 +2941,6 @@ struct IrInstructionContainerInitFieldsField {...@@ -2926,7 +2941,6 @@ struct IrInstructionContainerInitFieldsField {
2926struct IrInstructionContainerInitFields {2941struct IrInstructionContainerInitFields {
2927 IrInstruction base;2942 IrInstruction base;
29282943
2929 IrInstruction *container_type;
2930 size_t field_count;2944 size_t field_count;
2931 IrInstructionContainerInitFieldsField *fields;2945 IrInstructionContainerInitFieldsField *fields;
2932 IrInstruction *result_loc;2946 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...@@ -140,7 +140,6 @@ void init_scope(CodeGen *g, Scope *dest, ScopeId id, AstNode *source_node, Scope
140static ScopeDecls *create_decls_scope(CodeGen *g, AstNode *node, Scope *parent, ZigType *container_type,140static ScopeDecls *create_decls_scope(CodeGen *g, AstNode *node, Scope *parent, ZigType *container_type,
141 ZigType *import, Buf *bare_name)141 ZigType *import, Buf *bare_name)
142{142{
143 assert(node == nullptr || node->type == NodeTypeContainerDecl || node->type == NodeTypeFnCallExpr);
144 ScopeDecls *scope = allocate<ScopeDecls>(1);143 ScopeDecls *scope = allocate<ScopeDecls>(1);
145 init_scope(g, &scope->base, ScopeIdDecls, node, parent);144 init_scope(g, &scope->base, ScopeIdDecls, node, parent);
146 scope->decl_table.init(4);145 scope->decl_table.init(4);
...@@ -346,6 +345,8 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {...@@ -346,6 +345,8 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
346 switch (status) {345 switch (status) {
347 case ResolveStatusInvalid:346 case ResolveStatusInvalid:
348 zig_unreachable();347 zig_unreachable();
348 case ResolveStatusBeingInferred:
349 zig_unreachable();
349 case ResolveStatusUnstarted:350 case ResolveStatusUnstarted:
350 case ResolveStatusZeroBitsKnown:351 case ResolveStatusZeroBitsKnown:
351 return true;352 return true;
...@@ -362,6 +363,8 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {...@@ -362,6 +363,8 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
362 switch (status) {363 switch (status) {
363 case ResolveStatusInvalid:364 case ResolveStatusInvalid:
364 zig_unreachable();365 zig_unreachable();
366 case ResolveStatusBeingInferred:
367 zig_unreachable();
365 case ResolveStatusUnstarted:368 case ResolveStatusUnstarted:
366 return true;369 return true;
367 case ResolveStatusZeroBitsKnown:370 case ResolveStatusZeroBitsKnown:
...@@ -483,7 +486,7 @@ ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {...@@ -483,7 +486,7 @@ ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {
483ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const,486ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const,
484 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,487 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
485 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero,488 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)
487{490{
488 assert(ptr_len != PtrLenC || allow_zero);491 assert(ptr_len != PtrLenC || allow_zero);
489 assert(!type_is_invalid(child_type));492 assert(!type_is_invalid(child_type));
...@@ -506,7 +509,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con...@@ -506,7 +509,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
506 TypeId type_id = {};509 TypeId type_id = {};
507 ZigType **parent_pointer = nullptr;510 ZigType **parent_pointer = nullptr;
508 if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle ||511 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)
510 {513 {
511 type_id.id = ZigTypeIdPointer;514 type_id.id = ZigTypeIdPointer;
512 type_id.data.pointer.child_type = child_type;515 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...@@ -518,6 +521,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
518 type_id.data.pointer.ptr_len = ptr_len;521 type_id.data.pointer.ptr_len = ptr_len;
519 type_id.data.pointer.allow_zero = allow_zero;522 type_id.data.pointer.allow_zero = allow_zero;
520 type_id.data.pointer.vector_index = vector_index;523 type_id.data.pointer.vector_index = vector_index;
524 type_id.data.pointer.inferred_struct_field = inferred_struct_field;
521525
522 auto existing_entry = g->type_table.maybe_get(type_id);526 auto existing_entry = g->type_table.maybe_get(type_id);
523 if (existing_entry)527 if (existing_entry)
...@@ -545,8 +549,15 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con...@@ -545,8 +549,15 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
545 }549 }
546 buf_resize(&entry->name, 0);550 buf_resize(&entry->name, 0);
547 if (host_int_bytes == 0 && byte_alignment == 0 && vector_index == VECTOR_INDEX_NONE) {551 if (host_int_bytes == 0 && byte_alignment == 0 && vector_index == VECTOR_INDEX_NONE) {
548 buf_appendf(&entry->name, "%s%s%s%s%s",552 if (inferred_struct_field == nullptr) {
549 star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));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 }
550 } else if (host_int_bytes == 0 && vector_index == VECTOR_INDEX_NONE) {561 } else if (host_int_bytes == 0 && vector_index == VECTOR_INDEX_NONE) {
551 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,562 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
552 const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));563 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...@@ -603,6 +614,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
603 entry->data.pointer.host_int_bytes = host_int_bytes;614 entry->data.pointer.host_int_bytes = host_int_bytes;
604 entry->data.pointer.allow_zero = allow_zero;615 entry->data.pointer.allow_zero = allow_zero;
605 entry->data.pointer.vector_index = vector_index;616 entry->data.pointer.vector_index = vector_index;
617 entry->data.pointer.inferred_struct_field = inferred_struct_field;
606618
607 if (parent_pointer) {619 if (parent_pointer) {
608 *parent_pointer = entry;620 *parent_pointer = entry;
...@@ -617,12 +629,12 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -617,12 +629,12 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
617 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero)629 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero)
618{630{
619 return get_pointer_to_type_extra2(g, child_type, is_const, is_volatile, ptr_len,631 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);
621}633}
622634
623ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) {635ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) {
624 return get_pointer_to_type_extra2(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0, false,636 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);
626}638}
627639
628ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {640ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
...@@ -2079,7 +2091,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {...@@ -2079,7 +2091,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
2079 }2091 }
20802092
2081 assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0);2093 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
2084 size_t field_count = struct_type->data.structure.src_field_count;2096 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) {...@@ -2667,7 +2679,6 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
2667 return ErrorNone;2679 return ErrorNone;
26682680
2669 AstNode *decl_node = struct_type->data.structure.decl_node;2681 AstNode *decl_node = struct_type->data.structure.decl_node;
2670 assert(decl_node->type == NodeTypeContainerDecl);
26712682
2672 if (struct_type->data.structure.resolve_loop_flag_zero_bits) {2683 if (struct_type->data.structure.resolve_loop_flag_zero_bits) {
2673 if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {2684 if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
...@@ -2678,29 +2689,46 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2678,29 +2689,46 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
2678 }2689 }
2679 return ErrorSemanticAnalyzeFail;2690 return ErrorSemanticAnalyzeFail;
2680 }2691 }
2681
2682 struct_type->data.structure.resolve_loop_flag_zero_bits = true;2692 struct_type->data.structure.resolve_loop_flag_zero_bits = true;
26832693
2684 assert(!struct_type->data.structure.fields);2694 size_t field_count;
2685 size_t field_count = decl_node->data.container_decl.fields.length;2695 if (decl_node->type == NodeTypeContainerDecl) {
2686 struct_type->data.structure.src_field_count = (uint32_t)field_count;2696 field_count = decl_node->data.container_decl.fields.length;
2687 struct_type->data.structure.fields = allocate<TypeStructField>(field_count);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
2688 struct_type->data.structure.fields_by_name.init(field_count);2708 struct_type->data.structure.fields_by_name.init(field_count);
26892709
2690 Scope *scope = &struct_type->data.structure.decls_scope->base;2710 Scope *scope = &struct_type->data.structure.decls_scope->base;
26912711
2692 size_t gen_field_index = 0;2712 size_t gen_field_index = 0;
2693 for (size_t i = 0; i < field_count; i += 1) {2713 for (size_t i = 0; i < field_count; i += 1) {
2694 AstNode *field_node = decl_node->data.container_decl.fields.at(i);
2695 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];2714 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) {2716 AstNode *field_node;
2700 add_node_error(g, field_node, buf_sprintf("struct field missing type"));2717 if (decl_node->type == NodeTypeContainerDecl) {
2701 struct_type->data.structure.resolve_status = ResolveStatusInvalid;2718 field_node = decl_node->data.container_decl.fields.at(i);
2702 return ErrorSemanticAnalyzeFail;2719 type_struct_field->name = field_node->data.struct_field.name;
2703 }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
2705 auto field_entry = struct_type->data.structure.fields_by_name.put_unique(type_struct_field->name, type_struct_field);2733 auto field_entry = struct_type->data.structure.fields_by_name.put_unique(type_struct_field->name, type_struct_field);
2706 if (field_entry != nullptr) {2734 if (field_entry != nullptr) {
...@@ -2711,16 +2739,21 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2711,16 +2739,21 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
2711 return ErrorSemanticAnalyzeFail;2739 return ErrorSemanticAnalyzeFail;
2712 }2740 }
27132741
2714 ConstExprValue *field_type_val = analyze_const_value(g, scope,2742 ConstExprValue *field_type_val;
2715 field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef);2743 if (decl_node->type == NodeTypeContainerDecl) {
2716 if (type_is_invalid(field_type_val->type)) {2744 field_type_val = analyze_const_value(g, scope,
2717 struct_type->data.structure.resolve_status = ResolveStatusInvalid;2745 field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef);
2718 return ErrorSemanticAnalyzeFail;2746 if (type_is_invalid(field_type_val->type)) {
2719 }2747 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2720 assert(field_type_val->special != ConstValSpecialRuntime);2748 return ErrorSemanticAnalyzeFail;
2721 type_struct_field->type_val = field_type_val;2749 }
2722 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)2750 assert(field_type_val->special != ConstValSpecialRuntime);
2723 return ErrorSemanticAnalyzeFail;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
2725 bool field_is_opaque_type;2758 bool field_is_opaque_type;
2726 if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) {2759 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) {...@@ -2804,7 +2837,7 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
2804 }2837 }
28052838
2806 struct_type->data.structure.resolve_loop_flag_other = true;2839 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
2809 size_t field_count = struct_type->data.structure.src_field_count;2842 size_t field_count = struct_type->data.structure.src_field_count;
2810 bool packed = struct_type->data.structure.layout == ContainerLayoutPacked;2843 bool packed = struct_type->data.structure.layout == ContainerLayoutPacked;
...@@ -2814,7 +2847,8 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {...@@ -2814,7 +2847,8 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
2814 if (field->gen_index == SIZE_MAX)2847 if (field->gen_index == SIZE_MAX)
2815 continue;2848 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;
2818 if (align_expr != nullptr) {2852 if (align_expr != nullptr) {
2819 if (!analyze_const_align(g, &struct_type->data.structure.decls_scope->base, align_expr,2853 if (!analyze_const_align(g, &struct_type->data.structure.decls_scope->base, align_expr,
2820 &field->align))2854 &field->align))
...@@ -5413,6 +5447,12 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {...@@ -5413,6 +5447,12 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
5413 if (type_entry->one_possible_value != OnePossibleValueInvalid)5447 if (type_entry->one_possible_value != OnePossibleValueInvalid)
5414 return type_entry->one_possible_value;5448 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
5416 Error err;5456 Error err;
5417 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))5457 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
5418 return OnePossibleValueInvalid;5458 return OnePossibleValueInvalid;
...@@ -6132,6 +6172,8 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -6132,6 +6172,8 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
6132 continue;6172 continue;
6133 if (instruction->ref_count == 0)6173 if (instruction->ref_count == 0)
6134 continue;6174 continue;
6175 if ((err = type_resolve(g, instruction->value.type, ResolveStatusZeroBitsKnown)))
6176 return ErrorSemanticAnalyzeFail;
6135 if (!type_has_bits(instruction->value.type))6177 if (!type_has_bits(instruction->value.type))
6136 continue;6178 continue;
6137 if (scope_needs_spill(instruction->scope)) {6179 if (scope_needs_spill(instruction->scope)) {
...@@ -6271,6 +6313,8 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {...@@ -6271,6 +6313,8 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
6271 switch (status) {6313 switch (status) {
6272 case ResolveStatusUnstarted:6314 case ResolveStatusUnstarted:
6273 return ErrorNone;6315 return ErrorNone;
6316 case ResolveStatusBeingInferred:
6317 zig_unreachable();
6274 case ResolveStatusInvalid:6318 case ResolveStatusInvalid:
6275 zig_unreachable();6319 zig_unreachable();
6276 case ResolveStatusZeroBitsKnown:6320 case ResolveStatusZeroBitsKnown:
...@@ -6995,7 +7039,16 @@ bool type_id_eql(TypeId a, TypeId b) {...@@ -6995,7 +7039,16 @@ bool type_id_eql(TypeId a, TypeId b) {
6995 a.data.pointer.alignment == b.data.pointer.alignment &&7039 a.data.pointer.alignment == b.data.pointer.alignment &&
6996 a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&7040 a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&
6997 a.data.pointer.vector_index == b.data.pointer.vector_index &&7041 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 );
6999 case ZigTypeIdArray:7052 case ZigTypeIdArray:
7000 return a.data.array.child_type == b.data.array.child_type &&7053 return a.data.array.child_type == b.data.array.child_type &&
7001 a.data.array.size == b.data.array.size;7054 a.data.array.size == b.data.array.size;
...@@ -7808,7 +7861,6 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS...@@ -7808,7 +7861,6 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
7808 ZigLLVMDIScope *di_scope;7861 ZigLLVMDIScope *di_scope;
7809 unsigned line;7862 unsigned line;
7810 if (decl_node != nullptr) {7863 if (decl_node != nullptr) {
7811 assert(decl_node->type == NodeTypeContainerDecl);
7812 Scope *scope = &struct_type->data.structure.decls_scope->base;7864 Scope *scope = &struct_type->data.structure.decls_scope->base;
7813 ZigType *import = get_scope_import(scope);7865 ZigType *import = get_scope_import(scope);
7814 di_file = import->data.structure.root_struct->di_file;7866 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...@@ -8011,7 +8063,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
8011 }8063 }
8012 unsigned line;8064 unsigned line;
8013 if (decl_node != nullptr) {8065 if (decl_node != nullptr) {
8014 AstNode *field_node = decl_node->data.container_decl.fields.at(i);8066 AstNode *field_node = field->decl_node;
8015 line = field_node->line + 1;8067 line = field_node->line + 1;
8016 } else {8068 } else {
8017 line = 0;8069 line = 0;
...@@ -8307,12 +8359,12 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus...@@ -8307,12 +8359,12 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus
8307 if (type->data.pointer.vector_index == VECTOR_INDEX_NONE) {8359 if (type->data.pointer.vector_index == VECTOR_INDEX_NONE) {
8308 peer_type = get_pointer_to_type_extra2(g, elem_type, false, false,8360 peer_type = get_pointer_to_type_extra2(g, elem_type, false, false,
8309 PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false,8361 PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false,
8310 VECTOR_INDEX_NONE);8362 VECTOR_INDEX_NONE, nullptr);
8311 } else {8363 } else {
8312 uint32_t host_vec_len = type->data.pointer.host_int_bytes;8364 uint32_t host_vec_len = type->data.pointer.host_int_bytes;
8313 ZigType *host_vec_type = get_vector_type(g, host_vec_len, elem_type);8365 ZigType *host_vec_type = get_vector_type(g, host_vec_len, elem_type);
8314 peer_type = get_pointer_to_type_extra2(g, host_vec_type, false, false,8366 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);
8316 }8368 }
8317 type->llvm_type = get_llvm_type(g, peer_type);8369 type->llvm_type = get_llvm_type(g, peer_type);
8318 type->llvm_di_type = get_llvm_di_type(g, peer_type);8370 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,...@@ -9038,4 +9090,3 @@ Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str,
9038 *out_import = add_source_file(g, target_package, resolved_path, import_code, source_kind);9090 *out_import = add_source_file(g, target_package, resolved_path, import_code, source_kind);
9039 return ErrorNone;9091 return ErrorNone;
9040}9092}
9041
src/analyze.hpp+1-1
...@@ -24,7 +24,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type,...@@ -24,7 +24,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type,
24ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type,24ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type,
25 bool is_const, bool is_volatile, PtrLen ptr_len,25 bool is_const, bool is_volatile, PtrLen ptr_len,
26 uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count,26 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);
28uint64_t type_size(CodeGen *g, ZigType *type_entry);28uint64_t type_size(CodeGen *g, ZigType *type_entry);
29uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);29uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);
30ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);30ZigType *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) {...@@ -821,7 +821,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
821 break;821 break;
822 }822 }
823 case NodeTypeContainerInitExpr:823 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 }
825 if (node->data.container_init_expr.kind == ContainerInitKindStruct) {827 if (node->data.container_init_expr.kind == ContainerInitKindStruct) {
826 fprintf(ar->f, "{\n");828 fprintf(ar->f, "{\n");
827 ar->indent += ar->indent_size;829 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...@@ -202,6 +202,10 @@ static Buf *get_anon_type_name(CodeGen *codegen, IrExecutable *exec, const char
202 Scope *scope, AstNode *source_node, Buf *out_bare_name);202 Scope *scope, AstNode *source_node, Buf *out_bare_name);
203static ResultLocCast *ir_build_cast_result_loc(IrBuilder *irb, IrInstruction *dest_type,203static ResultLocCast *ir_build_cast_result_loc(IrBuilder *irb, IrInstruction *dest_type,
204 ResultLoc *parent_result_loc);204 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
206static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {210static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
207 assert(get_src_ptr_type(const_val->type) != nullptr);211 assert(get_src_ptr_type(const_val->type) != nullptr);
...@@ -1350,18 +1354,17 @@ static IrInstruction *ir_build_return_ptr(IrAnalyze *ira, IrInstruction *source_...@@ -1350,18 +1354,17 @@ static IrInstruction *ir_build_return_ptr(IrAnalyze *ira, IrInstruction *source_
13501354
1351static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,1355static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
1352 IrInstruction *array_ptr, IrInstruction *elem_index, bool safety_check_on, PtrLen ptr_len,1356 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)
1354{1358{
1355 IrInstructionElemPtr *instruction = ir_build_instruction<IrInstructionElemPtr>(irb, scope, source_node);1359 IrInstructionElemPtr *instruction = ir_build_instruction<IrInstructionElemPtr>(irb, scope, source_node);
1356 instruction->array_ptr = array_ptr;1360 instruction->array_ptr = array_ptr;
1357 instruction->elem_index = elem_index;1361 instruction->elem_index = elem_index;
1358 instruction->safety_check_on = safety_check_on;1362 instruction->safety_check_on = safety_check_on;
1359 instruction->ptr_len = ptr_len;1363 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
1362 ir_ref_instruction(array_ptr, irb->current_basic_block);1366 ir_ref_instruction(array_ptr, irb->current_basic_block);
1363 ir_ref_instruction(elem_index, irb->current_basic_block);1367 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
1366 return &instruction->base;1369 return &instruction->base;
1367}1370}
...@@ -1575,17 +1578,16 @@ static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *sour...@@ -1575,17 +1578,16 @@ static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *sour
1575}1578}
15761579
1577static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node,1580static 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,1581 size_t item_count, IrInstruction **elem_result_loc_list, IrInstruction *result_loc,
1579 IrInstruction *result_loc)1582 AstNode *init_array_type_source_node)
1580{1583{
1581 IrInstructionContainerInitList *container_init_list_instruction =1584 IrInstructionContainerInitList *container_init_list_instruction =
1582 ir_build_instruction<IrInstructionContainerInitList>(irb, scope, source_node);1585 ir_build_instruction<IrInstructionContainerInitList>(irb, scope, source_node);
1583 container_init_list_instruction->container_type = container_type;
1584 container_init_list_instruction->item_count = item_count;1586 container_init_list_instruction->item_count = item_count;
1585 container_init_list_instruction->elem_result_loc_list = elem_result_loc_list;1587 container_init_list_instruction->elem_result_loc_list = elem_result_loc_list;
1586 container_init_list_instruction->result_loc = result_loc;1588 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);
1589 for (size_t i = 0; i < item_count; i += 1) {1591 for (size_t i = 0; i < item_count; i += 1) {
1590 ir_ref_instruction(elem_result_loc_list[i], irb->current_basic_block);1592 ir_ref_instruction(elem_result_loc_list[i], irb->current_basic_block);
1591 }1593 }
...@@ -1595,17 +1597,14 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope,...@@ -1595,17 +1597,14 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope,
1595}1597}
15961598
1597static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scope, AstNode *source_node,1599static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scope, AstNode *source_node,
1598 IrInstruction *container_type, size_t field_count, IrInstructionContainerInitFieldsField *fields,1600 size_t field_count, IrInstructionContainerInitFieldsField *fields, IrInstruction *result_loc)
1599 IrInstruction *result_loc)
1600{1601{
1601 IrInstructionContainerInitFields *container_init_fields_instruction =1602 IrInstructionContainerInitFields *container_init_fields_instruction =
1602 ir_build_instruction<IrInstructionContainerInitFields>(irb, scope, source_node);1603 ir_build_instruction<IrInstructionContainerInitFields>(irb, scope, source_node);
1603 container_init_fields_instruction->container_type = container_type;
1604 container_init_fields_instruction->field_count = field_count;1604 container_init_fields_instruction->field_count = field_count;
1605 container_init_fields_instruction->fields = fields;1605 container_init_fields_instruction->fields = fields;
1606 container_init_fields_instruction->result_loc = result_loc;1606 container_init_fields_instruction->result_loc = result_loc;
16071607
1608 ir_ref_instruction(container_type, irb->current_basic_block);
1609 for (size_t i = 0; i < field_count; i += 1) {1608 for (size_t i = 0; i < field_count; i += 1) {
1610 ir_ref_instruction(fields[i].result_loc, irb->current_basic_block);1609 ir_ref_instruction(fields[i].result_loc, irb->current_basic_block);
1611 }1610 }
...@@ -3084,7 +3083,7 @@ static IrInstruction *ir_build_resolve_result(IrBuilder *irb, Scope *scope, AstN...@@ -3084,7 +3083,7 @@ static IrInstruction *ir_build_resolve_result(IrBuilder *irb, Scope *scope, AstN
3084 instruction->result_loc = result_loc;3083 instruction->result_loc = result_loc;
3085 instruction->ty = ty;3084 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
3089 return &instruction->base;3088 return &instruction->base;
3090}3089}
...@@ -6127,28 +6126,46 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A...@@ -6127,28 +6126,46 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
6127 AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;6126 AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
6128 ContainerInitKind kind = container_init_expr->kind;6127 ContainerInitKind kind = container_init_expr->kind;
61296128
6130 IrInstruction *container_type = nullptr;6129 ResultLocCast *result_loc_cast = nullptr;
6131 IrInstruction *elem_type = nullptr;6130 ResultLoc *child_result_loc;
6132 if (container_init_expr->type->type == NodeTypeInferredArrayType) {6131 AstNode *init_array_type_source_node;
6133 elem_type = ir_gen_node(irb, container_init_expr->type->data.inferred_array_type.child_type, scope);6132 if (container_init_expr->type != nullptr) {
6134 if (elem_type == irb->codegen->invalid_instruction)6133 IrInstruction *container_type;
6135 return elem_type;6134 if (container_init_expr->type->type == NodeTypeInferredArrayType) {
6136 } else {6135 if (kind == ContainerInitKindStruct) {
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) {
6145 add_node_error(irb->codegen, container_init_expr->type,6136 add_node_error(irb->codegen, container_init_expr->type,
6146 buf_sprintf("initializing array with struct syntax"));6137 buf_sprintf("initializing array with struct syntax"));
6147 return irb->codegen->invalid_instruction;6138 return irb->codegen->invalid_instruction;
6148 }6139 }
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,6153 result_loc_cast = ir_build_cast_result_loc(irb, container_type, parent_result_loc);
6151 container_type);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
6153 size_t field_count = container_init_expr->entries.length;6170 size_t field_count = container_init_expr->entries.length;
6154 IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count);6171 IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count);
...@@ -6176,29 +6193,27 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A...@@ -6176,29 +6193,27 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
6176 fields[i].source_node = entry_node;6193 fields[i].source_node = entry_node;
6177 fields[i].result_loc = field_ptr;6194 fields[i].result_loc = field_ptr;
6178 }6195 }
6179 IrInstruction *init_fields = ir_build_container_init_fields(irb, scope, node, container_type,6196 IrInstruction *result = ir_build_container_init_fields(irb, scope, node, field_count,
6180 field_count, fields, container_ptr);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);
6183 }6203 }
6184 case ContainerInitKindArray: {6204 case ContainerInitKindArray: {
6185 size_t item_count = container_init_expr->entries.length;6205 size_t item_count = container_init_expr->entries.length;
61866206
6187 if (container_type == nullptr) {6207 IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc,
6188 IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count);6208 nullptr);
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);
61946209
6195 IrInstruction **result_locs = allocate<IrInstruction *>(item_count);6210 IrInstruction **result_locs = allocate<IrInstruction *>(item_count);
6196 for (size_t i = 0; i < item_count; i += 1) {6211 for (size_t i = 0; i < item_count; i += 1) {
6197 AstNode *expr_node = container_init_expr->entries.at(i);6212 AstNode *expr_node = container_init_expr->entries.at(i);
61986213
6199 IrInstruction *elem_index = ir_build_const_usize(irb, scope, expr_node, i);6214 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,6215 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr,
6201 false, PtrLenSingle, container_type);6216 elem_index, false, PtrLenSingle, init_array_type_source_node);
6202 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);6217 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
6203 result_loc_inst->base.id = ResultLocIdInstruction;6218 result_loc_inst->base.id = ResultLocIdInstruction;
6204 result_loc_inst->base.source_instruction = elem_ptr;6219 result_loc_inst->base.source_instruction = elem_ptr;
...@@ -6213,9 +6228,12 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A...@@ -6213,9 +6228,12 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
62136228
6214 result_locs[i] = elem_ptr;6229 result_locs[i] = elem_ptr;
6215 }6230 }
6216 IrInstruction *init_list = ir_build_container_init_list(irb, scope, node, container_type,6231 IrInstruction *result = ir_build_container_init_list(irb, scope, node, item_count,
6217 item_count, result_locs, container_ptr);6232 result_locs, container_ptr, init_array_type_source_node);
6218 return ir_lval_wrap(irb, scope, init_list, lval, parent_result_loc);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);
6219 }6237 }
6220 }6238 }
6221 zig_unreachable();6239 zig_unreachable();
...@@ -7935,14 +7953,14 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o...@@ -7935,14 +7953,14 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o
7935static Buf *get_anon_type_name(CodeGen *codegen, IrExecutable *exec, const char *kind_name,7953static Buf *get_anon_type_name(CodeGen *codegen, IrExecutable *exec, const char *kind_name,
7936 Scope *scope, AstNode *source_node, Buf *out_bare_name)7954 Scope *scope, AstNode *source_node, Buf *out_bare_name)
7937{7955{
7938 if (exec->name) {7956 if (exec != nullptr && exec->name) {
7939 ZigType *import = get_scope_import(scope);7957 ZigType *import = get_scope_import(scope);
7940 Buf *namespace_name = buf_alloc();7958 Buf *namespace_name = buf_alloc();
7941 append_namespace_qualification(codegen, namespace_name, import);7959 append_namespace_qualification(codegen, namespace_name, import);
7942 buf_append_buf(namespace_name, exec->name);7960 buf_append_buf(namespace_name, exec->name);
7943 buf_init_from_buf(out_bare_name, exec->name);7961 buf_init_from_buf(out_bare_name, exec->name);
7944 return namespace_name;7962 return namespace_name;
7945 } else if (exec->name_fn != nullptr) {7963 } else if (exec != nullptr && exec->name_fn != nullptr) {
7946 Buf *name = buf_alloc();7964 Buf *name = buf_alloc();
7947 buf_append_buf(name, &exec->name_fn->symbol_name);7965 buf_append_buf(name, &exec->name_fn->symbol_name);
7948 buf_appendf(name, "(");7966 buf_appendf(name, "(");
...@@ -15541,11 +15559,7 @@ static bool ir_result_has_type(ResultLoc *result_loc) {...@@ -15541,11 +15559,7 @@ static bool ir_result_has_type(ResultLoc *result_loc) {
15541static IrInstruction *ir_resolve_no_result_loc(IrAnalyze *ira, IrInstruction *suspend_source_instr,15559static IrInstruction *ir_resolve_no_result_loc(IrAnalyze *ira, IrInstruction *suspend_source_instr,
15542 ResultLoc *result_loc, ZigType *value_type, bool force_runtime, bool non_null_comptime)15560 ResultLoc *result_loc, ZigType *value_type, bool force_runtime, bool non_null_comptime)
15543{15561{
15544 Error err;
15545
15546 IrInstructionAllocaGen *alloca_gen = ir_build_alloca_gen(ira, suspend_source_instr, 0, "");15562 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;
15549 alloca_gen->base.value.type = get_pointer_to_type_extra(ira->codegen, value_type, false, false,15563 alloca_gen->base.value.type = get_pointer_to_type_extra(ira->codegen, value_type, false, false,
15550 PtrLenSingle, 0, 0, 0, false);15564 PtrLenSingle, 0, 0, 0, false);
15551 set_up_result_loc_for_inferred_comptime(&alloca_gen->base);15565 set_up_result_loc_for_inferred_comptime(&alloca_gen->base);
...@@ -15750,6 +15764,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe...@@ -15750,6 +15764,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
15750 return casted_value;15764 return casted_value;
15751 }15765 }
1575215766
15767 bool old_parent_result_loc_written = result_cast->parent->written;
15753 IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_cast->parent,15768 IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_cast->parent,
15754 dest_type, casted_value, force_runtime, non_null_comptime, true);15769 dest_type, casted_value, force_runtime, non_null_comptime, true);
15755 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||15770 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...@@ -15775,6 +15790,22 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
15775 parent_ptr_type->data.pointer.is_const, parent_ptr_type->data.pointer.is_volatile, PtrLenSingle,15790 parent_ptr_type->data.pointer.is_const, parent_ptr_type->data.pointer.is_volatile, PtrLenSingle,
15776 parent_ptr_align, 0, 0, parent_ptr_type->data.pointer.allow_zero);15791 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
15778 result_loc->written = true;15809 result_loc->written = true;
15779 result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr, parent_result_loc,15810 result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr, parent_result_loc,
15780 ptr_type, result_cast->base.source_instruction, false);15811 ptr_type, result_cast->base.source_instruction, false);
...@@ -15902,10 +15933,37 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s...@@ -15902,10 +15933,37 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
15902 return result_loc;15933 return result_loc;
15903}15934}
1590415935
15905static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrInstructionResolveResult *instruction) {15936static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira,
15906 ZigType *implicit_elem_type = ir_resolve_type(ira, instruction->ty->child);15937 IrInstructionResolveResult *instruction)
15907 if (type_is_invalid(implicit_elem_type))15938{
15908 return ira->codegen->invalid_instruction;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 }
15909 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,15967 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
15910 implicit_elem_type, nullptr, false, true, true);15968 implicit_elem_type, nullptr, false, true, true);
15911 if (result_loc != nullptr)15969 if (result_loc != nullptr)
...@@ -16267,13 +16325,78 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -16267,13 +16325,78 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
16267 return ir_const_void(ira, source_instr);16325 return ir_const_void(ira, source_instr);
16268 }16326 }
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
16272 if (ptr->value.type->data.pointer.is_const && !allow_write_through_const) {16394 if (ptr->value.type->data.pointer.is_const && !allow_write_through_const) {
16273 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));16395 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
16274 return ira->codegen->invalid_instruction;16396 return ira->codegen->invalid_instruction;
16275 }16397 }
1627616398
16399 ZigType *child_type = ptr->value.type->data.pointer.child_type;
16277 IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type);16400 IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type);
16278 if (value == ira->codegen->invalid_instruction)16401 if (value == ira->codegen->invalid_instruction)
16279 return ira->codegen->invalid_instruction;16402 return ira->codegen->invalid_instruction;
...@@ -17769,6 +17892,19 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -17769,6 +17892,19 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
17769 } else if (array_type->id == ZigTypeIdVector) {17892 } else if (array_type->id == ZigTypeIdVector) {
17770 // This depends on whether the element index is comptime, so it is computed later.17893 // This depends on whether the element index is comptime, so it is computed later.
17771 return_type = nullptr;17894 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);
17772 } else {17908 } else {
17773 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,17909 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
17774 buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name)));17910 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...@@ -17799,7 +17935,8 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
17799 return_type = get_pointer_to_type_extra2(ira->codegen, elem_type,17935 return_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
17800 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,17936 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
17801 elem_ptr_instruction->ptr_len,17937 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);
17803 } else if (return_type->data.pointer.explicit_alignment != 0) {17940 } else if (return_type->data.pointer.explicit_alignment != 0) {
17804 // figure out the largest alignment possible17941 // figure out the largest alignment possible
1780517942
...@@ -17837,7 +17974,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -17837,7 +17974,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
17837 if (array_ptr_val == nullptr)17974 if (array_ptr_val == nullptr)
17838 return ira->codegen->invalid_instruction;17975 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 {
17841 if (array_type->id == ZigTypeIdArray || array_type->id == ZigTypeIdVector) {17980 if (array_type->id == ZigTypeIdArray || array_type->id == ZigTypeIdVector) {
17842 array_ptr_val->data.x_array.special = ConstArraySpecialNone;17981 array_ptr_val->data.x_array.special = ConstArraySpecialNone;
17843 array_ptr_val->data.x_array.data.s_none.elements = create_const_vals(array_type->data.array.len);17982 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...@@ -17851,11 +17990,13 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
17851 elem_val->parent.data.p_array.elem_index = i;17990 elem_val->parent.data.p_array.elem_index = i;
17852 }17991 }
17853 } else if (is_slice(array_type)) {17992 } 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
17855 if (type_is_invalid(actual_array_type))17996 if (type_is_invalid(actual_array_type))
17856 return ira->codegen->invalid_instruction;17997 return ira->codegen->invalid_instruction;
17857 if (actual_array_type->id != ZigTypeIdArray) {17998 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,
17859 buf_sprintf("expected array type or [_], found slice"));18000 buf_sprintf("expected array type or [_], found slice"));
17860 return ira->codegen->invalid_instruction;18001 return ira->codegen->invalid_instruction;
17861 }18002 }
...@@ -17879,7 +18020,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -17879,7 +18020,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
17879 false);18020 false);
17880 array_ptr_val->data.x_struct.fields[slice_ptr_index].data.x_ptr.mut = ConstPtrMutInfer;18021 array_ptr_val->data.x_struct.fields[slice_ptr_index].data.x_ptr.mut = ConstPtrMutInfer;
17881 } else {18022 } 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,
17883 buf_sprintf("expected array type or [_], found '%s'",18024 buf_sprintf("expected array type or [_], found '%s'",
17884 buf_ptr(&array_type->name)));18025 buf_ptr(&array_type->name)));
17885 return ira->codegen->invalid_instruction;18026 return ira->codegen->invalid_instruction;
...@@ -18012,7 +18153,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -18012,7 +18153,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
18012 if (orig_array_ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {18153 if (orig_array_ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
18013 result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,18154 result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,
18014 elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index,18155 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);
18016 result->value.type = return_type;18157 result->value.type = return_type;
18017 result->value.special = ConstValSpecialStatic;18158 result->value.special = ConstValSpecialStatic;
18018 } else {18159 } else {
...@@ -18036,7 +18177,8 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -18036,7 +18177,8 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
18036 return_type = get_pointer_to_type_extra2(ira->codegen, elem_type,18177 return_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
18037 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,18178 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
18038 elem_ptr_instruction->ptr_len,18179 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);
18040 } else {18182 } else {
18041 // runtime known element index18183 // runtime known element index
18042 switch (type_requires_comptime(ira->codegen, return_type)) {18184 switch (type_requires_comptime(ira->codegen, return_type)) {
...@@ -18073,7 +18215,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -18073,7 +18215,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1807318215
18074 IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,18216 IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,
18075 elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, safety_check_on,18217 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);
18077 result->value.type = return_type;18219 result->value.type = return_type;
18078 return result;18220 return result;
18079}18221}
...@@ -18152,31 +18294,34 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction...@@ -18152,31 +18294,34 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction
18152 case OnePossibleValueNo:18294 case OnePossibleValueNo:
18153 break;18295 break;
18154 }18296 }
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;
18165 bool is_const = struct_ptr->value.type->data.pointer.is_const;18297 bool is_const = struct_ptr->value.type->data.pointer.is_const;
18166 bool is_volatile = struct_ptr->value.type->data.pointer.is_volatile;18298 bool is_volatile = struct_ptr->value.type->data.pointer.is_volatile;
18167 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,18299 ZigType *ptr_type;
18168 is_const, is_volatile, PtrLenSingle, field->align,18300 if (struct_type->data.structure.is_inferred) {
18169 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),18301 ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
18170 (uint32_t)host_int_bytes_for_result_type, false);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 }
18171 if (instr_is_comptime(struct_ptr)) {18319 if (instr_is_comptime(struct_ptr)) {
18172 ConstExprValue *ptr_val = ir_resolve_const(ira, struct_ptr, UndefBad);18320 ConstExprValue *ptr_val = ir_resolve_const(ira, struct_ptr, UndefBad);
18173 if (!ptr_val)18321 if (!ptr_val)
18174 return ira->codegen->invalid_instruction;18322 return ira->codegen->invalid_instruction;
1817518323
18176 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {18324 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
18180 ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);18325 ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
18181 if (struct_val == nullptr)18326 if (struct_val == nullptr)
18182 return ira->codegen->invalid_instruction;18327 return ira->codegen->invalid_instruction;
...@@ -18188,7 +18333,8 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction...@@ -18188,7 +18333,8 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction
18188 for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) {18333 for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) {
18189 ConstExprValue *field_val = &struct_val->data.x_struct.fields[i];18334 ConstExprValue *field_val = &struct_val->data.x_struct.fields[i];
18190 field_val->special = ConstValSpecialUndef;18335 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]);
18192 field_val->parent.id = ConstParentIdStruct;18338 field_val->parent.id = ConstParentIdStruct;
18193 field_val->parent.data.p_struct.struct_val = struct_val;18339 field_val->parent.data.p_struct.struct_val = struct_val;
18194 field_val->parent.data.p_struct.field_index = i;18340 field_val->parent.data.p_struct.field_index = i;
...@@ -18217,12 +18363,53 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction...@@ -18217,12 +18363,53 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction
18217 return result;18363 return result;
18218}18364}
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
18220static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,18400static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
18221 IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing)18401 IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing)
18222{18402{
18223 Error err;18403 Error err;
1822418404
18225 ZigType *bare_type = container_ref_type(container_type);18405 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
18226 if ((err = type_resolve(ira->codegen, bare_type, ResolveStatusZeroBitsKnown)))18413 if ((err = type_resolve(ira->codegen, bare_type, ResolveStatusZeroBitsKnown)))
18227 return ira->codegen->invalid_instruction;18414 return ira->codegen->invalid_instruction;
1822818415
...@@ -19997,6 +20184,11 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -19997,6 +20184,11 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
19997 return ira->codegen->invalid_instruction;20184 return ira->codegen->invalid_instruction;
19998 }20185 }
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
20000 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))20192 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
20001 return ira->codegen->invalid_instruction;20193 return ira->codegen->invalid_instruction;
2000220194
...@@ -20066,8 +20258,12 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -20066,8 +20258,12 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
20066 TypeStructField *field = &container_type->data.structure.fields[i];20258 TypeStructField *field = &container_type->data.structure.fields[i];
20067 if (field->init_val == nullptr) {20259 if (field->init_val == nullptr) {
20068 // it's not memoized. time to go analyze it20260 // it's not memoized. time to go analyze it
20069 assert(field->decl_node->type == NodeTypeStructField);20261 AstNode *init_node;
20070 AstNode *init_node = field->decl_node->data.struct_field.value;20262 if (field->decl_node->type == NodeTypeStructField) {
20263 init_node = field->decl_node->data.struct_field.value;
20264 } else {
20265 init_node = nullptr;
20266 }
20071 if (init_node == nullptr) {20267 if (init_node == nullptr) {
20072 ir_add_error_node(ira, instruction->source_node,20268 ir_add_error_node(ira, instruction->source_node,
20073 buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i].name)));20269 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...@@ -20124,14 +20320,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
20124static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,20320static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
20125 IrInstructionContainerInitList *instruction)20321 IrInstructionContainerInitList *instruction)
20126{20322{
20127 ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);20323 ir_assert(instruction->result_loc != nullptr, &instruction->base);
20128 if (type_is_invalid(container_type))20324 IrInstruction *result_loc = instruction->result_loc->child;
20129 return ira->codegen->invalid_instruction;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
20131 size_t elem_count = instruction->item_count;20331 size_t elem_count = instruction->item_count;
2013220332
20133 if (is_slice(container_type)) {20333 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,
20135 buf_sprintf("expected array type or [_], found slice"));20335 buf_sprintf("expected array type or [_], found slice"));
20136 return ira->codegen->invalid_instruction;20336 return ira->codegen->invalid_instruction;
20137 }20337 }
...@@ -20153,29 +20353,28 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,...@@ -20153,29 +20353,28 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
20153 return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, result_loc);20353 return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, result_loc);
20154 }20354 }
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 {
20157 ir_add_error_node(ira, instruction->base.source_node,20372 ir_add_error_node(ira, instruction->base.source_node,
20158 buf_sprintf("type '%s' does not support array initialization",20373 buf_sprintf("type '%s' does not support array initialization",
20159 buf_ptr(&container_type->name)));20374 buf_ptr(&container_type->name)));
20160 return ira->codegen->invalid_instruction;20375 return ira->codegen->invalid_instruction;
20161 }20376 }
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
20179 switch (type_has_one_possible_value(ira->codegen, container_type)) {20378 switch (type_has_one_possible_value(ira->codegen, container_type)) {
20180 case OnePossibleValueInvalid:20379 case OnePossibleValueInvalid:
20181 return ira->codegen->invalid_instruction;20380 return ira->codegen->invalid_instruction;
...@@ -20262,16 +20461,14 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,...@@ -20262,16 +20461,14 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
20262static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira,20461static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira,
20263 IrInstructionContainerInitFields *instruction)20462 IrInstructionContainerInitFields *instruction)
20264{20463{
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
20270 ir_assert(instruction->result_loc != nullptr, &instruction->base);20464 ir_assert(instruction->result_loc != nullptr, &instruction->base);
20271 IrInstruction *result_loc = instruction->result_loc->child;20465 IrInstruction *result_loc = instruction->result_loc->child;
20272 if (type_is_invalid(result_loc->value.type))20466 if (type_is_invalid(result_loc->value.type))
20273 return result_loc;20467 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
20275 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,20472 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
20276 instruction->field_count, instruction->fields, result_loc);20473 instruction->field_count, instruction->fields, result_loc);
20277}20474}
...@@ -24607,6 +24804,10 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -24607,6 +24804,10 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
24607 ZigType *src_type = ptr->value.type;24804 ZigType *src_type = ptr->value.type;
24608 assert(!type_is_invalid(src_type));24805 assert(!type_is_invalid(src_type));
2460924806
24807 if (src_type == dest_type) {
24808 return ptr;
24809 }
24810
24610 // We have a check for zero bits later so we use get_src_ptr_type to24811 // We have a check for zero bits later so we use get_src_ptr_type to
24611 // validate src_type and dest_type.24812 // validate src_type and dest_type.
2461224813
...@@ -24656,6 +24857,9 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -24656,6 +24857,9 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
24656 IrInstruction *result;24857 IrInstruction *result;
24657 if (ptr->value.data.x_ptr.mut == ConstPtrMutInfer) {24858 if (ptr->value.data.x_ptr.mut == ConstPtrMutInfer) {
24658 result = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on);24859 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;
24659 } else {24863 } else {
24660 result = ir_const(ira, source_instr, dest_type);24864 result = ir_const(ira, source_instr, dest_type);
24661 }24865 }
src/ir_print.cpp+4-4
...@@ -731,7 +731,6 @@ static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) {...@@ -731,7 +731,6 @@ static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) {
731}731}
732732
733static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerInitList *instruction) {733static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerInitList *instruction) {
734 ir_print_other_instruction(irp, instruction->container_type);
735 fprintf(irp->f, "{");734 fprintf(irp->f, "{");
736 if (instruction->item_count > 50) {735 if (instruction->item_count > 50) {
737 fprintf(irp->f, "...(%" ZIG_PRI_usize " items)...", instruction->item_count);736 fprintf(irp->f, "...(%" ZIG_PRI_usize " items)...", instruction->item_count);
...@@ -743,11 +742,11 @@ static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerIni...@@ -743,11 +742,11 @@ static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerIni
743 ir_print_other_instruction(irp, result_loc);742 ir_print_other_instruction(irp, result_loc);
744 }743 }
745 }744 }
746 fprintf(irp->f, "}");745 fprintf(irp->f, "}result=");
746 ir_print_other_instruction(irp, instruction->result_loc);
747}747}
748748
749static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerInitFields *instruction) {749static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerInitFields *instruction) {
750 ir_print_other_instruction(irp, instruction->container_type);
751 fprintf(irp->f, "{");750 fprintf(irp->f, "{");
752 for (size_t i = 0; i < instruction->field_count; i += 1) {751 for (size_t i = 0; i < instruction->field_count; i += 1) {
753 IrInstructionContainerInitFieldsField *field = &instruction->fields[i];752 IrInstructionContainerInitFieldsField *field = &instruction->fields[i];
...@@ -755,7 +754,8 @@ static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerI...@@ -755,7 +754,8 @@ static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerI
755 fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field->name));754 fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field->name));
756 ir_print_other_instruction(irp, field->result_loc);755 ir_print_other_instruction(irp, field->result_loc);
757 }756 }
758 fprintf(irp->f, "} // container init");757 fprintf(irp->f, "}result=");
758 ir_print_other_instruction(irp, instruction->result_loc);
759}759}
760760
761static void ir_print_unreachable(IrPrint *irp, IrInstructionUnreachable *instruction) {761static 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);...@@ -81,7 +81,7 @@ static AstNode *ast_parse_for_type_expr(ParseContext *pc);
81static AstNode *ast_parse_while_type_expr(ParseContext *pc);81static AstNode *ast_parse_while_type_expr(ParseContext *pc);
82static AstNode *ast_parse_switch_expr(ParseContext *pc);82static AstNode *ast_parse_switch_expr(ParseContext *pc);
83static AstNode *ast_parse_asm_expr(ParseContext *pc);83static AstNode *ast_parse_asm_expr(ParseContext *pc);
84static AstNode *ast_parse_enum_lit(ParseContext *pc);84static AstNode *ast_parse_anon_lit(ParseContext *pc);
85static AstNode *ast_parse_asm_output(ParseContext *pc);85static AstNode *ast_parse_asm_output(ParseContext *pc);
86static AsmOutput *ast_parse_asm_output_item(ParseContext *pc);86static AsmOutput *ast_parse_asm_output_item(ParseContext *pc);
87static AstNode *ast_parse_asm_input(ParseContext *pc);87static AstNode *ast_parse_asm_input(ParseContext *pc);
...@@ -1600,9 +1600,9 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {...@@ -1600,9 +1600,9 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {
1600 if (container_decl != nullptr)1600 if (container_decl != nullptr)
1601 return container_decl;1601 return container_decl;
16021602
1603 AstNode *enum_lit = ast_parse_enum_lit(pc);1603 AstNode *anon_lit = ast_parse_anon_lit(pc);
1604 if (enum_lit != nullptr)1604 if (anon_lit != nullptr)
1605 return enum_lit;1605 return anon_lit;
16061606
1607 AstNode *error_set_decl = ast_parse_error_set_decl(pc);1607 AstNode *error_set_decl = ast_parse_error_set_decl(pc);
1608 if (error_set_decl != nullptr)1608 if (error_set_decl != nullptr)
...@@ -1876,16 +1876,22 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc) {...@@ -1876,16 +1876,22 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc) {
1876 return res;1876 return res;
1877}1877}
18781878
1879static AstNode *ast_parse_enum_lit(ParseContext *pc) {1879static AstNode *ast_parse_anon_lit(ParseContext *pc) {
1880 Token *period = eat_token_if(pc, TokenIdDot);1880 Token *period = eat_token_if(pc, TokenIdDot);
1881 if (period == nullptr)1881 if (period == nullptr)
1882 return nullptr;1882 return nullptr;
18831883
1884 Token *identifier = expect_token(pc, TokenIdSymbol);1884 // anon enum literal
1885 AstNode *res = ast_create_node(pc, NodeTypeEnumLiteral, period);1885 Token *identifier = eat_token_if(pc, TokenIdSymbol);
1886 res->data.enum_literal.period = period;1886 if (identifier != nullptr) {
1887 res->data.enum_literal.identifier = identifier;1887 AstNode *res = ast_create_node(pc, NodeTypeEnumLiteral, period);
1888 return res;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);
1889}1895}
18901896
1891// AsmOutput <- COLON AsmOutputList AsmInput?1897// AsmOutput <- COLON AsmOutputList AsmInput?
test/compile_errors.zig+19-2
...@@ -2,6 +2,23 @@ const tests = @import("tests.zig");...@@ -2,6 +2,23 @@ const tests = @import("tests.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub 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
5 cases.add(22 cases.add(
6 "slicing of global undefined pointer",23 "slicing of global undefined pointer",
7 \\var buf: *[1]u8 = undefined;24 \\var buf: *[1]u8 = undefined;
...@@ -216,9 +233,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -216,9 +233,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
216 \\ const obj = AstObject{ .lhsExpr = lhsExpr };233 \\ const obj = AstObject{ .lhsExpr = lhsExpr };
217 \\}234 \\}
218 ,235 ,
219 "tmp.zig:4:19: error: union 'AstObject' depends on itself",236 "tmp.zig:1:17: error: struct 'LhsExpr' depends on itself",
220 "tmp.zig:2:5: note: while checking this field",
221 "tmp.zig:5:5: note: while checking this field",237 "tmp.zig:5:5: note: while checking this field",
238 "tmp.zig:2:5: note: while checking this field",
222 );239 );
223240
224 cases.add(241 cases.add(
test/stage1/behavior/array.zig+14
...@@ -298,3 +298,17 @@ test "implicit cast zero sized array ptr to slice" {...@@ -298,3 +298,17 @@ test "implicit cast zero sized array ptr to slice" {
298 const c: []const u8 = &b;298 const c: []const u8 = &b;
299 expect(c.len == 0);299 expect(c.len == 0);
300}300}
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" {...@@ -1214,7 +1214,7 @@ test "spill target expr in a for loop" {
1214 }1214 }
12151215
1216 const Foo = struct {1216 const Foo = struct {
1217 slice: []i32,1217 slice: []const i32,
1218 };1218 };
12191219
1220 fn atest(foo: *Foo) i32 {1220 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" {...@@ -1245,7 +1245,7 @@ test "spill target expr in a for loop, with a var decl in the loop body" {
1245 }1245 }
12461246
1247 const Foo = struct {1247 const Foo = struct {
1248 slice: []i32,1248 slice: []const i32,
1249 };1249 };
12501250
1251 fn atest(foo: *Foo) i32 {1251 fn atest(foo: *Foo) i32 {
test/stage1/behavior/struct.zig+59
...@@ -709,3 +709,62 @@ test "packed struct field passed to generic function" {...@@ -709,3 +709,62 @@ test "packed struct field passed to generic function" {
709 var loaded = S.genericReadPackedField(&p.b);709 var loaded = S.genericReadPackedField(&p.b);
710 expect(loaded == 29);710 expect(loaded == 29);
711}711}
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" {...@@ -549,3 +549,25 @@ test "initialize global array of union" {
549 expect(glbl_array[0].U0 == 1);549 expect(glbl_array[0].U0 == 1);
550 expect(glbl_array[1].U1 == 2);550 expect(glbl_array[1].U1 == 2);
551}551}
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}