| ... | ... | @@ -3975,81 +3975,67 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node. |
| 3975 | 3975 | return rvalue(gz, ri, result, node); |
| 3976 | 3976 | } |
| 3977 | 3977 | |
| 3978 | | const WipMembers = struct { |
| 3979 | | payload: *ArrayList(u32), |
| 3980 | | payload_top: usize, |
| 3981 | | field_bits_start: u32, |
| 3982 | | fields_start: u32, |
| 3983 | | fields_end: u32, |
| 3984 | | decl_index: u32 = 0, |
| 3985 | | field_index: u32 = 0, |
| 3986 | | |
| 3987 | | const Self = @This(); |
| 3988 | | |
| 3989 | | fn init(gpa: Allocator, payload: *ArrayList(u32), decl_count: u32, field_count: u32, comptime bits_per_field: u32, comptime max_field_size: u32) Allocator.Error!Self { |
| 3990 | | const payload_top: u32 = @intCast(payload.items.len); |
| 3991 | | const field_bits_start = payload_top + decl_count; |
| 3992 | | const fields_start = field_bits_start + if (bits_per_field > 0) blk: { |
| 3993 | | const fields_per_u32 = 32 / bits_per_field; |
| 3994 | | break :blk (field_count + fields_per_u32 - 1) / fields_per_u32; |
| 3995 | | } else 0; |
| 3996 | | const payload_end = fields_start + field_count * max_field_size; |
| 3997 | | try payload.resize(gpa, payload_end); |
| 3978 | const Scratch = struct { |
| 3979 | astgen: *AstGen, |
| 3980 | scratch_top: u32, |
| 3981 | fn init(astgen: *AstGen) Scratch { |
| 3998 | 3982 | return .{ |
| 3999 | | .payload = payload, |
| 4000 | | .payload_top = payload_top, |
| 4001 | | .field_bits_start = field_bits_start, |
| 4002 | | .fields_start = fields_start, |
| 4003 | | .fields_end = fields_start, |
| 3983 | .astgen = astgen, |
| 3984 | .scratch_top = @intCast(astgen.scratch.items.len), |
| 4004 | 3985 | }; |
| 4005 | 3986 | } |
| 4006 | | |
| 4007 | | fn nextDecl(self: *Self, decl_inst: Zir.Inst.Index) void { |
| 4008 | | self.payload.items[self.payload_top + self.decl_index] = @intFromEnum(decl_inst); |
| 4009 | | self.decl_index += 1; |
| 3987 | fn reset(s: *Scratch) void { |
| 3988 | s.astgen.scratch.shrinkRetainingCapacity(s.scratch_top); |
| 3989 | s.* = undefined; |
| 4010 | 3990 | } |
| 4011 | | |
| 4012 | | fn nextField(self: *Self, comptime bits_per_field: u32, bits: [bits_per_field]bool) void { |
| 4013 | | const fields_per_u32 = 32 / bits_per_field; |
| 4014 | | const index = self.field_bits_start + self.field_index / fields_per_u32; |
| 4015 | | assert(index < self.fields_start); |
| 4016 | | var bit_bag: u32 = if (self.field_index % fields_per_u32 == 0) 0 else self.payload.items[index]; |
| 4017 | | bit_bag >>= bits_per_field; |
| 4018 | | comptime var i = 0; |
| 4019 | | inline while (i < bits_per_field) : (i += 1) { |
| 4020 | | bit_bag |= @as(u32, @intFromBool(bits[i])) << (32 - bits_per_field + i); |
| 4021 | | } |
| 4022 | | self.payload.items[index] = bit_bag; |
| 4023 | | self.field_index += 1; |
| 3991 | fn addSlice(s: *Scratch, len: u32) Allocator.Error!Slice { |
| 3992 | const start: u32 = @intCast(s.astgen.scratch.items.len); |
| 3993 | try s.astgen.scratch.resize(s.astgen.gpa, start + len); |
| 3994 | return .{ .start = start, .len = len }; |
| 4024 | 3995 | } |
| 4025 | | |
| 4026 | | fn appendToField(self: *Self, data: u32) void { |
| 4027 | | assert(self.fields_end < self.payload.items.len); |
| 4028 | | self.payload.items[self.fields_end] = data; |
| 4029 | | self.fields_end += 1; |
| 3996 | fn addOptionalSlice(s: *Scratch, present: bool, len: u32) Allocator.Error!?Slice { |
| 3997 | if (!present) return null; |
| 3998 | return try addSlice(s, len); |
| 4030 | 3999 | } |
| 4031 | | |
| 4032 | | fn finishBits(self: *Self, comptime bits_per_field: u32) void { |
| 4033 | | if (bits_per_field > 0) { |
| 4034 | | const fields_per_u32 = 32 / bits_per_field; |
| 4035 | | const empty_field_slots = fields_per_u32 - (self.field_index % fields_per_u32); |
| 4036 | | if (self.field_index > 0 and empty_field_slots < fields_per_u32) { |
| 4037 | | const index = self.field_bits_start + self.field_index / fields_per_u32; |
| 4038 | | self.payload.items[index] >>= @intCast(empty_field_slots * bits_per_field); |
| 4039 | | } |
| 4040 | | } |
| 4000 | fn appendBodyWithFixups(s: *Scratch, body: []const Zir.Inst.Index) Allocator.Error!u32 { |
| 4001 | const len = countBodyLenAfterFixups(s.astgen, body); |
| 4002 | try s.astgen.scratch.ensureUnusedCapacity(s.astgen.gpa, len); |
| 4003 | appendBodyWithFixupsArrayList(s.astgen, &s.astgen.scratch, body); |
| 4004 | return len; |
| 4041 | 4005 | } |
| 4042 | | |
| 4043 | | fn declsSlice(self: *Self) []u32 { |
| 4044 | | return self.payload.items[self.payload_top..][0..self.decl_index]; |
| 4006 | /// Returns the slice containing all data added to this `Scratch`. |
| 4007 | fn all(s: *Scratch) Slice { |
| 4008 | const len = s.astgen.scratch.items.len - s.scratch_top; |
| 4009 | return .{ .start = s.scratch_top, .len = @intCast(len) }; |
| 4045 | 4010 | } |
| 4011 | const Slice = struct { |
| 4012 | start: u32, |
| 4013 | len: u32, |
| 4014 | fn get(s: Slice, astgen: *AstGen) []u32 { |
| 4015 | return astgen.scratch.items[s.start..][0..s.len]; |
| 4016 | } |
| 4017 | }; |
| 4018 | }; |
| 4046 | 4019 | |
| 4047 | | fn fieldsSlice(self: *Self) []u32 { |
| 4048 | | return self.payload.items[self.field_bits_start..self.fields_end]; |
| 4049 | | } |
| 4020 | const WipDecls = struct { |
| 4021 | astgen: *AstGen, |
| 4022 | slice: Scratch.Slice, |
| 4023 | index: u32, |
| 4050 | 4024 | |
| 4051 | | fn deinit(self: *Self) void { |
| 4052 | | self.payload.items.len = self.payload_top; |
| 4025 | fn init(scratch: *Scratch, decls_len: u32) Allocator.Error!WipDecls { |
| 4026 | return .{ |
| 4027 | .astgen = scratch.astgen, |
| 4028 | .slice = try scratch.addSlice(decls_len), |
| 4029 | .index = 0, |
| 4030 | }; |
| 4031 | } |
| 4032 | fn finish(wip: *WipDecls) void { |
| 4033 | assert(wip.index == wip.slice.len); |
| 4034 | wip.* = undefined; |
| 4035 | } |
| 4036 | fn nextDecl(wip: *WipDecls, decl_inst: Zir.Inst.Index) void { |
| 4037 | wip.slice.get(wip.astgen)[wip.index] = @intFromEnum(decl_inst); |
| 4038 | wip.index += 1; |
| 4053 | 4039 | } |
| 4054 | 4040 | }; |
| 4055 | 4041 | |
| ... | ... | @@ -4057,7 +4043,7 @@ fn fnDecl( |
| 4057 | 4043 | astgen: *AstGen, |
| 4058 | 4044 | gz: *GenZir, |
| 4059 | 4045 | scope: *Scope, |
| 4060 | | wip_members: *WipMembers, |
| 4046 | wip_decls: *WipDecls, |
| 4061 | 4047 | decl_node: Ast.Node.Index, |
| 4062 | 4048 | body_node: Ast.Node.OptionalIndex, |
| 4063 | 4049 | fn_proto: Ast.full.FnProto, |
| ... | ... | @@ -4133,7 +4119,7 @@ fn fnDecl( |
| 4133 | 4119 | assert(!is_extern); // validated by parser (TODO why???) |
| 4134 | 4120 | } |
| 4135 | 4121 | |
| 4136 | | wip_members.nextDecl(decl_inst); |
| 4122 | wip_decls.nextDecl(decl_inst); |
| 4137 | 4123 | |
| 4138 | 4124 | var type_gz: GenZir = .{ |
| 4139 | 4125 | .is_comptime = true, |
| ... | ... | @@ -4488,7 +4474,7 @@ fn globalVarDecl( |
| 4488 | 4474 | astgen: *AstGen, |
| 4489 | 4475 | gz: *GenZir, |
| 4490 | 4476 | scope: *Scope, |
| 4491 | | wip_members: *WipMembers, |
| 4477 | wip_decls: *WipDecls, |
| 4492 | 4478 | node: Ast.Node.Index, |
| 4493 | 4479 | var_decl: Ast.full.VarDecl, |
| 4494 | 4480 | ) InnerError!void { |
| ... | ... | @@ -4533,7 +4519,7 @@ fn globalVarDecl( |
| 4533 | 4519 | const decl_column = astgen.source_column; |
| 4534 | 4520 | |
| 4535 | 4521 | const decl_inst = try gz.makeDeclaration(node); |
| 4536 | | wip_members.nextDecl(decl_inst); |
| 4522 | wip_decls.nextDecl(decl_inst); |
| 4537 | 4523 | |
| 4538 | 4524 | if (var_decl.ast.init_node.unwrap()) |init_node| { |
| 4539 | 4525 | if (is_extern) { |
| ... | ... | @@ -4635,7 +4621,7 @@ fn comptimeDecl( |
| 4635 | 4621 | astgen: *AstGen, |
| 4636 | 4622 | gz: *GenZir, |
| 4637 | 4623 | scope: *Scope, |
| 4638 | | wip_members: *WipMembers, |
| 4624 | wip_decls: *WipDecls, |
| 4639 | 4625 | node: Ast.Node.Index, |
| 4640 | 4626 | ) InnerError!void { |
| 4641 | 4627 | const tree = astgen.tree; |
| ... | ... | @@ -4650,7 +4636,7 @@ fn comptimeDecl( |
| 4650 | 4636 | // Up top so the ZIR instruction index marks the start range of this |
| 4651 | 4637 | // top-level declaration. |
| 4652 | 4638 | const decl_inst = try gz.makeDeclaration(node); |
| 4653 | | wip_members.nextDecl(decl_inst); |
| 4639 | wip_decls.nextDecl(decl_inst); |
| 4654 | 4640 | astgen.advanceSourceCursorToNode(node); |
| 4655 | 4641 | |
| 4656 | 4642 | // This is just needed for the `setDeclaration` call. |
| ... | ... | @@ -4698,7 +4684,7 @@ fn testDecl( |
| 4698 | 4684 | astgen: *AstGen, |
| 4699 | 4685 | gz: *GenZir, |
| 4700 | 4686 | scope: *Scope, |
| 4701 | | wip_members: *WipMembers, |
| 4687 | wip_decls: *WipDecls, |
| 4702 | 4688 | node: Ast.Node.Index, |
| 4703 | 4689 | ) InnerError!void { |
| 4704 | 4690 | const tree = astgen.tree; |
| ... | ... | @@ -4714,7 +4700,7 @@ fn testDecl( |
| 4714 | 4700 | // top-level declaration. |
| 4715 | 4701 | const decl_inst = try gz.makeDeclaration(node); |
| 4716 | 4702 | |
| 4717 | | wip_members.nextDecl(decl_inst); |
| 4703 | wip_decls.nextDecl(decl_inst); |
| 4718 | 4704 | astgen.advanceSourceCursorToNode(node); |
| 4719 | 4705 | |
| 4720 | 4706 | // This is just needed for the `setDeclaration` call. |
| ... | ... | @@ -4914,7 +4900,7 @@ fn structDeclInner( |
| 4914 | 4900 | node: Ast.Node.Index, |
| 4915 | 4901 | container_decl: Ast.full.ContainerDecl, |
| 4916 | 4902 | layout: std.builtin.Type.ContainerLayout, |
| 4917 | | backing_int_node: Ast.Node.OptionalIndex, |
| 4903 | maybe_backing_int_node: Ast.Node.OptionalIndex, |
| 4918 | 4904 | name_strat: Zir.Inst.NameStrategy, |
| 4919 | 4905 | ) InnerError!Zir.Inst.Ref { |
| 4920 | 4906 | const astgen = gz.astgen; |
| ... | ... | @@ -4930,27 +4916,39 @@ fn structDeclInner( |
| 4930 | 4916 | if (node == .root) { |
| 4931 | 4917 | return astgen.failNode(tuple_field_node, "file cannot be a tuple", .{}); |
| 4932 | 4918 | } else { |
| 4933 | | return tupleDecl(gz, scope, node, container_decl, layout, backing_int_node); |
| 4919 | return tupleDecl(gz, scope, node, container_decl, layout, maybe_backing_int_node); |
| 4934 | 4920 | } |
| 4935 | 4921 | } |
| 4936 | 4922 | |
| 4923 | astgen.advanceSourceCursorToNode(node); |
| 4924 | |
| 4925 | const backing_int_type_ref: Zir.Inst.Ref = ty: { |
| 4926 | const backing_int_node = maybe_backing_int_node.unwrap() orelse break :ty .none; |
| 4927 | if (layout != .@"packed") return astgen.failNode( |
| 4928 | backing_int_node, |
| 4929 | "non-packed struct does not support backing integer type", |
| 4930 | .{}, |
| 4931 | ); |
| 4932 | break :ty try typeExpr(gz, scope, backing_int_node); |
| 4933 | }; |
| 4934 | |
| 4937 | 4935 | const decl_inst = try gz.reserveInstructionIndex(); |
| 4938 | 4936 | |
| 4939 | | if (container_decl.ast.members.len == 0 and backing_int_node == .none) { |
| 4937 | if (container_decl.ast.members.len == 0 and backing_int_type_ref == .none) { |
| 4940 | 4938 | try gz.setStruct(decl_inst, .{ |
| 4941 | 4939 | .src_node = node, |
| 4940 | .name_strat = name_strat, |
| 4942 | 4941 | .layout = layout, |
| 4943 | | .captures_len = 0, |
| 4944 | | .fields_len = 0, |
| 4942 | .backing_int_type = .none, |
| 4945 | 4943 | .decls_len = 0, |
| 4946 | | .has_backing_int = false, |
| 4947 | | .known_non_opv = false, |
| 4948 | | .known_comptime_only = false, |
| 4944 | .fields_len = 0, |
| 4945 | .any_field_aligns = false, |
| 4946 | .any_field_defaults = false, |
| 4949 | 4947 | .any_comptime_fields = false, |
| 4950 | | .any_default_inits = false, |
| 4951 | | .any_aligned_fields = false, |
| 4952 | | .fields_hash = std.zig.hashSrc(@tagName(layout)), |
| 4953 | | .name_strat = name_strat, |
| 4948 | .fields_hash = @splat(0), |
| 4949 | .captures = &.{}, |
| 4950 | .capture_names = &.{}, |
| 4951 | .remaining = &.{}, |
| 4954 | 4952 | }); |
| 4955 | 4953 | return decl_inst.toRef(); |
| 4956 | 4954 | } |
| ... | ... | @@ -4967,7 +4965,6 @@ fn structDeclInner( |
| 4967 | 4965 | // The struct_decl instruction introduces a scope in which the decls of the struct |
| 4968 | 4966 | // are in scope, so that field types, alignments, and default value expressions |
| 4969 | 4967 | // can refer to decls within the struct itself. |
| 4970 | | astgen.advanceSourceCursorToNode(node); |
| 4971 | 4968 | var block_scope: GenZir = .{ |
| 4972 | 4969 | .parent = &namespace.base, |
| 4973 | 4970 | .decl_node_index = node, |
| ... | ... | @@ -4979,197 +4976,118 @@ fn structDeclInner( |
| 4979 | 4976 | }; |
| 4980 | 4977 | defer block_scope.unstack(); |
| 4981 | 4978 | |
| 4982 | | const scratch_top = astgen.scratch.items.len; |
| 4983 | | defer astgen.scratch.items.len = scratch_top; |
| 4984 | | |
| 4985 | | var backing_int_body_len: usize = 0; |
| 4986 | | const backing_int_ref: Zir.Inst.Ref = blk: { |
| 4987 | | if (backing_int_node.unwrap()) |arg| { |
| 4988 | | if (layout != .@"packed") { |
| 4989 | | return astgen.failNode(arg, "non-packed struct does not support backing integer type", .{}); |
| 4990 | | } else { |
| 4991 | | const backing_int_ref = try typeExpr(&block_scope, &namespace.base, arg); |
| 4992 | | if (!block_scope.isEmpty()) { |
| 4993 | | if (!block_scope.endsWithNoReturn()) { |
| 4994 | | _ = try block_scope.addBreak(.break_inline, decl_inst, backing_int_ref); |
| 4995 | | } |
| 4996 | | |
| 4997 | | const body = block_scope.instructionsSlice(); |
| 4998 | | const old_scratch_len = astgen.scratch.items.len; |
| 4999 | | try astgen.scratch.ensureUnusedCapacity(gpa, countBodyLenAfterFixups(astgen, body)); |
| 5000 | | appendBodyWithFixupsArrayList(astgen, &astgen.scratch, body); |
| 5001 | | backing_int_body_len = astgen.scratch.items.len - old_scratch_len; |
| 5002 | | block_scope.instructions.items.len = block_scope.instructions_top; |
| 5003 | | } |
| 5004 | | break :blk backing_int_ref; |
| 5005 | | } |
| 5006 | | } else { |
| 5007 | | break :blk .none; |
| 5008 | | } |
| 5009 | | }; |
| 4979 | const scan_result = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"struct"); |
| 5010 | 4980 | |
| 5011 | | const decl_count = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"struct"); |
| 5012 | | const field_count: u32 = @intCast(container_decl.ast.members.len - decl_count); |
| 4981 | var scratch: Scratch = .init(astgen); |
| 4982 | defer scratch.reset(); |
| 5013 | 4983 | |
| 5014 | | const bits_per_field = 4; |
| 5015 | | const max_field_size = 5; |
| 5016 | | var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size); |
| 5017 | | defer wip_members.deinit(); |
| 5018 | | |
| 5019 | | // We will use the scratch buffer, starting here, for the bodies: |
| 5020 | | // bodies: { // for every fields_len |
| 5021 | | // field_type_body_inst: Inst, // for each field_type_body_len |
| 5022 | | // align_body_inst: Inst, // for each align_body_len |
| 5023 | | // init_body_inst: Inst, // for each init_body_len |
| 5024 | | // } |
| 5025 | | // Note that the scratch buffer is simultaneously being used by WipMembers, however |
| 5026 | | // it will not access any elements beyond this point in the ArrayList. It also |
| 5027 | | // accesses via the ArrayList items field so it can handle the scratch buffer being |
| 5028 | | // reallocated. |
| 5029 | | // No defer needed here because it is handled by `wip_members.deinit()` above. |
| 5030 | | const bodies_start = astgen.scratch.items.len; |
| 4984 | // Replicate the structure of the ZIR trailing data in `scratch` |
| 4985 | var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len); |
| 4986 | const field_names = try scratch.addSlice(scan_result.fields_len); |
| 4987 | const field_type_body_lens = try scratch.addSlice(scan_result.fields_len); |
| 4988 | const field_align_body_lens = try scratch.addOptionalSlice(scan_result.any_field_aligns, scan_result.fields_len); |
| 4989 | const field_default_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, scan_result.fields_len); |
| 4990 | const field_comptime_bits = try scratch.addOptionalSlice( |
| 4991 | scan_result.any_comptime_fields, |
| 4992 | std.math.divCeil(u32, scan_result.fields_len, 32) catch unreachable, |
| 4993 | ); |
| 4994 | if (field_comptime_bits) |bits| @memset(bits.get(astgen), 0); |
| 5031 | 4995 | |
| 5032 | 4996 | const old_hasher = astgen.src_hasher; |
| 5033 | 4997 | defer astgen.src_hasher = old_hasher; |
| 5034 | | astgen.src_hasher = std.zig.SrcHasher.init(.{}); |
| 5035 | | astgen.src_hasher.update(@tagName(layout)); |
| 5036 | | if (backing_int_node.unwrap()) |arg| { |
| 5037 | | astgen.src_hasher.update(tree.getNodeSource(arg)); |
| 5038 | | } |
| 4998 | astgen.src_hasher = .init(.{}); |
| 5039 | 4999 | |
| 5040 | | var known_non_opv = false; |
| 5041 | | var known_comptime_only = false; |
| 5042 | | var any_comptime_fields = false; |
| 5043 | | var any_aligned_fields = false; |
| 5044 | | var any_default_inits = false; |
| 5000 | var next_field_idx: u32 = 0; |
| 5045 | 5001 | for (container_decl.ast.members) |member_node| { |
| 5046 | | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { |
| 5002 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) { |
| 5047 | 5003 | .decl => continue, |
| 5048 | 5004 | .field => |field| field, |
| 5049 | 5005 | }; |
| 5006 | const field_idx = next_field_idx; |
| 5007 | next_field_idx += 1; |
| 5050 | 5008 | |
| 5051 | 5009 | astgen.src_hasher.update(tree.getNodeSource(member_node)); |
| 5052 | 5010 | |
| 5053 | | const field_name = try astgen.identAsString(member.ast.main_token); |
| 5054 | 5011 | member.convertToNonTupleLike(astgen.tree); |
| 5055 | 5012 | assert(!member.ast.tuple_like); |
| 5056 | | wip_members.appendToField(@intFromEnum(field_name)); |
| 5057 | | |
| 5058 | | const type_expr = member.ast.type_expr.unwrap() orelse { |
| 5059 | | return astgen.failTok(member.ast.main_token, "struct field missing type", .{}); |
| 5060 | | }; |
| 5061 | | |
| 5062 | | const field_type = try typeExpr(&block_scope, &namespace.base, type_expr); |
| 5063 | | const have_type_body = !block_scope.isEmpty(); |
| 5064 | | const have_align = member.ast.align_expr != .none; |
| 5065 | | const have_value = member.ast.value_expr != .none; |
| 5066 | | const is_comptime = member.comptime_token != null; |
| 5067 | 5013 | |
| 5068 | | if (is_comptime) { |
| 5069 | | switch (layout) { |
| 5070 | | .@"packed", .@"extern" => return astgen.failTok(member.comptime_token.?, "{s} struct fields cannot be marked comptime", .{@tagName(layout)}), |
| 5071 | | .auto => any_comptime_fields = true, |
| 5072 | | } |
| 5073 | | } else { |
| 5074 | | known_non_opv = known_non_opv or |
| 5075 | | nodeImpliesMoreThanOnePossibleValue(tree, type_expr); |
| 5076 | | known_comptime_only = known_comptime_only or |
| 5077 | | nodeImpliesComptimeOnly(tree, type_expr); |
| 5078 | | } |
| 5079 | | wip_members.nextField(bits_per_field, .{ have_align, have_value, is_comptime, have_type_body }); |
| 5014 | field_names.get(astgen)[field_idx] = @intFromEnum(try astgen.identAsString(member.ast.main_token)); |
| 5080 | 5015 | |
| 5081 | | if (have_type_body) { |
| 5016 | { |
| 5017 | const type_node = member.ast.type_expr.unwrap() orelse { |
| 5018 | return astgen.failTok(member.ast.main_token, "struct field missing type", .{}); |
| 5019 | }; |
| 5020 | const type_ref = try typeExpr(&block_scope, &namespace.base, type_node); |
| 5082 | 5021 | if (!block_scope.endsWithNoReturn()) { |
| 5083 | | _ = try block_scope.addBreak(.break_inline, decl_inst, field_type); |
| 5022 | _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref); |
| 5084 | 5023 | } |
| 5085 | | const body = block_scope.instructionsSlice(); |
| 5086 | | const old_scratch_len = astgen.scratch.items.len; |
| 5087 | | try astgen.scratch.ensureUnusedCapacity(gpa, countBodyLenAfterFixups(astgen, body)); |
| 5088 | | appendBodyWithFixupsArrayList(astgen, &astgen.scratch, body); |
| 5089 | | wip_members.appendToField(@intCast(astgen.scratch.items.len - old_scratch_len)); |
| 5024 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); |
| 5025 | field_type_body_lens.get(astgen)[field_idx] = body_len; |
| 5090 | 5026 | block_scope.instructions.items.len = block_scope.instructions_top; |
| 5091 | | } else { |
| 5092 | | wip_members.appendToField(@intFromEnum(field_type)); |
| 5093 | 5027 | } |
| 5094 | 5028 | |
| 5095 | | if (member.ast.align_expr.unwrap()) |align_expr| { |
| 5029 | if (member.ast.align_expr.unwrap()) |align_node| { |
| 5096 | 5030 | if (layout == .@"packed") { |
| 5097 | | return astgen.failNode(align_expr, "unable to override alignment of packed struct fields", .{}); |
| 5031 | return astgen.failNode(align_node, "unable to override alignment of packed struct fields", .{}); |
| 5098 | 5032 | } |
| 5099 | | any_aligned_fields = true; |
| 5100 | | const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_expr); |
| 5033 | const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_node); |
| 5101 | 5034 | if (!block_scope.endsWithNoReturn()) { |
| 5102 | 5035 | _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref); |
| 5103 | 5036 | } |
| 5104 | | const body = block_scope.instructionsSlice(); |
| 5105 | | const old_scratch_len = astgen.scratch.items.len; |
| 5106 | | try astgen.scratch.ensureUnusedCapacity(gpa, countBodyLenAfterFixups(astgen, body)); |
| 5107 | | appendBodyWithFixupsArrayList(astgen, &astgen.scratch, body); |
| 5108 | | wip_members.appendToField(@intCast(astgen.scratch.items.len - old_scratch_len)); |
| 5037 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); |
| 5038 | field_align_body_lens.?.get(astgen)[field_idx] = body_len; |
| 5109 | 5039 | block_scope.instructions.items.len = block_scope.instructions_top; |
| 5040 | } else if (field_align_body_lens) |lens| { |
| 5041 | lens.get(astgen)[field_idx] = 0; |
| 5110 | 5042 | } |
| 5111 | 5043 | |
| 5112 | | if (member.ast.value_expr.unwrap()) |value_expr| { |
| 5113 | | any_default_inits = true; |
| 5114 | | |
| 5115 | | // The decl_inst is used as here so that we can easily reconstruct a mapping |
| 5116 | | // between it and the field type when the fields inits are analyzed. |
| 5117 | | const ri: ResultInfo = .{ .rl = if (field_type == .none) .none else .{ .coerced_ty = decl_inst.toRef() } }; |
| 5118 | | |
| 5119 | | const default_inst = try expr(&block_scope, &namespace.base, ri, value_expr); |
| 5044 | if (member.ast.value_expr.unwrap()) |default_node| { |
| 5045 | const ri: ResultInfo = .{ .rl = .{ .coerced_ty = decl_inst.toRef() } }; |
| 5046 | const default_ref = try expr(&block_scope, &namespace.base, ri, default_node); |
| 5120 | 5047 | if (!block_scope.endsWithNoReturn()) { |
| 5121 | | _ = try block_scope.addBreak(.break_inline, decl_inst, default_inst); |
| 5048 | _ = try block_scope.addBreak(.break_inline, decl_inst, default_ref); |
| 5122 | 5049 | } |
| 5123 | | const body = block_scope.instructionsSlice(); |
| 5124 | | const old_scratch_len = astgen.scratch.items.len; |
| 5125 | | try astgen.scratch.ensureUnusedCapacity(gpa, countBodyLenAfterFixups(astgen, body)); |
| 5126 | | appendBodyWithFixupsArrayList(astgen, &astgen.scratch, body); |
| 5127 | | wip_members.appendToField(@intCast(astgen.scratch.items.len - old_scratch_len)); |
| 5050 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); |
| 5051 | field_default_body_lens.?.get(astgen)[field_idx] = body_len; |
| 5128 | 5052 | block_scope.instructions.items.len = block_scope.instructions_top; |
| 5129 | | } else if (member.comptime_token) |comptime_token| { |
| 5130 | | return astgen.failTok(comptime_token, "comptime field without default initialization value", .{}); |
| 5053 | } else if (field_default_body_lens) |lens| { |
| 5054 | lens.get(astgen)[field_idx] = 0; |
| 5055 | } |
| 5056 | |
| 5057 | if (member.comptime_token) |comptime_token| { |
| 5058 | switch (layout) { |
| 5059 | .@"packed", .@"extern" => return astgen.failTok(comptime_token, "{s} struct fields cannot be marked comptime", .{@tagName(layout)}), |
| 5060 | .auto => {}, |
| 5061 | } |
| 5062 | if (member.ast.value_expr == .none) { |
| 5063 | return astgen.failTok(comptime_token, "comptime field without default initialization value", .{}); |
| 5064 | } |
| 5065 | const mask = @as(u32, 1) << @intCast(field_idx % 32); |
| 5066 | field_comptime_bits.?.get(astgen)[field_idx / 32] |= mask; |
| 5131 | 5067 | } |
| 5132 | 5068 | } |
| 5069 | assert(next_field_idx == scan_result.fields_len); |
| 5070 | wip_decls.finish(); |
| 5133 | 5071 | |
| 5134 | 5072 | var fields_hash: std.zig.SrcHash = undefined; |
| 5135 | 5073 | astgen.src_hasher.final(&fields_hash); |
| 5136 | 5074 | |
| 5137 | 5075 | try gz.setStruct(decl_inst, .{ |
| 5138 | 5076 | .src_node = node, |
| 5077 | .name_strat = name_strat, |
| 5139 | 5078 | .layout = layout, |
| 5140 | | .captures_len = @intCast(namespace.captures.count()), |
| 5141 | | .fields_len = field_count, |
| 5142 | | .decls_len = decl_count, |
| 5143 | | .has_backing_int = backing_int_ref != .none, |
| 5144 | | .known_non_opv = known_non_opv, |
| 5145 | | .known_comptime_only = known_comptime_only, |
| 5146 | | .any_comptime_fields = any_comptime_fields, |
| 5147 | | .any_default_inits = any_default_inits, |
| 5148 | | .any_aligned_fields = any_aligned_fields, |
| 5079 | .backing_int_type = backing_int_type_ref, |
| 5080 | .decls_len = scan_result.decls_len, |
| 5081 | .fields_len = scan_result.fields_len, |
| 5082 | .any_field_aligns = scan_result.any_field_aligns, |
| 5083 | .any_field_defaults = scan_result.any_field_values, |
| 5084 | .any_comptime_fields = scan_result.any_comptime_fields, |
| 5149 | 5085 | .fields_hash = fields_hash, |
| 5150 | | .name_strat = name_strat, |
| 5086 | .captures = namespace.captures.keys(), |
| 5087 | .capture_names = namespace.captures.values(), |
| 5088 | .remaining = scratch.all().get(astgen), |
| 5151 | 5089 | }); |
| 5152 | 5090 | |
| 5153 | | wip_members.finishBits(bits_per_field); |
| 5154 | | const decls_slice = wip_members.declsSlice(); |
| 5155 | | const fields_slice = wip_members.fieldsSlice(); |
| 5156 | | const bodies_slice = astgen.scratch.items[bodies_start..]; |
| 5157 | | try astgen.extra.ensureUnusedCapacity(gpa, backing_int_body_len + 2 + |
| 5158 | | decls_slice.len + namespace.captures.count() * 2 + fields_slice.len + bodies_slice.len); |
| 5159 | | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); |
| 5160 | | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.values())); |
| 5161 | | if (backing_int_ref != .none) { |
| 5162 | | astgen.extra.appendAssumeCapacity(@intCast(backing_int_body_len)); |
| 5163 | | if (backing_int_body_len == 0) { |
| 5164 | | astgen.extra.appendAssumeCapacity(@intFromEnum(backing_int_ref)); |
| 5165 | | } else { |
| 5166 | | astgen.extra.appendSliceAssumeCapacity(astgen.scratch.items[scratch_top..][0..backing_int_body_len]); |
| 5167 | | } |
| 5168 | | } |
| 5169 | | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 5170 | | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 5171 | | astgen.extra.appendSliceAssumeCapacity(bodies_slice); |
| 5172 | | |
| 5173 | 5091 | block_scope.unstack(); |
| 5174 | 5092 | return decl_inst.toRef(); |
| 5175 | 5093 | } |
| ... | ... | @@ -5281,11 +5199,34 @@ fn unionDeclInner( |
| 5281 | 5199 | auto_enum_tok: ?Ast.TokenIndex, |
| 5282 | 5200 | name_strat: Zir.Inst.NameStrategy, |
| 5283 | 5201 | ) InnerError!Zir.Inst.Ref { |
| 5284 | | const decl_inst = try gz.reserveInstructionIndex(); |
| 5285 | | |
| 5286 | 5202 | const astgen = gz.astgen; |
| 5287 | 5203 | const gpa = astgen.gpa; |
| 5288 | 5204 | |
| 5205 | const explicit_int_or_enum_tag = switch (layout) { |
| 5206 | .auto => opt_arg_node != .none, |
| 5207 | .@"extern" => if (opt_arg_node.unwrap()) |arg_node| { |
| 5208 | return astgen.failNode(arg_node, "{s} union does not support enum tag type", .{@tagName(layout)}); |
| 5209 | } else false, |
| 5210 | .@"packed" => false, |
| 5211 | }; |
| 5212 | |
| 5213 | if (auto_enum_tok) |t| { |
| 5214 | if (layout != .auto) { |
| 5215 | return astgen.failTok(t, "{s} union does not support enum tag type", .{@tagName(layout)}); |
| 5216 | } |
| 5217 | } |
| 5218 | |
| 5219 | const is_tagged = explicit_int_or_enum_tag or auto_enum_tok != null; |
| 5220 | |
| 5221 | astgen.advanceSourceCursorToNode(node); |
| 5222 | |
| 5223 | const arg_type_ref: Zir.Inst.Ref = ref: { |
| 5224 | const arg_node = opt_arg_node.unwrap() orelse break :ref .none; |
| 5225 | break :ref try typeExpr(gz, scope, arg_node); |
| 5226 | }; |
| 5227 | |
| 5228 | const decl_inst = try gz.reserveInstructionIndex(); |
| 5229 | |
| 5289 | 5230 | var namespace: Scope.Namespace = .{ |
| 5290 | 5231 | .parent = scope, |
| 5291 | 5232 | .node = node, |
| ... | ... | @@ -5298,7 +5239,6 @@ fn unionDeclInner( |
| 5298 | 5239 | // The union_decl instruction introduces a scope in which the decls of the union |
| 5299 | 5240 | // are in scope, so that field types, alignments, and default value expressions |
| 5300 | 5241 | // can refer to decls within the union itself. |
| 5301 | | astgen.advanceSourceCursorToNode(node); |
| 5302 | 5242 | var block_scope: GenZir = .{ |
| 5303 | 5243 | .parent = &namespace.base, |
| 5304 | 5244 | .decl_node_index = node, |
| ... | ... | @@ -5310,42 +5250,31 @@ fn unionDeclInner( |
| 5310 | 5250 | }; |
| 5311 | 5251 | defer block_scope.unstack(); |
| 5312 | 5252 | |
| 5313 | | const decl_count = try astgen.scanContainer(&namespace, members, .@"union"); |
| 5314 | | const field_count: u32 = @intCast(members.len - decl_count); |
| 5315 | | |
| 5316 | | if (layout != .auto and (auto_enum_tok != null or opt_arg_node != .none)) { |
| 5317 | | if (opt_arg_node.unwrap()) |arg_node| { |
| 5318 | | return astgen.failNode(arg_node, "{s} union does not support enum tag type", .{@tagName(layout)}); |
| 5319 | | } else { |
| 5320 | | return astgen.failTok(auto_enum_tok.?, "{s} union does not support enum tag type", .{@tagName(layout)}); |
| 5321 | | } |
| 5322 | | } |
| 5253 | const scan_result = try astgen.scanContainer(&namespace, members, .@"union"); |
| 5323 | 5254 | |
| 5324 | | const arg_inst: Zir.Inst.Ref = if (opt_arg_node.unwrap()) |arg_node| |
| 5325 | | try typeExpr(&block_scope, &namespace.base, arg_node) |
| 5326 | | else |
| 5327 | | .none; |
| 5255 | var scratch: Scratch = .init(astgen); |
| 5256 | defer scratch.reset(); |
| 5328 | 5257 | |
| 5329 | | const bits_per_field = 4; |
| 5330 | | const max_field_size = 4; |
| 5331 | | var any_aligned_fields = false; |
| 5332 | | var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size); |
| 5333 | | defer wip_members.deinit(); |
| 5258 | // Replicate the structure of the ZIR trailing data in `scratch` |
| 5259 | var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len); |
| 5260 | const field_names = try scratch.addSlice(scan_result.fields_len); |
| 5261 | const field_type_body_lens = try scratch.addSlice(scan_result.fields_len); |
| 5262 | const field_align_body_lens = try scratch.addOptionalSlice(scan_result.any_field_aligns, scan_result.fields_len); |
| 5263 | const field_value_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, scan_result.fields_len); |
| 5334 | 5264 | |
| 5335 | 5265 | const old_hasher = astgen.src_hasher; |
| 5336 | 5266 | defer astgen.src_hasher = old_hasher; |
| 5337 | | astgen.src_hasher = std.zig.SrcHasher.init(.{}); |
| 5338 | | astgen.src_hasher.update(@tagName(layout)); |
| 5339 | | astgen.src_hasher.update(&.{@intFromBool(auto_enum_tok != null)}); |
| 5340 | | if (opt_arg_node.unwrap()) |arg_node| { |
| 5341 | | astgen.src_hasher.update(astgen.tree.getNodeSource(arg_node)); |
| 5342 | | } |
| 5267 | astgen.src_hasher = .init(.{}); |
| 5343 | 5268 | |
| 5269 | var next_field_idx: u32 = 0; |
| 5344 | 5270 | for (members) |member_node| { |
| 5345 | | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { |
| 5271 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) { |
| 5346 | 5272 | .decl => continue, |
| 5347 | 5273 | .field => |field| field, |
| 5348 | 5274 | }; |
| 5275 | const field_idx = next_field_idx; |
| 5276 | next_field_idx += 1; |
| 5277 | |
| 5349 | 5278 | astgen.src_hasher.update(astgen.tree.getNodeSource(member_node)); |
| 5350 | 5279 | member.convertToNonTupleLike(astgen.tree); |
| 5351 | 5280 | if (member.ast.tuple_like) { |
| ... | ... | @@ -5355,97 +5284,91 @@ fn unionDeclInner( |
| 5355 | 5284 | return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{}); |
| 5356 | 5285 | } |
| 5357 | 5286 | |
| 5358 | | const field_name = try astgen.identAsString(member.ast.main_token); |
| 5359 | | wip_members.appendToField(@intFromEnum(field_name)); |
| 5360 | | |
| 5361 | | const have_type = member.ast.type_expr != .none; |
| 5362 | | const have_align = member.ast.align_expr != .none; |
| 5363 | | const have_value = member.ast.value_expr != .none; |
| 5364 | | const unused = false; |
| 5365 | | wip_members.nextField(bits_per_field, .{ have_type, have_align, have_value, unused }); |
| 5287 | field_names.get(astgen)[field_idx] = @intFromEnum(try astgen.identAsString(member.ast.main_token)); |
| 5366 | 5288 | |
| 5367 | | if (member.ast.type_expr.unwrap()) |type_expr| { |
| 5368 | | const field_type = try typeExpr(&block_scope, &namespace.base, type_expr); |
| 5369 | | wip_members.appendToField(@intFromEnum(field_type)); |
| 5370 | | } else if (arg_inst == .none and auto_enum_tok == null) { |
| 5289 | if (member.ast.type_expr.unwrap()) |type_node| { |
| 5290 | const type_ref = try typeExpr(&block_scope, &namespace.base, type_node); |
| 5291 | if (!block_scope.endsWithNoReturn()) { |
| 5292 | _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref); |
| 5293 | } |
| 5294 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); |
| 5295 | field_type_body_lens.get(astgen)[field_idx] = body_len; |
| 5296 | block_scope.instructions.items.len = block_scope.instructions_top; |
| 5297 | } else if (!is_tagged) { |
| 5371 | 5298 | return astgen.failNode(member_node, "union field missing type", .{}); |
| 5299 | } else { |
| 5300 | field_type_body_lens.get(astgen)[field_idx] = 0; |
| 5372 | 5301 | } |
| 5373 | | if (member.ast.align_expr.unwrap()) |align_expr| { |
| 5302 | |
| 5303 | if (member.ast.align_expr.unwrap()) |align_node| { |
| 5374 | 5304 | if (layout == .@"packed") { |
| 5375 | | return astgen.failNode(align_expr, "unable to override alignment of packed union fields", .{}); |
| 5305 | return astgen.failNode(align_node, "unable to override alignment of packed union fields", .{}); |
| 5376 | 5306 | } |
| 5377 | | const align_inst = try expr(&block_scope, &block_scope.base, coerced_align_ri, align_expr); |
| 5378 | | wip_members.appendToField(@intFromEnum(align_inst)); |
| 5379 | | any_aligned_fields = true; |
| 5380 | | } |
| 5381 | | if (member.ast.value_expr.unwrap()) |value_expr| { |
| 5382 | | if (arg_inst == .none) { |
| 5383 | | return astgen.failNodeNotes( |
| 5384 | | node, |
| 5385 | | "explicitly valued tagged union missing integer tag type", |
| 5386 | | .{}, |
| 5387 | | &[_]u32{ |
| 5388 | | try astgen.errNoteNode( |
| 5389 | | value_expr, |
| 5390 | | "tag value specified here", |
| 5391 | | .{}, |
| 5392 | | ), |
| 5393 | | }, |
| 5394 | | ); |
| 5307 | const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_node); |
| 5308 | if (!block_scope.endsWithNoReturn()) { |
| 5309 | _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref); |
| 5395 | 5310 | } |
| 5396 | | if (auto_enum_tok == null) { |
| 5397 | | return astgen.failNodeNotes( |
| 5398 | | node, |
| 5399 | | "explicitly valued tagged union requires inferred enum tag type", |
| 5400 | | .{}, |
| 5401 | | &[_]u32{ |
| 5402 | | try astgen.errNoteNode( |
| 5403 | | value_expr, |
| 5404 | | "tag value specified here", |
| 5405 | | .{}, |
| 5406 | | ), |
| 5407 | | }, |
| 5408 | | ); |
| 5311 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); |
| 5312 | field_align_body_lens.?.get(astgen)[field_idx] = body_len; |
| 5313 | block_scope.instructions.items.len = block_scope.instructions_top; |
| 5314 | } else if (field_align_body_lens) |lens| { |
| 5315 | lens.get(astgen)[field_idx] = 0; |
| 5316 | } |
| 5317 | |
| 5318 | if (member.ast.value_expr.unwrap()) |value_node| { |
| 5319 | if (!explicit_int_or_enum_tag) return astgen.failNodeNotes( |
| 5320 | node, |
| 5321 | "explicitly valued tagged union missing integer tag type", |
| 5322 | .{}, |
| 5323 | &.{try astgen.errNoteNode(value_node, "tag value specified here", .{})}, |
| 5324 | ); |
| 5325 | if (auto_enum_tok == null) return astgen.failNodeNotes( |
| 5326 | node, |
| 5327 | "explicitly valued tagged union requires inferred enum tag type", |
| 5328 | .{}, |
| 5329 | &.{try astgen.errNoteNode(value_node, "tag value specified here", .{})}, |
| 5330 | ); |
| 5331 | const ri: ResultInfo = .{ .rl = .{ .coerced_ty = decl_inst.toRef() } }; |
| 5332 | const value_ref = try expr(&block_scope, &namespace.base, ri, value_node); |
| 5333 | if (!block_scope.endsWithNoReturn()) { |
| 5334 | _ = try block_scope.addBreak(.break_inline, decl_inst, value_ref); |
| 5409 | 5335 | } |
| 5410 | | const tag_value = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = arg_inst } }, value_expr); |
| 5411 | | wip_members.appendToField(@intFromEnum(tag_value)); |
| 5336 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); |
| 5337 | field_value_body_lens.?.get(astgen)[field_idx] = body_len; |
| 5338 | block_scope.instructions.items.len = block_scope.instructions_top; |
| 5339 | } else if (field_value_body_lens) |lens| { |
| 5340 | lens.get(astgen)[field_idx] = 0; |
| 5412 | 5341 | } |
| 5413 | 5342 | } |
| 5343 | assert(next_field_idx == scan_result.fields_len); |
| 5344 | wip_decls.finish(); |
| 5414 | 5345 | |
| 5415 | 5346 | var fields_hash: std.zig.SrcHash = undefined; |
| 5416 | 5347 | astgen.src_hasher.final(&fields_hash); |
| 5417 | 5348 | |
| 5418 | | if (!block_scope.isEmpty()) { |
| 5419 | | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); |
| 5420 | | } |
| 5421 | | |
| 5422 | | const body = block_scope.instructionsSlice(); |
| 5423 | | const body_len = astgen.countBodyLenAfterFixups(body); |
| 5424 | | |
| 5425 | 5349 | try gz.setUnion(decl_inst, .{ |
| 5426 | 5350 | .src_node = node, |
| 5427 | | .layout = layout, |
| 5428 | | .tag_type = arg_inst, |
| 5429 | | .captures_len = @intCast(namespace.captures.count()), |
| 5430 | | .body_len = body_len, |
| 5431 | | .fields_len = field_count, |
| 5432 | | .decls_len = decl_count, |
| 5433 | | .auto_enum_tag = auto_enum_tok != null, |
| 5434 | | .any_aligned_fields = any_aligned_fields, |
| 5435 | | .fields_hash = fields_hash, |
| 5436 | 5351 | .name_strat = name_strat, |
| 5352 | .kind = switch (layout) { |
| 5353 | .auto => if (auto_enum_tok == null) l: { |
| 5354 | break :l if (opt_arg_node == .none) .auto else .tagged_explicit; |
| 5355 | } else l: { |
| 5356 | break :l if (opt_arg_node == .none) .tagged_enum else .tagged_enum_explicit; |
| 5357 | }, |
| 5358 | .@"extern" => .@"extern", |
| 5359 | .@"packed" => if (opt_arg_node != .none) .packed_explicit else .@"packed", |
| 5360 | }, |
| 5361 | .arg_type = arg_type_ref, |
| 5362 | .decls_len = scan_result.decls_len, |
| 5363 | .fields_len = scan_result.fields_len, |
| 5364 | .any_field_aligns = scan_result.any_field_aligns, |
| 5365 | .any_field_values = scan_result.any_field_values, |
| 5366 | .fields_hash = fields_hash, |
| 5367 | .captures = namespace.captures.keys(), |
| 5368 | .capture_names = namespace.captures.values(), |
| 5369 | .remaining = scratch.all().get(astgen), |
| 5437 | 5370 | }); |
| 5438 | 5371 | |
| 5439 | | wip_members.finishBits(bits_per_field); |
| 5440 | | const decls_slice = wip_members.declsSlice(); |
| 5441 | | const fields_slice = wip_members.fieldsSlice(); |
| 5442 | | try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() * 2 + decls_slice.len + body_len + fields_slice.len); |
| 5443 | | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); |
| 5444 | | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.values())); |
| 5445 | | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 5446 | | astgen.appendBodyWithFixups(body); |
| 5447 | | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 5448 | | |
| 5449 | 5372 | block_scope.unstack(); |
| 5450 | 5373 | return decl_inst.toRef(); |
| 5451 | 5374 | } |
| ... | ... | @@ -5494,103 +5417,13 @@ fn containerDecl( |
| 5494 | 5417 | if (container_decl.layout_token) |t| { |
| 5495 | 5418 | return astgen.failTok(t, "enums do not support 'packed' or 'extern'; instead provide an explicit integer tag type", .{}); |
| 5496 | 5419 | } |
| 5497 | | // Count total fields as well as how many have explicitly provided tag values. |
| 5498 | | const counts = blk: { |
| 5499 | | var values: usize = 0; |
| 5500 | | var total_fields: usize = 0; |
| 5501 | | var decls: usize = 0; |
| 5502 | | var opt_nonexhaustive_node: Ast.Node.OptionalIndex = .none; |
| 5503 | | var nonfinal_nonexhaustive = false; |
| 5504 | | for (container_decl.ast.members) |member_node| { |
| 5505 | | var member = tree.fullContainerField(member_node) orelse { |
| 5506 | | decls += 1; |
| 5507 | | continue; |
| 5508 | | }; |
| 5509 | | member.convertToNonTupleLike(astgen.tree); |
| 5510 | | if (member.ast.tuple_like) { |
| 5511 | | return astgen.failTok(member.ast.main_token, "enum field missing name", .{}); |
| 5512 | | } |
| 5513 | | if (member.comptime_token) |comptime_token| { |
| 5514 | | return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{}); |
| 5515 | | } |
| 5516 | | if (member.ast.type_expr.unwrap()) |type_expr| { |
| 5517 | | return astgen.failNodeNotes( |
| 5518 | | type_expr, |
| 5519 | | "enum fields do not have types", |
| 5520 | | .{}, |
| 5521 | | &[_]u32{ |
| 5522 | | try astgen.errNoteNode( |
| 5523 | | node, |
| 5524 | | "consider 'union(enum)' here to make it a tagged union", |
| 5525 | | .{}, |
| 5526 | | ), |
| 5527 | | }, |
| 5528 | | ); |
| 5529 | | } |
| 5530 | | if (member.ast.align_expr.unwrap()) |align_expr| { |
| 5531 | | return astgen.failNode(align_expr, "enum fields cannot be aligned", .{}); |
| 5532 | | } |
| 5533 | 5420 | |
| 5534 | | const name_token = member.ast.main_token; |
| 5535 | | if (mem.eql(u8, tree.tokenSlice(name_token), "_")) { |
| 5536 | | if (opt_nonexhaustive_node.unwrap()) |nonexhaustive_node| { |
| 5537 | | return astgen.failNodeNotes( |
| 5538 | | member_node, |
| 5539 | | "redundant non-exhaustive enum mark", |
| 5540 | | .{}, |
| 5541 | | &[_]u32{ |
| 5542 | | try astgen.errNoteNode( |
| 5543 | | nonexhaustive_node, |
| 5544 | | "other mark here", |
| 5545 | | .{}, |
| 5546 | | ), |
| 5547 | | }, |
| 5548 | | ); |
| 5549 | | } |
| 5550 | | opt_nonexhaustive_node = member_node.toOptional(); |
| 5551 | | if (member.ast.value_expr.unwrap()) |value_expr| { |
| 5552 | | return astgen.failNode(value_expr, "'_' is used to mark an enum as non-exhaustive and cannot be assigned a value", .{}); |
| 5553 | | } |
| 5554 | | continue; |
| 5555 | | } else if (opt_nonexhaustive_node != .none) { |
| 5556 | | nonfinal_nonexhaustive = true; |
| 5557 | | } |
| 5558 | | total_fields += 1; |
| 5559 | | if (member.ast.value_expr.unwrap()) |value_expr| { |
| 5560 | | if (container_decl.ast.arg == .none) { |
| 5561 | | return astgen.failNode(value_expr, "value assigned to enum tag with inferred tag type", .{}); |
| 5562 | | } |
| 5563 | | values += 1; |
| 5564 | | } |
| 5565 | | } |
| 5566 | | if (nonfinal_nonexhaustive) { |
| 5567 | | return astgen.failNode(opt_nonexhaustive_node.unwrap().?, "'_' field of non-exhaustive enum must be last", .{}); |
| 5568 | | } |
| 5569 | | break :blk .{ |
| 5570 | | .total_fields = total_fields, |
| 5571 | | .values = values, |
| 5572 | | .decls = decls, |
| 5573 | | .nonexhaustive_node = opt_nonexhaustive_node, |
| 5574 | | }; |
| 5421 | astgen.advanceSourceCursorToNode(node); |
| 5422 | |
| 5423 | const tag_type_ref: Zir.Inst.Ref = ref: { |
| 5424 | const arg_node = container_decl.ast.arg.unwrap() orelse break :ref .none; |
| 5425 | break :ref try typeExpr(gz, scope, arg_node); |
| 5575 | 5426 | }; |
| 5576 | | if (counts.nonexhaustive_node != .none and container_decl.ast.arg == .none) { |
| 5577 | | const nonexhaustive_node = counts.nonexhaustive_node.unwrap().?; |
| 5578 | | return astgen.failNodeNotes( |
| 5579 | | node, |
| 5580 | | "non-exhaustive enum missing integer tag type", |
| 5581 | | .{}, |
| 5582 | | &[_]u32{ |
| 5583 | | try astgen.errNoteNode( |
| 5584 | | nonexhaustive_node, |
| 5585 | | "marked non-exhaustive here", |
| 5586 | | .{}, |
| 5587 | | ), |
| 5588 | | }, |
| 5589 | | ); |
| 5590 | | } |
| 5591 | | // In this case we must generate ZIR code for the tag values, similar to |
| 5592 | | // how structs are handled above. |
| 5593 | | const nonexhaustive = counts.nonexhaustive_node != .none; |
| 5594 | 5427 | |
| 5595 | 5428 | const decl_inst = try gz.reserveInstructionIndex(); |
| 5596 | 5429 | |
| ... | ... | @@ -5605,7 +5438,6 @@ fn containerDecl( |
| 5605 | 5438 | |
| 5606 | 5439 | // The enum_decl instruction introduces a scope in which the decls of the enum |
| 5607 | 5440 | // are in scope, so that tag values can refer to decls within the enum itself. |
| 5608 | | astgen.advanceSourceCursorToNode(node); |
| 5609 | 5441 | var block_scope: GenZir = .{ |
| 5610 | 5442 | .parent = &namespace.base, |
| 5611 | 5443 | .decl_node_index = node, |
| ... | ... | @@ -5617,104 +5449,111 @@ fn containerDecl( |
| 5617 | 5449 | }; |
| 5618 | 5450 | defer block_scope.unstack(); |
| 5619 | 5451 | |
| 5620 | | _ = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"enum"); |
| 5621 | | namespace.base.tag = .namespace; |
| 5452 | const scan_result = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"enum"); |
| 5453 | // The name `_` is not actually a field; it marks a non-exhaustive enum. |
| 5454 | const fields_len: u32 = scan_result.fields_len - @intFromBool(scan_result.has_underscore_field); |
| 5622 | 5455 | |
| 5623 | | const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg.unwrap()) |arg| |
| 5624 | | try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, arg, .type) |
| 5625 | | else |
| 5626 | | .none; |
| 5456 | var scratch: Scratch = .init(astgen); |
| 5457 | defer scratch.reset(); |
| 5627 | 5458 | |
| 5628 | | const bits_per_field = 1; |
| 5629 | | const max_field_size = 2; |
| 5630 | | var wip_members = try WipMembers.init(gpa, &astgen.scratch, @intCast(counts.decls), @intCast(counts.total_fields), bits_per_field, max_field_size); |
| 5631 | | defer wip_members.deinit(); |
| 5459 | // Replicate the structure of the ZIR trailing data in `scratch` |
| 5460 | var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len); |
| 5461 | const field_names = try scratch.addSlice(fields_len); |
| 5462 | const field_value_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, fields_len); |
| 5632 | 5463 | |
| 5633 | 5464 | const old_hasher = astgen.src_hasher; |
| 5634 | 5465 | defer astgen.src_hasher = old_hasher; |
| 5635 | | astgen.src_hasher = std.zig.SrcHasher.init(.{}); |
| 5636 | | if (container_decl.ast.arg.unwrap()) |arg| { |
| 5637 | | astgen.src_hasher.update(tree.getNodeSource(arg)); |
| 5638 | | } |
| 5639 | | astgen.src_hasher.update(&.{@intFromBool(nonexhaustive)}); |
| 5466 | astgen.src_hasher = .init(.{}); |
| 5640 | 5467 | |
| 5468 | var next_field_idx: u32 = 0; |
| 5469 | var opt_nonexhaustive_node: Ast.Node.OptionalIndex = .none; |
| 5641 | 5470 | for (container_decl.ast.members) |member_node| { |
| 5642 | | if (member_node.toOptional() == counts.nonexhaustive_node) |
| 5643 | | continue; |
| 5644 | | astgen.src_hasher.update(tree.getNodeSource(member_node)); |
| 5645 | | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { |
| 5471 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) { |
| 5646 | 5472 | .decl => continue, |
| 5647 | 5473 | .field => |field| field, |
| 5648 | 5474 | }; |
| 5649 | 5475 | member.convertToNonTupleLike(astgen.tree); |
| 5650 | | assert(member.comptime_token == null); |
| 5651 | | assert(member.ast.type_expr == .none); |
| 5652 | | assert(member.ast.align_expr == .none); |
| 5476 | if (member.ast.tuple_like) return astgen.failTok(member.ast.main_token, "enum field missing name", .{}); |
| 5477 | if (member.comptime_token) |t| return astgen.failTok(t, "enum fields cannot be marked comptime", .{}); |
| 5478 | if (member.ast.type_expr.unwrap()) |type_node| { |
| 5479 | return astgen.failNodeNotes(type_node, "enum fields do not have types", .{}, &.{ |
| 5480 | try astgen.errNoteNode(node, "consider 'union(enum)' here to make it a tagged union", .{}), |
| 5481 | }); |
| 5482 | } |
| 5483 | if (member.ast.align_expr.unwrap()) |n| return astgen.failNode(n, "enum fields cannot be aligned", .{}); |
| 5484 | if (mem.eql(u8, tree.tokenSlice(member.ast.main_token), "_")) { |
| 5485 | // non-exhaustive mark |
| 5486 | assert(scan_result.has_underscore_field); |
| 5487 | if (opt_nonexhaustive_node.unwrap()) |prev_node| { |
| 5488 | return astgen.failNodeNotes(member_node, "redundant non-exhaustive enum mark", .{}, &.{ |
| 5489 | try astgen.errNoteNode(prev_node, "other mark here", .{}), |
| 5490 | }); |
| 5491 | } |
| 5492 | if (member.ast.value_expr.unwrap()) |value_node| { |
| 5493 | return astgen.failNode(value_node, "'_' is used to mark an enum as non-exhaustive and cannot be assigned a value", .{}); |
| 5494 | } |
| 5495 | if (next_field_idx != fields_len) { |
| 5496 | return astgen.failNode(member_node, "'_' field of non-exhaustive enum must be last", .{}); |
| 5497 | } |
| 5498 | opt_nonexhaustive_node = member_node.toOptional(); |
| 5499 | continue; |
| 5500 | } |
| 5653 | 5501 | |
| 5654 | | const field_name = try astgen.identAsString(member.ast.main_token); |
| 5655 | | wip_members.appendToField(@intFromEnum(field_name)); |
| 5502 | // This is a real field rather than a non-exhaustive mark. |
| 5503 | const field_idx = next_field_idx; |
| 5504 | next_field_idx += 1; |
| 5656 | 5505 | |
| 5657 | | const have_value = member.ast.value_expr != .none; |
| 5658 | | wip_members.nextField(bits_per_field, .{have_value}); |
| 5506 | astgen.src_hasher.update(tree.getNodeSource(member_node)); |
| 5659 | 5507 | |
| 5660 | | if (member.ast.value_expr.unwrap()) |value_expr| { |
| 5661 | | if (arg_inst == .none) { |
| 5662 | | return astgen.failNodeNotes( |
| 5663 | | node, |
| 5664 | | "explicitly valued enum missing integer tag type", |
| 5665 | | .{}, |
| 5666 | | &[_]u32{ |
| 5667 | | try astgen.errNoteNode( |
| 5668 | | value_expr, |
| 5669 | | "tag value specified here", |
| 5670 | | .{}, |
| 5671 | | ), |
| 5672 | | }, |
| 5673 | | ); |
| 5508 | field_names.get(astgen)[field_idx] = @intFromEnum(try astgen.identAsString(member.ast.main_token)); |
| 5509 | |
| 5510 | if (member.ast.value_expr.unwrap()) |value_node| { |
| 5511 | if (tag_type_ref == .none) { |
| 5512 | return astgen.failNodeNotes(node, "explicitly valued enum missing integer tag type", .{}, &.{ |
| 5513 | try astgen.errNoteNode(value_node, "tag value specified here", .{}), |
| 5514 | }); |
| 5515 | } |
| 5516 | const val_ri: ResultInfo = .{ .rl = .{ .coerced_ty = decl_inst.toRef() } }; |
| 5517 | const value_ref = try expr(&block_scope, &namespace.base, val_ri, value_node); |
| 5518 | if (!block_scope.endsWithNoReturn()) { |
| 5519 | _ = try block_scope.addBreak(.break_inline, decl_inst, value_ref); |
| 5674 | 5520 | } |
| 5675 | | const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, value_expr); |
| 5676 | | wip_members.appendToField(@intFromEnum(tag_value_inst)); |
| 5521 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); |
| 5522 | field_value_body_lens.?.get(astgen)[field_idx] = body_len; |
| 5523 | block_scope.instructions.items.len = block_scope.instructions_top; |
| 5524 | } else if (field_value_body_lens) |lens| { |
| 5525 | lens.get(astgen)[field_idx] = 0; |
| 5677 | 5526 | } |
| 5678 | 5527 | } |
| 5679 | | |
| 5680 | | if (!block_scope.isEmpty()) { |
| 5681 | | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); |
| 5682 | | } |
| 5528 | assert(scan_result.has_underscore_field == (opt_nonexhaustive_node != .none)); |
| 5529 | assert(next_field_idx == fields_len); |
| 5530 | wip_decls.finish(); |
| 5683 | 5531 | |
| 5684 | 5532 | var fields_hash: std.zig.SrcHash = undefined; |
| 5685 | 5533 | astgen.src_hasher.final(&fields_hash); |
| 5686 | 5534 | |
| 5687 | | const body = block_scope.instructionsSlice(); |
| 5688 | | const body_len = astgen.countBodyLenAfterFixups(body); |
| 5689 | | |
| 5690 | 5535 | try gz.setEnum(decl_inst, .{ |
| 5691 | 5536 | .src_node = node, |
| 5692 | | .nonexhaustive = nonexhaustive, |
| 5693 | | .tag_type = arg_inst, |
| 5694 | | .captures_len = @intCast(namespace.captures.count()), |
| 5695 | | .body_len = body_len, |
| 5696 | | .fields_len = @intCast(counts.total_fields), |
| 5697 | | .decls_len = @intCast(counts.decls), |
| 5698 | | .fields_hash = fields_hash, |
| 5699 | 5537 | .name_strat = name_strat, |
| 5538 | .tag_type = tag_type_ref, |
| 5539 | .nonexhaustive = scan_result.has_underscore_field, |
| 5540 | .decls_len = scan_result.decls_len, |
| 5541 | .fields_len = fields_len, |
| 5542 | .any_field_values = scan_result.any_field_values, |
| 5543 | .fields_hash = fields_hash, |
| 5544 | .captures = namespace.captures.keys(), |
| 5545 | .capture_names = namespace.captures.values(), |
| 5546 | .remaining = scratch.all().get(astgen), |
| 5700 | 5547 | }); |
| 5701 | 5548 | |
| 5702 | | wip_members.finishBits(bits_per_field); |
| 5703 | | const decls_slice = wip_members.declsSlice(); |
| 5704 | | const fields_slice = wip_members.fieldsSlice(); |
| 5705 | | try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() * 2 + decls_slice.len + body_len + fields_slice.len); |
| 5706 | | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); |
| 5707 | | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.values())); |
| 5708 | | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 5709 | | astgen.appendBodyWithFixups(body); |
| 5710 | | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 5711 | | |
| 5712 | 5549 | block_scope.unstack(); |
| 5713 | 5550 | return rvalue(gz, ri, decl_inst.toRef(), node); |
| 5714 | 5551 | }, |
| 5715 | 5552 | .keyword_opaque => { |
| 5716 | 5553 | assert(container_decl.ast.arg == .none); |
| 5717 | 5554 | |
| 5555 | astgen.advanceSourceCursorToNode(node); |
| 5556 | |
| 5718 | 5557 | const decl_inst = try gz.reserveInstructionIndex(); |
| 5719 | 5558 | |
| 5720 | 5559 | var namespace: Scope.Namespace = .{ |
| ... | ... | @@ -5726,7 +5565,6 @@ fn containerDecl( |
| 5726 | 5565 | }; |
| 5727 | 5566 | defer namespace.deinit(gpa); |
| 5728 | 5567 | |
| 5729 | | astgen.advanceSourceCursorToNode(node); |
| 5730 | 5568 | var block_scope: GenZir = .{ |
| 5731 | 5569 | .parent = &namespace.base, |
| 5732 | 5570 | .decl_node_index = node, |
| ... | ... | @@ -5738,36 +5576,34 @@ fn containerDecl( |
| 5738 | 5576 | }; |
| 5739 | 5577 | defer block_scope.unstack(); |
| 5740 | 5578 | |
| 5741 | | const decl_count = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"opaque"); |
| 5579 | const scan_result = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"opaque"); |
| 5742 | 5580 | |
| 5743 | | var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, 0, 0, 0); |
| 5744 | | defer wip_members.deinit(); |
| 5581 | var scratch: Scratch = .init(astgen); |
| 5582 | defer scratch.reset(); |
| 5583 | var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len); |
| 5745 | 5584 | |
| 5746 | 5585 | if (container_decl.layout_token) |layout_token| { |
| 5747 | 5586 | return astgen.failTok(layout_token, "opaque types do not support 'packed' or 'extern'", .{}); |
| 5748 | 5587 | } |
| 5749 | 5588 | |
| 5750 | 5589 | for (container_decl.ast.members) |member_node| { |
| 5751 | | const res = try containerMember(&block_scope, &namespace.base, &wip_members, member_node); |
| 5752 | | if (res == .field) { |
| 5753 | | return astgen.failNode(member_node, "opaque types cannot have fields", .{}); |
| 5590 | switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) { |
| 5591 | .decl => {}, |
| 5592 | .field => return astgen.failNode(member_node, "opaque types cannot have fields", .{}), |
| 5754 | 5593 | } |
| 5755 | 5594 | } |
| 5756 | 5595 | |
| 5596 | wip_decls.finish(); |
| 5597 | |
| 5757 | 5598 | try gz.setOpaque(decl_inst, .{ |
| 5758 | 5599 | .src_node = node, |
| 5759 | | .captures_len = @intCast(namespace.captures.count()), |
| 5760 | | .decls_len = decl_count, |
| 5761 | 5600 | .name_strat = name_strat, |
| 5601 | .decls_len = scan_result.decls_len, |
| 5602 | .captures = namespace.captures.keys(), |
| 5603 | .capture_names = namespace.captures.values(), |
| 5604 | .decls = @ptrCast(scratch.all().get(astgen)), |
| 5762 | 5605 | }); |
| 5763 | 5606 | |
| 5764 | | wip_members.finishBits(0); |
| 5765 | | const decls_slice = wip_members.declsSlice(); |
| 5766 | | try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() * 2 + decls_slice.len); |
| 5767 | | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); |
| 5768 | | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.values())); |
| 5769 | | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 5770 | | |
| 5771 | 5607 | block_scope.unstack(); |
| 5772 | 5608 | return rvalue(gz, ri, decl_inst.toRef(), node); |
| 5773 | 5609 | }, |
| ... | ... | @@ -5780,7 +5616,7 @@ const ContainerMemberResult = union(enum) { decl, field: Ast.full.ContainerField |
| 5780 | 5616 | fn containerMember( |
| 5781 | 5617 | gz: *GenZir, |
| 5782 | 5618 | scope: *Scope, |
| 5783 | | wip_members: *WipMembers, |
| 5619 | wip_decls: *WipDecls, |
| 5784 | 5620 | member_node: Ast.Node.Index, |
| 5785 | 5621 | ) InnerError!ContainerMemberResult { |
| 5786 | 5622 | const astgen = gz.astgen; |
| ... | ... | @@ -5805,13 +5641,13 @@ fn containerMember( |
| 5805 | 5641 | else |
| 5806 | 5642 | .none; |
| 5807 | 5643 | |
| 5808 | | const prev_decl_index = wip_members.decl_index; |
| 5809 | | astgen.fnDecl(gz, scope, wip_members, member_node, body, full) catch |err| switch (err) { |
| 5644 | const prev_decl_index = wip_decls.index; |
| 5645 | astgen.fnDecl(gz, scope, wip_decls, member_node, body, full) catch |err| switch (err) { |
| 5810 | 5646 | error.OutOfMemory => return error.OutOfMemory, |
| 5811 | 5647 | error.AnalysisFail => { |
| 5812 | | wip_members.decl_index = prev_decl_index; |
| 5648 | wip_decls.index = prev_decl_index; |
| 5813 | 5649 | try addFailedDeclaration( |
| 5814 | | wip_members, |
| 5650 | wip_decls, |
| 5815 | 5651 | gz, |
| 5816 | 5652 | .@"const", |
| 5817 | 5653 | try astgen.identAsString(full.name_token.?), |
| ... | ... | @@ -5828,13 +5664,13 @@ fn containerMember( |
| 5828 | 5664 | .aligned_var_decl, |
| 5829 | 5665 | => { |
| 5830 | 5666 | const full = tree.fullVarDecl(member_node).?; |
| 5831 | | const prev_decl_index = wip_members.decl_index; |
| 5832 | | astgen.globalVarDecl(gz, scope, wip_members, member_node, full) catch |err| switch (err) { |
| 5667 | const prev_decl_index = wip_decls.index; |
| 5668 | astgen.globalVarDecl(gz, scope, wip_decls, member_node, full) catch |err| switch (err) { |
| 5833 | 5669 | error.OutOfMemory => return error.OutOfMemory, |
| 5834 | 5670 | error.AnalysisFail => { |
| 5835 | | wip_members.decl_index = prev_decl_index; |
| 5671 | wip_decls.index = prev_decl_index; |
| 5836 | 5672 | try addFailedDeclaration( |
| 5837 | | wip_members, |
| 5673 | wip_decls, |
| 5838 | 5674 | gz, |
| 5839 | 5675 | .@"const", // doesn't really matter |
| 5840 | 5676 | try astgen.identAsString(full.ast.mut_token + 1), |
| ... | ... | @@ -5846,13 +5682,13 @@ fn containerMember( |
| 5846 | 5682 | }, |
| 5847 | 5683 | |
| 5848 | 5684 | .@"comptime" => { |
| 5849 | | const prev_decl_index = wip_members.decl_index; |
| 5850 | | astgen.comptimeDecl(gz, scope, wip_members, member_node) catch |err| switch (err) { |
| 5685 | const prev_decl_index = wip_decls.index; |
| 5686 | astgen.comptimeDecl(gz, scope, wip_decls, member_node) catch |err| switch (err) { |
| 5851 | 5687 | error.OutOfMemory => return error.OutOfMemory, |
| 5852 | 5688 | error.AnalysisFail => { |
| 5853 | | wip_members.decl_index = prev_decl_index; |
| 5689 | wip_decls.index = prev_decl_index; |
| 5854 | 5690 | try addFailedDeclaration( |
| 5855 | | wip_members, |
| 5691 | wip_decls, |
| 5856 | 5692 | gz, |
| 5857 | 5693 | .@"comptime", |
| 5858 | 5694 | .empty, |
| ... | ... | @@ -5863,16 +5699,16 @@ fn containerMember( |
| 5863 | 5699 | }; |
| 5864 | 5700 | }, |
| 5865 | 5701 | .test_decl => { |
| 5866 | | const prev_decl_index = wip_members.decl_index; |
| 5702 | const prev_decl_index = wip_decls.index; |
| 5867 | 5703 | // We need to have *some* decl here so that the decl count matches what's expected. |
| 5868 | 5704 | // Since it doesn't strictly matter *what* this is, let's save ourselves the trouble |
| 5869 | 5705 | // of duplicating the test name logic, and just assume this is an unnamed test. |
| 5870 | | astgen.testDecl(gz, scope, wip_members, member_node) catch |err| switch (err) { |
| 5706 | astgen.testDecl(gz, scope, wip_decls, member_node) catch |err| switch (err) { |
| 5871 | 5707 | error.OutOfMemory => return error.OutOfMemory, |
| 5872 | 5708 | error.AnalysisFail => { |
| 5873 | | wip_members.decl_index = prev_decl_index; |
| 5709 | wip_decls.index = prev_decl_index; |
| 5874 | 5710 | try addFailedDeclaration( |
| 5875 | | wip_members, |
| 5711 | wip_decls, |
| 5876 | 5712 | gz, |
| 5877 | 5713 | .unnamed_test, |
| 5878 | 5714 | .empty, |
| ... | ... | @@ -10619,495 +10455,19 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev |
| 10619 | 10455 | } |
| 10620 | 10456 | } |
| 10621 | 10457 | |
| 10622 | | /// Returns `true` if it is known the type expression has more than one possible value; |
| 10623 | | /// `false` otherwise. |
| 10624 | | fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.Index) bool { |
| 10625 | | var node = start_node; |
| 10626 | | while (true) { |
| 10627 | | switch (tree.nodeTag(node)) { |
| 10628 | | .root, |
| 10629 | | .test_decl, |
| 10630 | | .switch_case, |
| 10631 | | .switch_case_inline, |
| 10632 | | .switch_case_one, |
| 10633 | | .switch_case_inline_one, |
| 10634 | | .container_field_init, |
| 10635 | | .container_field_align, |
| 10636 | | .container_field, |
| 10637 | | .asm_output, |
| 10638 | | .asm_input, |
| 10639 | | .global_var_decl, |
| 10640 | | .local_var_decl, |
| 10641 | | .simple_var_decl, |
| 10642 | | .aligned_var_decl, |
| 10643 | | => unreachable, |
| 10644 | | |
| 10645 | | .@"return", |
| 10646 | | .@"break", |
| 10647 | | .@"continue", |
| 10648 | | .bit_not, |
| 10649 | | .bool_not, |
| 10650 | | .@"defer", |
| 10651 | | .@"errdefer", |
| 10652 | | .address_of, |
| 10653 | | .negation, |
| 10654 | | .negation_wrap, |
| 10655 | | .@"resume", |
| 10656 | | .array_type, |
| 10657 | | .@"suspend", |
| 10658 | | .fn_decl, |
| 10659 | | .anyframe_literal, |
| 10660 | | .number_literal, |
| 10661 | | .enum_literal, |
| 10662 | | .string_literal, |
| 10663 | | .multiline_string_literal, |
| 10664 | | .char_literal, |
| 10665 | | .unreachable_literal, |
| 10666 | | .error_set_decl, |
| 10667 | | .container_decl, |
| 10668 | | .container_decl_trailing, |
| 10669 | | .container_decl_two, |
| 10670 | | .container_decl_two_trailing, |
| 10671 | | .container_decl_arg, |
| 10672 | | .container_decl_arg_trailing, |
| 10673 | | .tagged_union, |
| 10674 | | .tagged_union_trailing, |
| 10675 | | .tagged_union_two, |
| 10676 | | .tagged_union_two_trailing, |
| 10677 | | .tagged_union_enum_tag, |
| 10678 | | .tagged_union_enum_tag_trailing, |
| 10679 | | .@"asm", |
| 10680 | | .asm_simple, |
| 10681 | | .add, |
| 10682 | | .add_wrap, |
| 10683 | | .add_sat, |
| 10684 | | .array_cat, |
| 10685 | | .array_mult, |
| 10686 | | .assign, |
| 10687 | | .assign_destructure, |
| 10688 | | .assign_bit_and, |
| 10689 | | .assign_bit_or, |
| 10690 | | .assign_shl, |
| 10691 | | .assign_shl_sat, |
| 10692 | | .assign_shr, |
| 10693 | | .assign_bit_xor, |
| 10694 | | .assign_div, |
| 10695 | | .assign_sub, |
| 10696 | | .assign_sub_wrap, |
| 10697 | | .assign_sub_sat, |
| 10698 | | .assign_mod, |
| 10699 | | .assign_add, |
| 10700 | | .assign_add_wrap, |
| 10701 | | .assign_add_sat, |
| 10702 | | .assign_mul, |
| 10703 | | .assign_mul_wrap, |
| 10704 | | .assign_mul_sat, |
| 10705 | | .bang_equal, |
| 10706 | | .bit_and, |
| 10707 | | .bit_or, |
| 10708 | | .shl, |
| 10709 | | .shl_sat, |
| 10710 | | .shr, |
| 10711 | | .bit_xor, |
| 10712 | | .bool_and, |
| 10713 | | .bool_or, |
| 10714 | | .div, |
| 10715 | | .equal_equal, |
| 10716 | | .error_union, |
| 10717 | | .greater_or_equal, |
| 10718 | | .greater_than, |
| 10719 | | .less_or_equal, |
| 10720 | | .less_than, |
| 10721 | | .merge_error_sets, |
| 10722 | | .mod, |
| 10723 | | .mul, |
| 10724 | | .mul_wrap, |
| 10725 | | .mul_sat, |
| 10726 | | .switch_range, |
| 10727 | | .for_range, |
| 10728 | | .field_access, |
| 10729 | | .sub, |
| 10730 | | .sub_wrap, |
| 10731 | | .sub_sat, |
| 10732 | | .slice, |
| 10733 | | .slice_open, |
| 10734 | | .slice_sentinel, |
| 10735 | | .deref, |
| 10736 | | .array_access, |
| 10737 | | .error_value, |
| 10738 | | .while_simple, |
| 10739 | | .while_cont, |
| 10740 | | .for_simple, |
| 10741 | | .if_simple, |
| 10742 | | .@"catch", |
| 10743 | | .@"orelse", |
| 10744 | | .array_init_one, |
| 10745 | | .array_init_one_comma, |
| 10746 | | .array_init_dot_two, |
| 10747 | | .array_init_dot_two_comma, |
| 10748 | | .array_init_dot, |
| 10749 | | .array_init_dot_comma, |
| 10750 | | .array_init, |
| 10751 | | .array_init_comma, |
| 10752 | | .struct_init_one, |
| 10753 | | .struct_init_one_comma, |
| 10754 | | .struct_init_dot_two, |
| 10755 | | .struct_init_dot_two_comma, |
| 10756 | | .struct_init_dot, |
| 10757 | | .struct_init_dot_comma, |
| 10758 | | .struct_init, |
| 10759 | | .struct_init_comma, |
| 10760 | | .@"while", |
| 10761 | | .@"if", |
| 10762 | | .@"for", |
| 10763 | | .@"switch", |
| 10764 | | .switch_comma, |
| 10765 | | .call_one, |
| 10766 | | .call_one_comma, |
| 10767 | | .call, |
| 10768 | | .call_comma, |
| 10769 | | .block_two, |
| 10770 | | .block_two_semicolon, |
| 10771 | | .block, |
| 10772 | | .block_semicolon, |
| 10773 | | .builtin_call, |
| 10774 | | .builtin_call_comma, |
| 10775 | | .builtin_call_two, |
| 10776 | | .builtin_call_two_comma, |
| 10777 | | // these are function bodies, not pointers |
| 10778 | | .fn_proto_simple, |
| 10779 | | .fn_proto_multi, |
| 10780 | | .fn_proto_one, |
| 10781 | | .fn_proto, |
| 10782 | | => return false, |
| 10783 | | |
| 10784 | | // Forward the question to the LHS sub-expression. |
| 10785 | | .@"try", |
| 10786 | | .@"comptime", |
| 10787 | | .@"nosuspend", |
| 10788 | | => node = tree.nodeData(node).node, |
| 10789 | | .grouped_expression, |
| 10790 | | .unwrap_optional, |
| 10791 | | => node = tree.nodeData(node).node_and_token[0], |
| 10792 | | |
| 10793 | | .ptr_type_aligned, |
| 10794 | | .ptr_type_sentinel, |
| 10795 | | .ptr_type, |
| 10796 | | .ptr_type_bit_range, |
| 10797 | | .optional_type, |
| 10798 | | .anyframe_type, |
| 10799 | | .array_type_sentinel, |
| 10800 | | => return true, |
| 10801 | | |
| 10802 | | .identifier => { |
| 10803 | | const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node)); |
| 10804 | | if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) { |
| 10805 | | .anyerror_type, |
| 10806 | | .anyframe_type, |
| 10807 | | .anyopaque_type, |
| 10808 | | .bool_type, |
| 10809 | | .c_int_type, |
| 10810 | | .c_long_type, |
| 10811 | | .c_longdouble_type, |
| 10812 | | .c_longlong_type, |
| 10813 | | .c_char_type, |
| 10814 | | .c_short_type, |
| 10815 | | .c_uint_type, |
| 10816 | | .c_ulong_type, |
| 10817 | | .c_ulonglong_type, |
| 10818 | | .c_ushort_type, |
| 10819 | | .comptime_float_type, |
| 10820 | | .comptime_int_type, |
| 10821 | | .f16_type, |
| 10822 | | .f32_type, |
| 10823 | | .f64_type, |
| 10824 | | .f80_type, |
| 10825 | | .f128_type, |
| 10826 | | .i16_type, |
| 10827 | | .i32_type, |
| 10828 | | .i64_type, |
| 10829 | | .i128_type, |
| 10830 | | .i8_type, |
| 10831 | | .isize_type, |
| 10832 | | .type_type, |
| 10833 | | .u16_type, |
| 10834 | | .u29_type, |
| 10835 | | .u32_type, |
| 10836 | | .u64_type, |
| 10837 | | .u128_type, |
| 10838 | | .u1_type, |
| 10839 | | .u8_type, |
| 10840 | | .usize_type, |
| 10841 | | => return true, |
| 10842 | | |
| 10843 | | .void_type, |
| 10844 | | .bool_false, |
| 10845 | | .bool_true, |
| 10846 | | .null_value, |
| 10847 | | .undef, |
| 10848 | | .noreturn_type, |
| 10849 | | => return false, |
| 10850 | | |
| 10851 | | else => unreachable, // that's all the values from `primitives`. |
| 10852 | | } else { |
| 10853 | | return false; |
| 10854 | | } |
| 10855 | | }, |
| 10856 | | } |
| 10857 | | } |
| 10858 | | } |
| 10859 | | |
| 10860 | | /// Returns `true` if it is known the expression is a type that cannot be used at runtime; |
| 10861 | | /// `false` otherwise. |
| 10862 | | fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool { |
| 10863 | | var node = start_node; |
| 10864 | | while (true) { |
| 10865 | | switch (tree.nodeTag(node)) { |
| 10866 | | .root, |
| 10867 | | .test_decl, |
| 10868 | | .switch_case, |
| 10869 | | .switch_case_inline, |
| 10870 | | .switch_case_one, |
| 10871 | | .switch_case_inline_one, |
| 10872 | | .container_field_init, |
| 10873 | | .container_field_align, |
| 10874 | | .container_field, |
| 10875 | | .asm_output, |
| 10876 | | .asm_input, |
| 10877 | | .global_var_decl, |
| 10878 | | .local_var_decl, |
| 10879 | | .simple_var_decl, |
| 10880 | | .aligned_var_decl, |
| 10881 | | => unreachable, |
| 10882 | | |
| 10883 | | .@"return", |
| 10884 | | .@"break", |
| 10885 | | .@"continue", |
| 10886 | | .bit_not, |
| 10887 | | .bool_not, |
| 10888 | | .@"defer", |
| 10889 | | .@"errdefer", |
| 10890 | | .address_of, |
| 10891 | | .negation, |
| 10892 | | .negation_wrap, |
| 10893 | | .@"resume", |
| 10894 | | .array_type, |
| 10895 | | .@"suspend", |
| 10896 | | .fn_decl, |
| 10897 | | .anyframe_literal, |
| 10898 | | .number_literal, |
| 10899 | | .enum_literal, |
| 10900 | | .string_literal, |
| 10901 | | .multiline_string_literal, |
| 10902 | | .char_literal, |
| 10903 | | .unreachable_literal, |
| 10904 | | .error_set_decl, |
| 10905 | | .container_decl, |
| 10906 | | .container_decl_trailing, |
| 10907 | | .container_decl_two, |
| 10908 | | .container_decl_two_trailing, |
| 10909 | | .container_decl_arg, |
| 10910 | | .container_decl_arg_trailing, |
| 10911 | | .tagged_union, |
| 10912 | | .tagged_union_trailing, |
| 10913 | | .tagged_union_two, |
| 10914 | | .tagged_union_two_trailing, |
| 10915 | | .tagged_union_enum_tag, |
| 10916 | | .tagged_union_enum_tag_trailing, |
| 10917 | | .@"asm", |
| 10918 | | .asm_simple, |
| 10919 | | .add, |
| 10920 | | .add_wrap, |
| 10921 | | .add_sat, |
| 10922 | | .array_cat, |
| 10923 | | .array_mult, |
| 10924 | | .assign, |
| 10925 | | .assign_destructure, |
| 10926 | | .assign_bit_and, |
| 10927 | | .assign_bit_or, |
| 10928 | | .assign_shl, |
| 10929 | | .assign_shl_sat, |
| 10930 | | .assign_shr, |
| 10931 | | .assign_bit_xor, |
| 10932 | | .assign_div, |
| 10933 | | .assign_sub, |
| 10934 | | .assign_sub_wrap, |
| 10935 | | .assign_sub_sat, |
| 10936 | | .assign_mod, |
| 10937 | | .assign_add, |
| 10938 | | .assign_add_wrap, |
| 10939 | | .assign_add_sat, |
| 10940 | | .assign_mul, |
| 10941 | | .assign_mul_wrap, |
| 10942 | | .assign_mul_sat, |
| 10943 | | .bang_equal, |
| 10944 | | .bit_and, |
| 10945 | | .bit_or, |
| 10946 | | .shl, |
| 10947 | | .shl_sat, |
| 10948 | | .shr, |
| 10949 | | .bit_xor, |
| 10950 | | .bool_and, |
| 10951 | | .bool_or, |
| 10952 | | .div, |
| 10953 | | .equal_equal, |
| 10954 | | .error_union, |
| 10955 | | .greater_or_equal, |
| 10956 | | .greater_than, |
| 10957 | | .less_or_equal, |
| 10958 | | .less_than, |
| 10959 | | .merge_error_sets, |
| 10960 | | .mod, |
| 10961 | | .mul, |
| 10962 | | .mul_wrap, |
| 10963 | | .mul_sat, |
| 10964 | | .switch_range, |
| 10965 | | .for_range, |
| 10966 | | .field_access, |
| 10967 | | .sub, |
| 10968 | | .sub_wrap, |
| 10969 | | .sub_sat, |
| 10970 | | .slice, |
| 10971 | | .slice_open, |
| 10972 | | .slice_sentinel, |
| 10973 | | .deref, |
| 10974 | | .array_access, |
| 10975 | | .error_value, |
| 10976 | | .while_simple, |
| 10977 | | .while_cont, |
| 10978 | | .for_simple, |
| 10979 | | .if_simple, |
| 10980 | | .@"catch", |
| 10981 | | .@"orelse", |
| 10982 | | .array_init_one, |
| 10983 | | .array_init_one_comma, |
| 10984 | | .array_init_dot_two, |
| 10985 | | .array_init_dot_two_comma, |
| 10986 | | .array_init_dot, |
| 10987 | | .array_init_dot_comma, |
| 10988 | | .array_init, |
| 10989 | | .array_init_comma, |
| 10990 | | .struct_init_one, |
| 10991 | | .struct_init_one_comma, |
| 10992 | | .struct_init_dot_two, |
| 10993 | | .struct_init_dot_two_comma, |
| 10994 | | .struct_init_dot, |
| 10995 | | .struct_init_dot_comma, |
| 10996 | | .struct_init, |
| 10997 | | .struct_init_comma, |
| 10998 | | .@"while", |
| 10999 | | .@"if", |
| 11000 | | .@"for", |
| 11001 | | .@"switch", |
| 11002 | | .switch_comma, |
| 11003 | | .call_one, |
| 11004 | | .call_one_comma, |
| 11005 | | .call, |
| 11006 | | .call_comma, |
| 11007 | | .block_two, |
| 11008 | | .block_two_semicolon, |
| 11009 | | .block, |
| 11010 | | .block_semicolon, |
| 11011 | | .builtin_call, |
| 11012 | | .builtin_call_comma, |
| 11013 | | .builtin_call_two, |
| 11014 | | .builtin_call_two_comma, |
| 11015 | | .ptr_type_aligned, |
| 11016 | | .ptr_type_sentinel, |
| 11017 | | .ptr_type, |
| 11018 | | .ptr_type_bit_range, |
| 11019 | | .optional_type, |
| 11020 | | .anyframe_type, |
| 11021 | | .array_type_sentinel, |
| 11022 | | => return false, |
| 11023 | | |
| 11024 | | // these are function bodies, not pointers |
| 11025 | | .fn_proto_simple, |
| 11026 | | .fn_proto_multi, |
| 11027 | | .fn_proto_one, |
| 11028 | | .fn_proto, |
| 11029 | | => return true, |
| 11030 | | |
| 11031 | | // Forward the question to the LHS sub-expression. |
| 11032 | | .@"try", |
| 11033 | | .@"comptime", |
| 11034 | | .@"nosuspend", |
| 11035 | | => node = tree.nodeData(node).node, |
| 11036 | | .grouped_expression, |
| 11037 | | .unwrap_optional, |
| 11038 | | => node = tree.nodeData(node).node_and_token[0], |
| 11039 | | |
| 11040 | | .identifier => { |
| 11041 | | const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node)); |
| 11042 | | if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) { |
| 11043 | | .anyerror_type, |
| 11044 | | .anyframe_type, |
| 11045 | | .anyopaque_type, |
| 11046 | | .bool_type, |
| 11047 | | .c_int_type, |
| 11048 | | .c_long_type, |
| 11049 | | .c_longdouble_type, |
| 11050 | | .c_longlong_type, |
| 11051 | | .c_char_type, |
| 11052 | | .c_short_type, |
| 11053 | | .c_uint_type, |
| 11054 | | .c_ulong_type, |
| 11055 | | .c_ulonglong_type, |
| 11056 | | .c_ushort_type, |
| 11057 | | .f16_type, |
| 11058 | | .f32_type, |
| 11059 | | .f64_type, |
| 11060 | | .f80_type, |
| 11061 | | .f128_type, |
| 11062 | | .i16_type, |
| 11063 | | .i32_type, |
| 11064 | | .i64_type, |
| 11065 | | .i128_type, |
| 11066 | | .i8_type, |
| 11067 | | .isize_type, |
| 11068 | | .u16_type, |
| 11069 | | .u29_type, |
| 11070 | | .u32_type, |
| 11071 | | .u64_type, |
| 11072 | | .u128_type, |
| 11073 | | .u1_type, |
| 11074 | | .u8_type, |
| 11075 | | .usize_type, |
| 11076 | | .void_type, |
| 11077 | | .bool_false, |
| 11078 | | .bool_true, |
| 11079 | | .null_value, |
| 11080 | | .undef, |
| 11081 | | .noreturn_type, |
| 11082 | | => return false, |
| 11083 | | |
| 11084 | | .comptime_float_type, |
| 11085 | | .comptime_int_type, |
| 11086 | | .type_type, |
| 11087 | | => return true, |
| 11088 | | |
| 11089 | | else => unreachable, // that's all the values from `primitives`. |
| 11090 | | } else { |
| 11091 | | return false; |
| 11092 | | } |
| 11093 | | }, |
| 11094 | | } |
| 11095 | | } |
| 11096 | | } |
| 11097 | | |
| 11098 | | /// Applies `rl` semantics to `result`. Expressions which do not do their own handling of |
| 11099 | | /// result locations must call this function on their result. |
| 11100 | | /// As an example, if `ri.rl` is `.ptr`, it will write the result to the pointer. |
| 11101 | | /// If `ri.rl` is `.ty`, it will coerce the result to the type. |
| 11102 | | /// Assumes nothing stacked on `gz`. |
| 11103 | | fn rvalue( |
| 11104 | | gz: *GenZir, |
| 11105 | | ri: ResultInfo, |
| 11106 | | raw_result: Zir.Inst.Ref, |
| 11107 | | src_node: Ast.Node.Index, |
| 11108 | | ) InnerError!Zir.Inst.Ref { |
| 11109 | | return rvalueInner(gz, ri, raw_result, src_node, true); |
| 11110 | | } |
| 10458 | /// Applies `rl` semantics to `result`. Expressions which do not do their own handling of |
| 10459 | /// result locations must call this function on their result. |
| 10460 | /// As an example, if `ri.rl` is `.ptr`, it will write the result to the pointer. |
| 10461 | /// If `ri.rl` is `.ty`, it will coerce the result to the type. |
| 10462 | /// Assumes nothing stacked on `gz`. |
| 10463 | fn rvalue( |
| 10464 | gz: *GenZir, |
| 10465 | ri: ResultInfo, |
| 10466 | raw_result: Zir.Inst.Ref, |
| 10467 | src_node: Ast.Node.Index, |
| 10468 | ) InnerError!Zir.Inst.Ref { |
| 10469 | return rvalueInner(gz, ri, raw_result, src_node, true); |
| 10470 | } |
| 11111 | 10471 | |
| 11112 | 10472 | /// Like `rvalue`, but refuses to perform coercions before taking references for |
| 11113 | 10473 | /// the `ref_coerced_ty` result type. This is used for local variables which do |
| ... | ... | @@ -13044,18 +12404,19 @@ const GenZir = struct { |
| 13044 | 12404 | |
| 13045 | 12405 | fn setStruct(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 13046 | 12406 | src_node: Ast.Node.Index, |
| 13047 | | captures_len: u32, |
| 13048 | | fields_len: u32, |
| 13049 | | decls_len: u32, |
| 13050 | | has_backing_int: bool, |
| 12407 | name_strat: Zir.Inst.NameStrategy, |
| 13051 | 12408 | layout: std.builtin.Type.ContainerLayout, |
| 13052 | | known_non_opv: bool, |
| 13053 | | known_comptime_only: bool, |
| 12409 | backing_int_type: Zir.Inst.Ref, |
| 12410 | decls_len: u32, |
| 12411 | fields_len: u32, |
| 12412 | any_field_aligns: bool, |
| 12413 | any_field_defaults: bool, |
| 13054 | 12414 | any_comptime_fields: bool, |
| 13055 | | any_default_inits: bool, |
| 13056 | | any_aligned_fields: bool, |
| 13057 | 12415 | fields_hash: std.zig.SrcHash, |
| 13058 | | name_strat: Zir.Inst.NameStrategy, |
| 12416 | captures: []const Zir.Inst.Capture, |
| 12417 | capture_names: []const Zir.NullTerminatedString, |
| 12418 | /// The trailing declaration list, field information, and body instructions. |
| 12419 | remaining: []const u32, |
| 13059 | 12420 | }) !void { |
| 13060 | 12421 | const astgen = gz.astgen; |
| 13061 | 12422 | const gpa = astgen.gpa; |
| ... | ... | @@ -13063,9 +12424,16 @@ const GenZir = struct { |
| 13063 | 12424 | // Node .root is valid for the root `struct_decl` of a file! |
| 13064 | 12425 | assert(args.src_node != .root or gz.parent.tag == .top); |
| 13065 | 12426 | |
| 12427 | const captures_len: u32 = @intCast(args.captures.len); |
| 12428 | assert(args.capture_names.len == captures_len); |
| 12429 | |
| 13066 | 12430 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 13067 | 12431 | |
| 13068 | | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len + 3); |
| 12432 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len + |
| 12433 | 4 + // `captures_len`, `decls_len`, `fields_len`, `backing_int_type` |
| 12434 | captures_len * 2 + // `capture`, `capture_name` |
| 12435 | args.remaining.len); |
| 12436 | |
| 13069 | 12437 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.StructDecl{ |
| 13070 | 12438 | .fields_hash_0 = fields_hash_arr[0], |
| 13071 | 12439 | .fields_hash_1 = fields_hash_arr[1], |
| ... | ... | @@ -13075,31 +12443,28 @@ const GenZir = struct { |
| 13075 | 12443 | .src_node = args.src_node, |
| 13076 | 12444 | }); |
| 13077 | 12445 | |
| 13078 | | if (args.captures_len != 0) { |
| 13079 | | astgen.extra.appendAssumeCapacity(args.captures_len); |
| 13080 | | } |
| 13081 | | if (args.fields_len != 0) { |
| 13082 | | astgen.extra.appendAssumeCapacity(args.fields_len); |
| 13083 | | } |
| 13084 | | if (args.decls_len != 0) { |
| 13085 | | astgen.extra.appendAssumeCapacity(args.decls_len); |
| 13086 | | } |
| 12446 | if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len); |
| 12447 | if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len); |
| 12448 | if (args.fields_len != 0) astgen.extra.appendAssumeCapacity(args.fields_len); |
| 12449 | if (args.backing_int_type != .none) astgen.extra.appendAssumeCapacity(@intFromEnum(args.backing_int_type)); |
| 12450 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures)); |
| 12451 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names)); |
| 12452 | astgen.extra.appendSliceAssumeCapacity(args.remaining); |
| 12453 | |
| 13087 | 12454 | astgen.instructions.set(@intFromEnum(inst), .{ |
| 13088 | 12455 | .tag = .extended, |
| 13089 | 12456 | .data = .{ .extended = .{ |
| 13090 | 12457 | .opcode = .struct_decl, |
| 13091 | 12458 | .small = @bitCast(Zir.Inst.StructDecl.Small{ |
| 13092 | | .has_captures_len = args.captures_len != 0, |
| 13093 | | .has_fields_len = args.fields_len != 0, |
| 12459 | .has_captures_len = captures_len != 0, |
| 13094 | 12460 | .has_decls_len = args.decls_len != 0, |
| 13095 | | .has_backing_int = args.has_backing_int, |
| 13096 | | .known_non_opv = args.known_non_opv, |
| 13097 | | .known_comptime_only = args.known_comptime_only, |
| 12461 | .has_fields_len = args.fields_len != 0, |
| 13098 | 12462 | .name_strategy = args.name_strat, |
| 13099 | 12463 | .layout = args.layout, |
| 12464 | .has_backing_int_type = args.backing_int_type != .none, |
| 12465 | .any_field_aligns = args.any_field_aligns, |
| 12466 | .any_field_defaults = args.any_field_defaults, |
| 13100 | 12467 | .any_comptime_fields = args.any_comptime_fields, |
| 13101 | | .any_default_inits = args.any_default_inits, |
| 13102 | | .any_aligned_fields = args.any_aligned_fields, |
| 13103 | 12468 | }), |
| 13104 | 12469 | .operand = payload_index, |
| 13105 | 12470 | } }, |
| ... | ... | @@ -13108,25 +12473,34 @@ const GenZir = struct { |
| 13108 | 12473 | |
| 13109 | 12474 | fn setUnion(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 13110 | 12475 | src_node: Ast.Node.Index, |
| 13111 | | tag_type: Zir.Inst.Ref, |
| 13112 | | captures_len: u32, |
| 13113 | | body_len: u32, |
| 13114 | | fields_len: u32, |
| 12476 | name_strat: Zir.Inst.NameStrategy, |
| 12477 | kind: Zir.Inst.UnionDecl.Kind, |
| 12478 | arg_type: Zir.Inst.Ref, |
| 13115 | 12479 | decls_len: u32, |
| 13116 | | layout: std.builtin.Type.ContainerLayout, |
| 13117 | | auto_enum_tag: bool, |
| 13118 | | any_aligned_fields: bool, |
| 12480 | fields_len: u32, |
| 12481 | any_field_aligns: bool, |
| 12482 | any_field_values: bool, |
| 13119 | 12483 | fields_hash: std.zig.SrcHash, |
| 13120 | | name_strat: Zir.Inst.NameStrategy, |
| 12484 | captures: []const Zir.Inst.Capture, |
| 12485 | capture_names: []const Zir.NullTerminatedString, |
| 12486 | /// The trailing declaration list, field information, and body instructions. |
| 12487 | remaining: []const u32, |
| 13121 | 12488 | }) !void { |
| 13122 | 12489 | const astgen = gz.astgen; |
| 13123 | 12490 | const gpa = astgen.gpa; |
| 13124 | 12491 | |
| 13125 | 12492 | assert(args.src_node != .root); |
| 13126 | 12493 | |
| 12494 | const captures_len: u32 = @intCast(args.captures.len); |
| 12495 | assert(args.capture_names.len == captures_len); |
| 12496 | |
| 13127 | 12497 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 13128 | 12498 | |
| 13129 | | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.UnionDecl).@"struct".fields.len + 5); |
| 12499 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.UnionDecl).@"struct".fields.len + |
| 12500 | 4 + // `captures_len`, `decls_len`, `fields_len`, `backing_int_type` |
| 12501 | captures_len * 2 + // `capture`, `capture_name` |
| 12502 | args.remaining.len); |
| 12503 | |
| 13130 | 12504 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.UnionDecl{ |
| 13131 | 12505 | .fields_hash_0 = fields_hash_arr[0], |
| 13132 | 12506 | .fields_hash_1 = fields_hash_arr[1], |
| ... | ... | @@ -13136,60 +12510,68 @@ const GenZir = struct { |
| 13136 | 12510 | .src_node = args.src_node, |
| 13137 | 12511 | }); |
| 13138 | 12512 | |
| 13139 | | if (args.tag_type != .none) { |
| 13140 | | astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); |
| 13141 | | } |
| 13142 | | if (args.captures_len != 0) { |
| 13143 | | astgen.extra.appendAssumeCapacity(args.captures_len); |
| 13144 | | } |
| 13145 | | if (args.body_len != 0) { |
| 13146 | | astgen.extra.appendAssumeCapacity(args.body_len); |
| 13147 | | } |
| 13148 | | if (args.fields_len != 0) { |
| 13149 | | astgen.extra.appendAssumeCapacity(args.fields_len); |
| 13150 | | } |
| 13151 | | if (args.decls_len != 0) { |
| 13152 | | astgen.extra.appendAssumeCapacity(args.decls_len); |
| 12513 | if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len); |
| 12514 | if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len); |
| 12515 | if (args.fields_len != 0) astgen.extra.appendAssumeCapacity(args.fields_len); |
| 12516 | if (args.kind.hasArgType()) { |
| 12517 | assert(args.arg_type != .none); |
| 12518 | astgen.extra.appendAssumeCapacity(@intFromEnum(args.arg_type)); |
| 12519 | } else { |
| 12520 | assert(args.arg_type == .none); |
| 13153 | 12521 | } |
| 12522 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures)); |
| 12523 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names)); |
| 12524 | astgen.extra.appendSliceAssumeCapacity(args.remaining); |
| 12525 | |
| 13154 | 12526 | astgen.instructions.set(@intFromEnum(inst), .{ |
| 13155 | 12527 | .tag = .extended, |
| 13156 | | .data = .{ .extended = .{ |
| 13157 | | .opcode = .union_decl, |
| 13158 | | .small = @bitCast(Zir.Inst.UnionDecl.Small{ |
| 13159 | | .has_tag_type = args.tag_type != .none, |
| 13160 | | .has_captures_len = args.captures_len != 0, |
| 13161 | | .has_body_len = args.body_len != 0, |
| 13162 | | .has_fields_len = args.fields_len != 0, |
| 13163 | | .has_decls_len = args.decls_len != 0, |
| 13164 | | .name_strategy = args.name_strat, |
| 13165 | | .layout = args.layout, |
| 13166 | | .auto_enum_tag = args.auto_enum_tag, |
| 13167 | | .any_aligned_fields = args.any_aligned_fields, |
| 13168 | | }), |
| 13169 | | .operand = payload_index, |
| 13170 | | } }, |
| 12528 | .data = .{ |
| 12529 | .extended = .{ |
| 12530 | .opcode = .union_decl, |
| 12531 | .small = @bitCast(Zir.Inst.UnionDecl.Small{ |
| 12532 | .has_captures_len = captures_len != 0, |
| 12533 | .has_decls_len = args.decls_len != 0, |
| 12534 | .has_fields_len = args.fields_len != 0, |
| 12535 | .name_strategy = args.name_strat, |
| 12536 | .kind = args.kind, |
| 12537 | .any_field_aligns = args.any_field_aligns, |
| 12538 | .any_field_values = args.any_field_values, |
| 12539 | }), |
| 12540 | .operand = payload_index, |
| 12541 | }, |
| 12542 | }, |
| 13171 | 12543 | }); |
| 13172 | 12544 | } |
| 13173 | 12545 | |
| 13174 | 12546 | fn setEnum(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 13175 | 12547 | src_node: Ast.Node.Index, |
| 12548 | name_strat: Zir.Inst.NameStrategy, |
| 13176 | 12549 | tag_type: Zir.Inst.Ref, |
| 13177 | | captures_len: u32, |
| 13178 | | body_len: u32, |
| 13179 | | fields_len: u32, |
| 13180 | | decls_len: u32, |
| 13181 | 12550 | nonexhaustive: bool, |
| 12551 | decls_len: u32, |
| 12552 | fields_len: u32, |
| 12553 | any_field_values: bool, |
| 13182 | 12554 | fields_hash: std.zig.SrcHash, |
| 13183 | | name_strat: Zir.Inst.NameStrategy, |
| 12555 | captures: []const Zir.Inst.Capture, |
| 12556 | capture_names: []const Zir.NullTerminatedString, |
| 12557 | /// The trailing declaration list, field information, and body instructions. |
| 12558 | remaining: []const u32, |
| 13184 | 12559 | }) !void { |
| 13185 | 12560 | const astgen = gz.astgen; |
| 13186 | 12561 | const gpa = astgen.gpa; |
| 13187 | 12562 | |
| 13188 | 12563 | assert(args.src_node != .root); |
| 13189 | 12564 | |
| 12565 | const captures_len: u32 = @intCast(args.captures.len); |
| 12566 | assert(args.capture_names.len == captures_len); |
| 12567 | |
| 13190 | 12568 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 13191 | 12569 | |
| 13192 | | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).@"struct".fields.len + 5); |
| 12570 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).@"struct".fields.len + |
| 12571 | 4 + // `captures_len`, `decls_len`, `fields_len`, `tag_type` |
| 12572 | captures_len * 2 + // `capture`, `capture_name` |
| 12573 | args.remaining.len); |
| 12574 | |
| 13193 | 12575 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{ |
| 13194 | 12576 | .fields_hash_0 = fields_hash_arr[0], |
| 13195 | 12577 | .fields_hash_1 = fields_hash_arr[1], |
| ... | ... | @@ -13199,33 +12581,26 @@ const GenZir = struct { |
| 13199 | 12581 | .src_node = args.src_node, |
| 13200 | 12582 | }); |
| 13201 | 12583 | |
| 13202 | | if (args.tag_type != .none) { |
| 13203 | | astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); |
| 13204 | | } |
| 13205 | | if (args.captures_len != 0) { |
| 13206 | | astgen.extra.appendAssumeCapacity(args.captures_len); |
| 13207 | | } |
| 13208 | | if (args.body_len != 0) { |
| 13209 | | astgen.extra.appendAssumeCapacity(args.body_len); |
| 13210 | | } |
| 13211 | | if (args.fields_len != 0) { |
| 13212 | | astgen.extra.appendAssumeCapacity(args.fields_len); |
| 13213 | | } |
| 13214 | | if (args.decls_len != 0) { |
| 13215 | | astgen.extra.appendAssumeCapacity(args.decls_len); |
| 13216 | | } |
| 12584 | if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len); |
| 12585 | if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len); |
| 12586 | if (args.fields_len != 0) astgen.extra.appendAssumeCapacity(args.fields_len); |
| 12587 | if (args.tag_type != .none) astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); |
| 12588 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures)); |
| 12589 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names)); |
| 12590 | astgen.extra.appendSliceAssumeCapacity(args.remaining); |
| 12591 | |
| 13217 | 12592 | astgen.instructions.set(@intFromEnum(inst), .{ |
| 13218 | 12593 | .tag = .extended, |
| 13219 | 12594 | .data = .{ .extended = .{ |
| 13220 | 12595 | .opcode = .enum_decl, |
| 13221 | 12596 | .small = @bitCast(Zir.Inst.EnumDecl.Small{ |
| 13222 | | .has_tag_type = args.tag_type != .none, |
| 13223 | | .has_captures_len = args.captures_len != 0, |
| 13224 | | .has_body_len = args.body_len != 0, |
| 13225 | | .has_fields_len = args.fields_len != 0, |
| 12597 | .has_captures_len = captures_len != 0, |
| 13226 | 12598 | .has_decls_len = args.decls_len != 0, |
| 12599 | .has_fields_len = args.fields_len != 0, |
| 13227 | 12600 | .name_strategy = args.name_strat, |
| 12601 | .has_tag_type = args.tag_type != .none, |
| 13228 | 12602 | .nonexhaustive = args.nonexhaustive, |
| 12603 | .any_field_values = args.any_field_values, |
| 13229 | 12604 | }), |
| 13230 | 12605 | .operand = payload_index, |
| 13231 | 12606 | } }, |
| ... | ... | @@ -13234,33 +12609,41 @@ const GenZir = struct { |
| 13234 | 12609 | |
| 13235 | 12610 | fn setOpaque(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 13236 | 12611 | src_node: Ast.Node.Index, |
| 13237 | | captures_len: u32, |
| 13238 | | decls_len: u32, |
| 13239 | 12612 | name_strat: Zir.Inst.NameStrategy, |
| 12613 | decls_len: u32, |
| 12614 | captures: []const Zir.Inst.Capture, |
| 12615 | capture_names: []const Zir.NullTerminatedString, |
| 12616 | decls: []const Zir.Inst.Index, |
| 13240 | 12617 | }) !void { |
| 13241 | 12618 | const astgen = gz.astgen; |
| 13242 | 12619 | const gpa = astgen.gpa; |
| 13243 | 12620 | |
| 13244 | 12621 | assert(args.src_node != .root); |
| 13245 | 12622 | |
| 13246 | | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).@"struct".fields.len + 2); |
| 12623 | const captures_len: u32 = @intCast(args.captures.len); |
| 12624 | assert(args.capture_names.len == captures_len); |
| 12625 | |
| 12626 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).@"struct".fields.len + |
| 12627 | 2 + // `captures_len`, `decls_len` |
| 12628 | captures_len * 2 + // `capture`, `capture_name` |
| 12629 | args.decls.len); |
| 12630 | |
| 13247 | 12631 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{ |
| 13248 | 12632 | .src_line = astgen.source_line, |
| 13249 | 12633 | .src_node = args.src_node, |
| 13250 | 12634 | }); |
| 12635 | if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len); |
| 12636 | if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len); |
| 12637 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures)); |
| 12638 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names)); |
| 12639 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.decls)); |
| 13251 | 12640 | |
| 13252 | | if (args.captures_len != 0) { |
| 13253 | | astgen.extra.appendAssumeCapacity(args.captures_len); |
| 13254 | | } |
| 13255 | | if (args.decls_len != 0) { |
| 13256 | | astgen.extra.appendAssumeCapacity(args.decls_len); |
| 13257 | | } |
| 13258 | 12641 | astgen.instructions.set(@intFromEnum(inst), .{ |
| 13259 | 12642 | .tag = .extended, |
| 13260 | 12643 | .data = .{ .extended = .{ |
| 13261 | 12644 | .opcode = .opaque_decl, |
| 13262 | 12645 | .small = @bitCast(Zir.Inst.OpaqueDecl.Small{ |
| 13263 | | .has_captures_len = args.captures_len != 0, |
| 12646 | .has_captures_len = captures_len != 0, |
| 13264 | 12647 | .has_decls_len = args.decls_len != 0, |
| 13265 | 12648 | .name_strategy = args.name_strat, |
| 13266 | 12649 | }), |
| ... | ... | @@ -13484,14 +12867,24 @@ fn restoreSourceCursor(astgen: *AstGen, cursor: SourceCursor) void { |
| 13484 | 12867 | astgen.source_column = cursor.column; |
| 13485 | 12868 | } |
| 13486 | 12869 | |
| 12870 | const ScanContainerResult = struct { |
| 12871 | /// Includes unnamed declarations (e.g. `comptime` decls) |
| 12872 | decls_len: u32, |
| 12873 | fields_len: u32, |
| 12874 | any_field_aligns: bool, |
| 12875 | any_field_values: bool, |
| 12876 | any_comptime_fields: bool, |
| 12877 | /// Whether there is a field named `_` (indicating a non-exhaustive enum) |
| 12878 | has_underscore_field: bool, |
| 12879 | }; |
| 12880 | |
| 13487 | 12881 | /// Detects name conflicts for decls and fields, and populates `namespace.decls` with all named declarations. |
| 13488 | | /// Returns the number of declarations in the namespace, including unnamed declarations (e.g. `comptime` decls). |
| 13489 | 12882 | fn scanContainer( |
| 13490 | 12883 | astgen: *AstGen, |
| 13491 | 12884 | namespace: *Scope.Namespace, |
| 13492 | 12885 | members: []const Ast.Node.Index, |
| 13493 | 12886 | container_kind: enum { @"struct", @"union", @"enum", @"opaque" }, |
| 13494 | | ) !u32 { |
| 12887 | ) !ScanContainerResult { |
| 13495 | 12888 | const gpa = astgen.gpa; |
| 13496 | 12889 | const tree = astgen.tree; |
| 13497 | 12890 | |
| ... | ... | @@ -13521,6 +12914,10 @@ fn scanContainer( |
| 13521 | 12914 | |
| 13522 | 12915 | var any_duplicates = false; |
| 13523 | 12916 | var decl_count: u32 = 0; |
| 12917 | var any_field_aligns = false; |
| 12918 | var any_field_values = false; |
| 12919 | var any_comptime_fields = false; |
| 12920 | var has_underscore_field = false; |
| 13524 | 12921 | for (members) |member_node| { |
| 13525 | 12922 | const Kind = enum { decl, field }; |
| 13526 | 12923 | const kind: Kind, const name_token = switch (tree.nodeTag(member_node)) { |
| ... | ... | @@ -13533,6 +12930,10 @@ fn scanContainer( |
| 13533 | 12930 | .@"struct", .@"opaque" => {}, |
| 13534 | 12931 | .@"union", .@"enum" => full.convertToNonTupleLike(astgen.tree), |
| 13535 | 12932 | } |
| 12933 | if (full.ast.align_expr != .none) any_field_aligns = true; |
| 12934 | if (full.ast.value_expr != .none) any_field_values = true; |
| 12935 | if (full.comptime_token != null) any_comptime_fields = true; |
| 12936 | if (mem.eql(u8, tree.tokenSlice(full.ast.main_token), "_")) has_underscore_field = true; |
| 13536 | 12937 | if (full.ast.tuple_like) continue; |
| 13537 | 12938 | break :blk .{ .field, full.ast.main_token }; |
| 13538 | 12939 | }, |
| ... | ... | @@ -13698,7 +13099,14 @@ fn scanContainer( |
| 13698 | 13099 | |
| 13699 | 13100 | if (!any_duplicates) { |
| 13700 | 13101 | if (any_invalid_declarations) return error.AnalysisFail; |
| 13701 | | return decl_count; |
| 13102 | return .{ |
| 13103 | .decls_len = decl_count, |
| 13104 | .fields_len = @intCast(members.len - decl_count), |
| 13105 | .any_field_aligns = any_field_aligns, |
| 13106 | .any_field_values = any_field_values, |
| 13107 | .any_comptime_fields = any_comptime_fields, |
| 13108 | .has_underscore_field = has_underscore_field, |
| 13109 | }; |
| 13702 | 13110 | } |
| 13703 | 13111 | |
| 13704 | 13112 | for (names.keys(), names.values()) |name, first| { |
| ... | ... | @@ -13954,7 +13362,7 @@ const DeclarationName = union(enum) { |
| 13954 | 13362 | }; |
| 13955 | 13363 | |
| 13956 | 13364 | fn addFailedDeclaration( |
| 13957 | | wip_members: *WipMembers, |
| 13365 | wip_decls: *WipDecls, |
| 13958 | 13366 | gz: *GenZir, |
| 13959 | 13367 | kind: Zir.Inst.Declaration.Unwrapped.Kind, |
| 13960 | 13368 | name: Zir.NullTerminatedString, |
| ... | ... | @@ -13962,7 +13370,7 @@ fn addFailedDeclaration( |
| 13962 | 13370 | is_pub: bool, |
| 13963 | 13371 | ) !void { |
| 13964 | 13372 | const decl_inst = try gz.makeDeclaration(src_node); |
| 13965 | | wip_members.nextDecl(decl_inst); |
| 13373 | wip_decls.nextDecl(decl_inst); |
| 13966 | 13374 | |
| 13967 | 13375 | var dummy_gz = gz.makeSubBlock(&gz.base); |
| 13968 | 13376 | |