| ... | ... | @@ -4386,6 +4386,7 @@ fn structDeclInner( |
| 4386 | 4386 | .backing_int_body_len = 0, |
| 4387 | 4387 | .known_non_opv = false, |
| 4388 | 4388 | .known_comptime_only = false, |
| 4389 | .is_tuple = false, |
| 4389 | 4390 | }); |
| 4390 | 4391 | return indexToRef(decl_inst); |
| 4391 | 4392 | } |
| ... | ... | @@ -4467,22 +4468,59 @@ fn structDeclInner( |
| 4467 | 4468 | // No defer needed here because it is handled by `wip_members.deinit()` above. |
| 4468 | 4469 | const bodies_start = astgen.scratch.items.len; |
| 4469 | 4470 | |
| 4471 | var is_tuple = false; |
| 4472 | const node_tags = tree.nodes.items(.tag); |
| 4473 | for (container_decl.ast.members) |member_node| { |
| 4474 | switch (node_tags[member_node]) { |
| 4475 | .container_field_init => is_tuple = tree.containerFieldInit(member_node).ast.tuple_like, |
| 4476 | .container_field_align => is_tuple = tree.containerFieldAlign(member_node).ast.tuple_like, |
| 4477 | .container_field => is_tuple = tree.containerField(member_node).ast.tuple_like, |
| 4478 | else => continue, |
| 4479 | } |
| 4480 | if (is_tuple) break; |
| 4481 | } |
| 4482 | if (is_tuple) for (container_decl.ast.members) |member_node| { |
| 4483 | switch (node_tags[member_node]) { |
| 4484 | .container_field_init, |
| 4485 | .container_field_align, |
| 4486 | .container_field, |
| 4487 | .@"comptime", |
| 4488 | => continue, |
| 4489 | else => { |
| 4490 | return astgen.failNode(member_node, "tuple declarations cannot contain declarations", .{}); |
| 4491 | }, |
| 4492 | } |
| 4493 | }; |
| 4494 | |
| 4470 | 4495 | var known_non_opv = false; |
| 4471 | 4496 | var known_comptime_only = false; |
| 4472 | 4497 | for (container_decl.ast.members) |member_node| { |
| 4473 | | const member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { |
| 4498 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { |
| 4474 | 4499 | .decl => continue, |
| 4475 | 4500 | .field => |field| field, |
| 4476 | 4501 | }; |
| 4502 | if (member.ast.tuple_like and !is_tuple and member.ast.type_expr != 0 and |
| 4503 | astgen.tree.nodes.items(.tag)[member.ast.type_expr] == .identifier) |
| 4504 | { |
| 4505 | const ident = astgen.tree.nodes.items(.main_token)[member.ast.type_expr]; |
| 4506 | member.ast.tuple_like = false; |
| 4507 | member.ast.main_token = ident; |
| 4508 | member.ast.type_expr = 0; |
| 4509 | } else if (is_tuple and !member.ast.tuple_like) { |
| 4510 | return astgen.failTok(member.ast.main_token, "tuple field has a name", .{}); |
| 4511 | } |
| 4477 | 4512 | |
| 4478 | | const field_name = try astgen.identAsString(member.ast.name_token); |
| 4479 | | wip_members.appendToField(field_name); |
| 4513 | if (!is_tuple) { |
| 4514 | if (member.ast.tuple_like) return astgen.failTok(member.ast.main_token, "struct field missing name", .{}); |
| 4515 | const field_name = try astgen.identAsString(member.ast.main_token); |
| 4516 | wip_members.appendToField(field_name); |
| 4517 | } |
| 4480 | 4518 | |
| 4481 | 4519 | const doc_comment_index = try astgen.docCommentAsString(member.firstToken()); |
| 4482 | 4520 | wip_members.appendToField(doc_comment_index); |
| 4483 | 4521 | |
| 4484 | 4522 | if (member.ast.type_expr == 0) { |
| 4485 | | return astgen.failTok(member.ast.name_token, "struct field missing type", .{}); |
| 4523 | return astgen.failTok(member.ast.main_token, "struct field missing type", .{}); |
| 4486 | 4524 | } |
| 4487 | 4525 | |
| 4488 | 4526 | const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr); |
| ... | ... | @@ -4562,6 +4600,7 @@ fn structDeclInner( |
| 4562 | 4600 | .backing_int_body_len = @intCast(u32, backing_int_body_len), |
| 4563 | 4601 | .known_non_opv = known_non_opv, |
| 4564 | 4602 | .known_comptime_only = known_comptime_only, |
| 4603 | .is_tuple = is_tuple, |
| 4565 | 4604 | }); |
| 4566 | 4605 | |
| 4567 | 4606 | wip_members.finishBits(bits_per_field); |
| ... | ... | @@ -4640,15 +4679,25 @@ fn unionDeclInner( |
| 4640 | 4679 | defer wip_members.deinit(); |
| 4641 | 4680 | |
| 4642 | 4681 | for (members) |member_node| { |
| 4643 | | const member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { |
| 4682 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { |
| 4644 | 4683 | .decl => continue, |
| 4645 | 4684 | .field => |field| field, |
| 4646 | 4685 | }; |
| 4686 | if (member.ast.tuple_like and member.ast.type_expr != 0 and |
| 4687 | astgen.tree.nodes.items(.tag)[member.ast.type_expr] == .identifier) |
| 4688 | { |
| 4689 | const ident = astgen.tree.nodes.items(.main_token)[member.ast.type_expr]; |
| 4690 | member.ast.tuple_like = false; |
| 4691 | member.ast.main_token = ident; |
| 4692 | member.ast.type_expr = 0; |
| 4693 | } else if (member.ast.tuple_like) { |
| 4694 | return astgen.failTok(member.ast.main_token, "union field missing name", .{}); |
| 4695 | } |
| 4647 | 4696 | if (member.comptime_token) |comptime_token| { |
| 4648 | 4697 | return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{}); |
| 4649 | 4698 | } |
| 4650 | 4699 | |
| 4651 | | const field_name = try astgen.identAsString(member.ast.name_token); |
| 4700 | const field_name = try astgen.identAsString(member.ast.main_token); |
| 4652 | 4701 | wip_members.appendToField(field_name); |
| 4653 | 4702 | |
| 4654 | 4703 | const doc_comment_index = try astgen.docCommentAsString(member.firstToken()); |
| ... | ... | @@ -4787,7 +4836,7 @@ fn containerDecl( |
| 4787 | 4836 | var nonexhaustive_node: Ast.Node.Index = 0; |
| 4788 | 4837 | var nonfinal_nonexhaustive = false; |
| 4789 | 4838 | for (container_decl.ast.members) |member_node| { |
| 4790 | | const member = switch (node_tags[member_node]) { |
| 4839 | var member = switch (node_tags[member_node]) { |
| 4791 | 4840 | .container_field_init => tree.containerFieldInit(member_node), |
| 4792 | 4841 | .container_field_align => tree.containerFieldAlign(member_node), |
| 4793 | 4842 | .container_field => tree.containerField(member_node), |
| ... | ... | @@ -4796,6 +4845,16 @@ fn containerDecl( |
| 4796 | 4845 | continue; |
| 4797 | 4846 | }, |
| 4798 | 4847 | }; |
| 4848 | if (member.ast.tuple_like and member.ast.type_expr != 0 and |
| 4849 | astgen.tree.nodes.items(.tag)[member.ast.type_expr] == .identifier) |
| 4850 | { |
| 4851 | const ident = astgen.tree.nodes.items(.main_token)[member.ast.type_expr]; |
| 4852 | member.ast.tuple_like = false; |
| 4853 | member.ast.main_token = ident; |
| 4854 | member.ast.type_expr = 0; |
| 4855 | } else if (member.ast.tuple_like) { |
| 4856 | return astgen.failTok(member.ast.main_token, "enum field missing name", .{}); |
| 4857 | } |
| 4799 | 4858 | if (member.comptime_token) |comptime_token| { |
| 4800 | 4859 | return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{}); |
| 4801 | 4860 | } |
| ... | ... | @@ -4816,7 +4875,7 @@ fn containerDecl( |
| 4816 | 4875 | // Alignment expressions in enums are caught by the parser. |
| 4817 | 4876 | assert(member.ast.align_expr == 0); |
| 4818 | 4877 | |
| 4819 | | const name_token = member.ast.name_token; |
| 4878 | const name_token = member.ast.main_token; |
| 4820 | 4879 | if (mem.eql(u8, tree.tokenSlice(name_token), "_")) { |
| 4821 | 4880 | if (nonexhaustive_node != 0) { |
| 4822 | 4881 | return astgen.failNodeNotes( |
| ... | ... | @@ -4915,15 +4974,23 @@ fn containerDecl( |
| 4915 | 4974 | for (container_decl.ast.members) |member_node| { |
| 4916 | 4975 | if (member_node == counts.nonexhaustive_node) |
| 4917 | 4976 | continue; |
| 4918 | | const member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { |
| 4977 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { |
| 4919 | 4978 | .decl => continue, |
| 4920 | 4979 | .field => |field| field, |
| 4921 | 4980 | }; |
| 4981 | if (member.ast.tuple_like and member.ast.type_expr != 0 and |
| 4982 | astgen.tree.nodes.items(.tag)[member.ast.type_expr] == .identifier) |
| 4983 | { |
| 4984 | const ident = astgen.tree.nodes.items(.main_token)[member.ast.type_expr]; |
| 4985 | member.ast.tuple_like = false; |
| 4986 | member.ast.main_token = ident; |
| 4987 | member.ast.type_expr = 0; |
| 4988 | } |
| 4922 | 4989 | assert(member.comptime_token == null); |
| 4923 | 4990 | assert(member.ast.type_expr == 0); |
| 4924 | 4991 | assert(member.ast.align_expr == 0); |
| 4925 | 4992 | |
| 4926 | | const field_name = try astgen.identAsString(member.ast.name_token); |
| 4993 | const field_name = try astgen.identAsString(member.ast.main_token); |
| 4927 | 4994 | wip_members.appendToField(field_name); |
| 4928 | 4995 | |
| 4929 | 4996 | const doc_comment_index = try astgen.docCommentAsString(member.firstToken()); |
| ... | ... | @@ -11786,6 +11853,7 @@ const GenZir = struct { |
| 11786 | 11853 | layout: std.builtin.Type.ContainerLayout, |
| 11787 | 11854 | known_non_opv: bool, |
| 11788 | 11855 | known_comptime_only: bool, |
| 11856 | is_tuple: bool, |
| 11789 | 11857 | }) !void { |
| 11790 | 11858 | const astgen = gz.astgen; |
| 11791 | 11859 | const gpa = astgen.gpa; |
| ... | ... | @@ -11820,6 +11888,7 @@ const GenZir = struct { |
| 11820 | 11888 | .has_backing_int = args.backing_int_ref != .none, |
| 11821 | 11889 | .known_non_opv = args.known_non_opv, |
| 11822 | 11890 | .known_comptime_only = args.known_comptime_only, |
| 11891 | .is_tuple = args.is_tuple, |
| 11823 | 11892 | .name_strategy = gz.anon_name_strategy, |
| 11824 | 11893 | .layout = args.layout, |
| 11825 | 11894 | }), |