| ... | @@ -4386,6 +4386,7 @@ fn structDeclInner( | ... | @@ -4386,6 +4386,7 @@ fn structDeclInner( |
| 4386 | .backing_int_body_len = 0, | 4386 | .backing_int_body_len = 0, |
| 4387 | .known_non_opv = false, | 4387 | .known_non_opv = false, |
| 4388 | .known_comptime_only = false, | 4388 | .known_comptime_only = false, |
| | 4389 | .is_tuple = false, |
| 4389 | }); | 4390 | }); |
| 4390 | return indexToRef(decl_inst); | 4391 | return indexToRef(decl_inst); |
| 4391 | } | 4392 | } |
| ... | @@ -4467,22 +4468,59 @@ fn structDeclInner( | ... | @@ -4467,22 +4468,59 @@ fn structDeclInner( |
| 4467 | // No defer needed here because it is handled by `wip_members.deinit()` above. | 4468 | // No defer needed here because it is handled by `wip_members.deinit()` above. |
| 4468 | const bodies_start = astgen.scratch.items.len; | 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 | var known_non_opv = false; | 4495 | var known_non_opv = false; |
| 4471 | var known_comptime_only = false; | 4496 | var known_comptime_only = false; |
| 4472 | for (container_decl.ast.members) |member_node| { | 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 | .decl => continue, | 4499 | .decl => continue, |
| 4475 | .field => |field| field, | 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); | 4513 | if (!is_tuple) { |
| 4479 | wip_members.appendToField(field_name); | 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 | const doc_comment_index = try astgen.docCommentAsString(member.firstToken()); | 4519 | const doc_comment_index = try astgen.docCommentAsString(member.firstToken()); |
| 4482 | wip_members.appendToField(doc_comment_index); | 4520 | wip_members.appendToField(doc_comment_index); |
| 4483 | | 4521 | |
| 4484 | if (member.ast.type_expr == 0) { | 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 | const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr); | 4526 | const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr); |
| ... | @@ -4562,6 +4600,7 @@ fn structDeclInner( | ... | @@ -4562,6 +4600,7 @@ fn structDeclInner( |
| 4562 | .backing_int_body_len = @intCast(u32, backing_int_body_len), | 4600 | .backing_int_body_len = @intCast(u32, backing_int_body_len), |
| 4563 | .known_non_opv = known_non_opv, | 4601 | .known_non_opv = known_non_opv, |
| 4564 | .known_comptime_only = known_comptime_only, | 4602 | .known_comptime_only = known_comptime_only, |
| | 4603 | .is_tuple = is_tuple, |
| 4565 | }); | 4604 | }); |
| 4566 | | 4605 | |
| 4567 | wip_members.finishBits(bits_per_field); | 4606 | wip_members.finishBits(bits_per_field); |
| ... | @@ -4640,15 +4679,25 @@ fn unionDeclInner( | ... | @@ -4640,15 +4679,25 @@ fn unionDeclInner( |
| 4640 | defer wip_members.deinit(); | 4679 | defer wip_members.deinit(); |
| 4641 | | 4680 | |
| 4642 | for (members) |member_node| { | 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 | .decl => continue, | 4683 | .decl => continue, |
| 4645 | .field => |field| field, | 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 | if (member.comptime_token) |comptime_token| { | 4696 | if (member.comptime_token) |comptime_token| { |
| 4648 | return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{}); | 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 | wip_members.appendToField(field_name); | 4701 | wip_members.appendToField(field_name); |
| 4653 | | 4702 | |
| 4654 | const doc_comment_index = try astgen.docCommentAsString(member.firstToken()); | 4703 | const doc_comment_index = try astgen.docCommentAsString(member.firstToken()); |
| ... | @@ -4787,7 +4836,7 @@ fn containerDecl( | ... | @@ -4787,7 +4836,7 @@ fn containerDecl( |
| 4787 | var nonexhaustive_node: Ast.Node.Index = 0; | 4836 | var nonexhaustive_node: Ast.Node.Index = 0; |
| 4788 | var nonfinal_nonexhaustive = false; | 4837 | var nonfinal_nonexhaustive = false; |
| 4789 | for (container_decl.ast.members) |member_node| { | 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 | .container_field_init => tree.containerFieldInit(member_node), | 4840 | .container_field_init => tree.containerFieldInit(member_node), |
| 4792 | .container_field_align => tree.containerFieldAlign(member_node), | 4841 | .container_field_align => tree.containerFieldAlign(member_node), |
| 4793 | .container_field => tree.containerField(member_node), | 4842 | .container_field => tree.containerField(member_node), |
| ... | @@ -4796,6 +4845,16 @@ fn containerDecl( | ... | @@ -4796,6 +4845,16 @@ fn containerDecl( |
| 4796 | continue; | 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 | if (member.comptime_token) |comptime_token| { | 4858 | if (member.comptime_token) |comptime_token| { |
| 4800 | return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{}); | 4859 | return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{}); |
| 4801 | } | 4860 | } |
| ... | @@ -4816,7 +4875,7 @@ fn containerDecl( | ... | @@ -4816,7 +4875,7 @@ fn containerDecl( |
| 4816 | // Alignment expressions in enums are caught by the parser. | 4875 | // Alignment expressions in enums are caught by the parser. |
| 4817 | assert(member.ast.align_expr == 0); | 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 | if (mem.eql(u8, tree.tokenSlice(name_token), "_")) { | 4879 | if (mem.eql(u8, tree.tokenSlice(name_token), "_")) { |
| 4821 | if (nonexhaustive_node != 0) { | 4880 | if (nonexhaustive_node != 0) { |
| 4822 | return astgen.failNodeNotes( | 4881 | return astgen.failNodeNotes( |
| ... | @@ -4915,15 +4974,23 @@ fn containerDecl( | ... | @@ -4915,15 +4974,23 @@ fn containerDecl( |
| 4915 | for (container_decl.ast.members) |member_node| { | 4974 | for (container_decl.ast.members) |member_node| { |
| 4916 | if (member_node == counts.nonexhaustive_node) | 4975 | if (member_node == counts.nonexhaustive_node) |
| 4917 | continue; | 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 | .decl => continue, | 4978 | .decl => continue, |
| 4920 | .field => |field| field, | 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 | assert(member.comptime_token == null); | 4989 | assert(member.comptime_token == null); |
| 4923 | assert(member.ast.type_expr == 0); | 4990 | assert(member.ast.type_expr == 0); |
| 4924 | assert(member.ast.align_expr == 0); | 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 | wip_members.appendToField(field_name); | 4994 | wip_members.appendToField(field_name); |
| 4928 | | 4995 | |
| 4929 | const doc_comment_index = try astgen.docCommentAsString(member.firstToken()); | 4996 | const doc_comment_index = try astgen.docCommentAsString(member.firstToken()); |
| ... | @@ -11786,6 +11853,7 @@ const GenZir = struct { | ... | @@ -11786,6 +11853,7 @@ const GenZir = struct { |
| 11786 | layout: std.builtin.Type.ContainerLayout, | 11853 | layout: std.builtin.Type.ContainerLayout, |
| 11787 | known_non_opv: bool, | 11854 | known_non_opv: bool, |
| 11788 | known_comptime_only: bool, | 11855 | known_comptime_only: bool, |
| | 11856 | is_tuple: bool, |
| 11789 | }) !void { | 11857 | }) !void { |
| 11790 | const astgen = gz.astgen; | 11858 | const astgen = gz.astgen; |
| 11791 | const gpa = astgen.gpa; | 11859 | const gpa = astgen.gpa; |
| ... | @@ -11820,6 +11888,7 @@ const GenZir = struct { | ... | @@ -11820,6 +11888,7 @@ const GenZir = struct { |
| 11820 | .has_backing_int = args.backing_int_ref != .none, | 11888 | .has_backing_int = args.backing_int_ref != .none, |
| 11821 | .known_non_opv = args.known_non_opv, | 11889 | .known_non_opv = args.known_non_opv, |
| 11822 | .known_comptime_only = args.known_comptime_only, | 11890 | .known_comptime_only = args.known_comptime_only, |
| | 11891 | .is_tuple = args.is_tuple, |
| 11823 | .name_strategy = gz.anon_name_strategy, | 11892 | .name_strategy = gz.anon_name_strategy, |
| 11824 | .layout = args.layout, | 11893 | .layout = args.layout, |
| 11825 | }), | 11894 | }), |