Merge pull request #20593 from jacobly0/more-races
InternPool: fix more races
This commit is contained in:
221
src/Sema.zig
221
src/Sema.zig
@@ -2530,13 +2530,13 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.Error
|
||||
}
|
||||
|
||||
if (sema.owner_func_index != .none) {
|
||||
ip.funcAnalysis(sema.owner_func_index).state = .sema_failure;
|
||||
ip.funcSetAnalysisState(sema.owner_func_index, .sema_failure);
|
||||
} else {
|
||||
sema.owner_decl.analysis = .sema_failure;
|
||||
}
|
||||
|
||||
if (sema.func_index != .none) {
|
||||
ip.funcAnalysis(sema.func_index).state = .sema_failure;
|
||||
ip.funcSetAnalysisState(sema.func_index, .sema_failure);
|
||||
}
|
||||
|
||||
return error.AnalysisFail;
|
||||
@@ -2848,7 +2848,7 @@ fn zirStructDecl(
|
||||
}
|
||||
|
||||
try pt.finalizeAnonDecl(new_decl_index);
|
||||
try mod.comp.work_queue.writeItem(.{ .resolve_type_fully = wip_ty.index });
|
||||
try mod.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
|
||||
try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index }));
|
||||
return Air.internedToRef(wip_ty.finish(ip, new_decl_index, new_namespace_index));
|
||||
}
|
||||
@@ -3353,7 +3353,7 @@ fn zirUnionDecl(
|
||||
}
|
||||
|
||||
try pt.finalizeAnonDecl(new_decl_index);
|
||||
try mod.comp.work_queue.writeItem(.{ .resolve_type_fully = wip_ty.index });
|
||||
try mod.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
|
||||
try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index }));
|
||||
return Air.internedToRef(wip_ty.finish(ip, new_decl_index, new_namespace_index));
|
||||
}
|
||||
@@ -6550,14 +6550,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
|
||||
}
|
||||
sema.prev_stack_alignment_src = src;
|
||||
|
||||
const ip = &mod.intern_pool;
|
||||
const a = ip.funcAnalysis(sema.func_index);
|
||||
if (a.stack_alignment != .none) {
|
||||
a.stack_alignment = @enumFromInt(@max(
|
||||
@intFromEnum(alignment),
|
||||
@intFromEnum(a.stack_alignment),
|
||||
));
|
||||
}
|
||||
mod.intern_pool.funcMaxStackAlignment(sema.func_index, alignment);
|
||||
}
|
||||
|
||||
fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
|
||||
@@ -6570,7 +6563,7 @@ fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData)
|
||||
.needed_comptime_reason = "operand to @setCold must be comptime-known",
|
||||
});
|
||||
if (sema.func_index == .none) return; // does nothing outside a function
|
||||
ip.funcAnalysis(sema.func_index).is_cold = is_cold;
|
||||
ip.funcSetCold(sema.func_index, is_cold);
|
||||
}
|
||||
|
||||
fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
|
||||
@@ -7085,7 +7078,7 @@ fn zirCall(
|
||||
const call_inst = try sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, args_info, call_dbg_node, .call);
|
||||
|
||||
if (sema.owner_func_index == .none or
|
||||
!mod.intern_pool.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn)
|
||||
!mod.intern_pool.funcAnalysisUnordered(sema.owner_func_index).calls_or_awaits_errorable_fn)
|
||||
{
|
||||
// No errorable fn actually called; we have no error return trace
|
||||
input_is_error = false;
|
||||
@@ -7793,7 +7786,7 @@ fn analyzeCall(
|
||||
_ = ics.callee();
|
||||
|
||||
if (!inlining.has_comptime_args) {
|
||||
if (module_fn.analysis(ip).state == .sema_failure)
|
||||
if (module_fn.analysisUnordered(ip).state == .sema_failure)
|
||||
return error.AnalysisFail;
|
||||
|
||||
var block_it = block;
|
||||
@@ -7816,7 +7809,7 @@ fn analyzeCall(
|
||||
try sema.resolveInst(fn_info.ret_ty_ref);
|
||||
const ret_ty_src: LazySrcLoc = .{ .base_node_inst = module_fn.zir_body_inst, .offset = .{ .node_offset_fn_type_ret_ty = 0 } };
|
||||
sema.fn_ret_ty = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst);
|
||||
if (module_fn.analysis(ip).inferred_error_set) {
|
||||
if (module_fn.analysisUnordered(ip).inferred_error_set) {
|
||||
// Create a fresh inferred error set type for inline/comptime calls.
|
||||
const ies = try sema.arena.create(InferredErrorSet);
|
||||
ies.* = .{ .func = .none };
|
||||
@@ -7942,7 +7935,7 @@ fn analyzeCall(
|
||||
if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
|
||||
|
||||
if (sema.owner_func_index != .none and Type.fromInterned(func_ty_info.return_type).isError(mod)) {
|
||||
ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn = true;
|
||||
ip.funcSetCallsOrAwaitsErrorableFn(sema.owner_func_index);
|
||||
}
|
||||
|
||||
if (try sema.resolveValue(func)) |func_val| {
|
||||
@@ -8386,7 +8379,7 @@ fn instantiateGenericCall(
|
||||
const callee_index = (child_sema.resolveConstDefinedValue(&child_block, LazySrcLoc.unneeded, new_func_inst, undefined) catch unreachable).toIntern();
|
||||
|
||||
const callee = zcu.funcInfo(callee_index);
|
||||
callee.branchQuota(ip).* = @max(callee.branchQuota(ip).*, sema.branch_quota);
|
||||
callee.maxBranchQuota(ip, sema.branch_quota);
|
||||
|
||||
// Make a runtime call to the new function, making sure to omit the comptime args.
|
||||
const func_ty = Type.fromInterned(callee.ty);
|
||||
@@ -8408,7 +8401,7 @@ fn instantiateGenericCall(
|
||||
if (sema.owner_func_index != .none and
|
||||
Type.fromInterned(func_ty_info.return_type).isError(zcu))
|
||||
{
|
||||
ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn = true;
|
||||
ip.funcSetCallsOrAwaitsErrorableFn(sema.owner_func_index);
|
||||
}
|
||||
|
||||
try sema.addReferenceEntry(call_src, AnalUnit.wrap(.{ .func = callee_index }));
|
||||
@@ -8769,9 +8762,9 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
|
||||
const int = try sema.usizeCast(block, operand_src, try value.toUnsignedIntSema(pt));
|
||||
if (int > len: {
|
||||
const mutate = &ip.global_error_set.mutate;
|
||||
mutate.mutex.lock();
|
||||
defer mutate.mutex.unlock();
|
||||
break :len mutate.list.len;
|
||||
mutate.map.mutex.lock();
|
||||
defer mutate.map.mutex.unlock();
|
||||
break :len mutate.names.len;
|
||||
} or int == 0)
|
||||
return sema.fail(block, operand_src, "integer value '{d}' represents no error", .{int});
|
||||
return Air.internedToRef((try pt.intern(.{ .err = .{
|
||||
@@ -18395,7 +18388,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
try ty.resolveLayout(pt); // Getting alignment requires type layout
|
||||
const union_obj = mod.typeToUnion(ty).?;
|
||||
const tag_type = union_obj.loadTagType(ip);
|
||||
const layout = union_obj.getLayout(ip);
|
||||
const layout = union_obj.flagsUnordered(ip).layout;
|
||||
|
||||
const union_field_vals = try gpa.alloc(InternPool.Index, tag_type.names.len);
|
||||
defer gpa.free(union_field_vals);
|
||||
@@ -18713,8 +18706,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
const backing_integer_val = try pt.intern(.{ .opt = .{
|
||||
.ty = (try pt.optionalType(.type_type)).toIntern(),
|
||||
.val = if (mod.typeToPackedStruct(ty)) |packed_struct| val: {
|
||||
assert(Type.fromInterned(packed_struct.backingIntType(ip).*).isInt(mod));
|
||||
break :val packed_struct.backingIntType(ip).*;
|
||||
assert(Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)).isInt(mod));
|
||||
break :val packed_struct.backingIntTypeUnordered(ip);
|
||||
} else .none,
|
||||
} });
|
||||
|
||||
@@ -19795,7 +19788,7 @@ fn restoreErrRetIndex(sema: *Sema, start_block: *Block, src: LazySrcLoc, target_
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mod.intern_pool.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn) return;
|
||||
if (!mod.intern_pool.funcAnalysisUnordered(sema.owner_func_index).calls_or_awaits_errorable_fn) return;
|
||||
if (!start_block.ownerModule().error_tracing) return;
|
||||
|
||||
assert(saved_index != .none); // The .error_return_trace_index field was dropped somewhere
|
||||
@@ -21053,7 +21046,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
|
||||
const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern());
|
||||
|
||||
if (sema.owner_func_index != .none and
|
||||
ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn and
|
||||
ip.funcAnalysisUnordered(sema.owner_func_index).calls_or_awaits_errorable_fn and
|
||||
block.ownerModule().error_tracing)
|
||||
{
|
||||
return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);
|
||||
@@ -22201,11 +22194,11 @@ fn reifyUnion(
|
||||
if (any_aligns) {
|
||||
loaded_union.setFieldAligns(ip, field_aligns);
|
||||
}
|
||||
loaded_union.tagTypePtr(ip).* = enum_tag_ty;
|
||||
loaded_union.flagsPtr(ip).status = .have_field_types;
|
||||
loaded_union.setTagType(ip, enum_tag_ty);
|
||||
loaded_union.setStatus(ip, .have_field_types);
|
||||
|
||||
try pt.finalizeAnonDecl(new_decl_index);
|
||||
try mod.comp.work_queue.writeItem(.{ .resolve_type_fully = wip_ty.index });
|
||||
try mod.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
|
||||
try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index }));
|
||||
return Air.internedToRef(wip_ty.finish(ip, new_decl_index, .none));
|
||||
}
|
||||
@@ -22464,15 +22457,15 @@ fn reifyStruct(
|
||||
if (opt_backing_int_val.optionalValue(mod)) |backing_int_val| {
|
||||
const backing_int_ty = backing_int_val.toType();
|
||||
try sema.checkBackingIntType(block, src, backing_int_ty, fields_bit_sum);
|
||||
struct_type.backingIntType(ip).* = backing_int_ty.toIntern();
|
||||
struct_type.setBackingIntType(ip, backing_int_ty.toIntern());
|
||||
} else {
|
||||
const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum));
|
||||
struct_type.backingIntType(ip).* = backing_int_ty.toIntern();
|
||||
struct_type.setBackingIntType(ip, backing_int_ty.toIntern());
|
||||
}
|
||||
}
|
||||
|
||||
try pt.finalizeAnonDecl(new_decl_index);
|
||||
try mod.comp.work_queue.writeItem(.{ .resolve_type_fully = wip_ty.index });
|
||||
try mod.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
|
||||
try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index }));
|
||||
return Air.internedToRef(wip_ty.finish(ip, new_decl_index, .none));
|
||||
}
|
||||
@@ -28347,7 +28340,7 @@ fn unionFieldPtr(
|
||||
.is_const = union_ptr_info.flags.is_const,
|
||||
.is_volatile = union_ptr_info.flags.is_volatile,
|
||||
.address_space = union_ptr_info.flags.address_space,
|
||||
.alignment = if (union_obj.getLayout(ip) == .auto) blk: {
|
||||
.alignment = if (union_obj.flagsUnordered(ip).layout == .auto) blk: {
|
||||
const union_align = if (union_ptr_info.flags.alignment != .none)
|
||||
union_ptr_info.flags.alignment
|
||||
else
|
||||
@@ -28375,7 +28368,7 @@ fn unionFieldPtr(
|
||||
}
|
||||
|
||||
if (try sema.resolveDefinedValue(block, src, union_ptr)) |union_ptr_val| ct: {
|
||||
switch (union_obj.getLayout(ip)) {
|
||||
switch (union_obj.flagsUnordered(ip).layout) {
|
||||
.auto => if (initializing) {
|
||||
// Store to the union to initialize the tag.
|
||||
const field_tag = try pt.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index);
|
||||
@@ -28413,7 +28406,7 @@ fn unionFieldPtr(
|
||||
}
|
||||
|
||||
try sema.requireRuntimeBlock(block, src, null);
|
||||
if (!initializing and union_obj.getLayout(ip) == .auto and block.wantSafety() and
|
||||
if (!initializing and union_obj.flagsUnordered(ip).layout == .auto and block.wantSafety() and
|
||||
union_ty.unionTagTypeSafety(mod) != null and union_obj.field_types.len > 1)
|
||||
{
|
||||
const wanted_tag_val = try pt.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index);
|
||||
@@ -28456,7 +28449,7 @@ fn unionFieldVal(
|
||||
const un = ip.indexToKey(union_val.toIntern()).un;
|
||||
const field_tag = try pt.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index);
|
||||
const tag_matches = un.tag == field_tag.toIntern();
|
||||
switch (union_obj.getLayout(ip)) {
|
||||
switch (union_obj.flagsUnordered(ip).layout) {
|
||||
.auto => {
|
||||
if (tag_matches) {
|
||||
return Air.internedToRef(un.val);
|
||||
@@ -28490,7 +28483,7 @@ fn unionFieldVal(
|
||||
}
|
||||
|
||||
try sema.requireRuntimeBlock(block, src, null);
|
||||
if (union_obj.getLayout(ip) == .auto and block.wantSafety() and
|
||||
if (union_obj.flagsUnordered(ip).layout == .auto and block.wantSafety() and
|
||||
union_ty.unionTagTypeSafety(zcu) != null and union_obj.field_types.len > 1)
|
||||
{
|
||||
const wanted_tag_val = try pt.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index);
|
||||
@@ -32037,7 +32030,7 @@ pub fn ensureDeclAnalyzed(sema: *Sema, decl_index: InternPool.DeclIndex) Compile
|
||||
|
||||
pt.ensureDeclAnalyzed(decl_index) catch |err| {
|
||||
if (sema.owner_func_index != .none) {
|
||||
ip.funcAnalysis(sema.owner_func_index).state = .dependency_failure;
|
||||
ip.funcSetAnalysisState(sema.owner_func_index, .dependency_failure);
|
||||
} else {
|
||||
sema.owner_decl.analysis = .dependency_failure;
|
||||
}
|
||||
@@ -32051,7 +32044,7 @@ fn ensureFuncBodyAnalyzed(sema: *Sema, func: InternPool.Index) CompileError!void
|
||||
const ip = &mod.intern_pool;
|
||||
pt.ensureFuncBodyAnalyzed(func) catch |err| {
|
||||
if (sema.owner_func_index != .none) {
|
||||
ip.funcAnalysis(sema.owner_func_index).state = .dependency_failure;
|
||||
ip.funcSetAnalysisState(sema.owner_func_index, .dependency_failure);
|
||||
} else {
|
||||
sema.owner_decl.analysis = .dependency_failure;
|
||||
}
|
||||
@@ -32397,7 +32390,7 @@ fn analyzeIsNonErrComptimeOnly(
|
||||
// If the error set is empty, we must return a comptime true or false.
|
||||
// However we want to avoid unnecessarily resolving an inferred error set
|
||||
// in case it is already non-empty.
|
||||
switch (ip.funcIesResolved(func_index).*) {
|
||||
switch (ip.funcIesResolvedUnordered(func_index)) {
|
||||
.anyerror_type => break :blk,
|
||||
.none => {},
|
||||
else => |i| if (ip.indexToKey(i).error_set_type.names.len != 0) break :blk,
|
||||
@@ -33466,7 +33459,7 @@ fn wrapErrorUnionSet(
|
||||
.inferred_error_set_type => |func_index| ok: {
|
||||
// We carefully do this in an order that avoids unnecessarily
|
||||
// resolving the destination error set type.
|
||||
switch (ip.funcIesResolved(func_index).*) {
|
||||
switch (ip.funcIesResolvedUnordered(func_index)) {
|
||||
.anyerror_type => break :ok,
|
||||
.none => if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) {
|
||||
break :ok;
|
||||
@@ -35071,33 +35064,25 @@ pub fn resolveStructAlignment(
|
||||
|
||||
assert(sema.ownerUnit().unwrap().decl == struct_type.decl.unwrap().?);
|
||||
|
||||
assert(struct_type.flagsPtr(ip).alignment == .none);
|
||||
assert(struct_type.layout != .@"packed");
|
||||
assert(struct_type.flagsUnordered(ip).alignment == .none);
|
||||
|
||||
if (struct_type.flagsPtr(ip).field_types_wip) {
|
||||
// We'll guess "pointer-aligned", if the struct has an
|
||||
// underaligned pointer field then some allocations
|
||||
// might require explicit alignment.
|
||||
struct_type.flagsPtr(ip).assumed_pointer_aligned = true;
|
||||
const result = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8));
|
||||
struct_type.flagsPtr(ip).alignment = result;
|
||||
return;
|
||||
}
|
||||
const ptr_align = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8));
|
||||
|
||||
// We'll guess "pointer-aligned", if the struct has an
|
||||
// underaligned pointer field then some allocations
|
||||
// might require explicit alignment.
|
||||
if (struct_type.assumePointerAlignedIfFieldTypesWip(ip, ptr_align)) return;
|
||||
|
||||
try sema.resolveTypeFieldsStruct(ty, struct_type);
|
||||
|
||||
if (struct_type.setAlignmentWip(ip)) {
|
||||
// We'll guess "pointer-aligned", if the struct has an
|
||||
// underaligned pointer field then some allocations
|
||||
// might require explicit alignment.
|
||||
struct_type.flagsPtr(ip).assumed_pointer_aligned = true;
|
||||
const result = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8));
|
||||
struct_type.flagsPtr(ip).alignment = result;
|
||||
return;
|
||||
}
|
||||
// We'll guess "pointer-aligned", if the struct has an
|
||||
// underaligned pointer field then some allocations
|
||||
// might require explicit alignment.
|
||||
if (struct_type.assumePointerAlignedIfWip(ip, ptr_align)) return;
|
||||
defer struct_type.clearAlignmentWip(ip);
|
||||
|
||||
var result: Alignment = .@"1";
|
||||
var alignment: Alignment = .@"1";
|
||||
|
||||
for (0..struct_type.field_types.len) |i| {
|
||||
const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);
|
||||
@@ -35109,10 +35094,10 @@ pub fn resolveStructAlignment(
|
||||
struct_type.layout,
|
||||
.sema,
|
||||
);
|
||||
result = result.maxStrict(field_align);
|
||||
alignment = alignment.maxStrict(field_align);
|
||||
}
|
||||
|
||||
struct_type.flagsPtr(ip).alignment = result;
|
||||
struct_type.setAlignment(ip, alignment);
|
||||
}
|
||||
|
||||
pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
|
||||
@@ -35177,7 +35162,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
|
||||
big_align = big_align.maxStrict(field_align.*);
|
||||
}
|
||||
|
||||
if (struct_type.flagsPtr(ip).assumed_runtime_bits and !(try sema.typeHasRuntimeBits(ty))) {
|
||||
if (struct_type.flagsUnordered(ip).assumed_runtime_bits and !(try sema.typeHasRuntimeBits(ty))) {
|
||||
const msg = try sema.errMsg(
|
||||
ty.srcLoc(zcu),
|
||||
"struct layout depends on it having runtime bits",
|
||||
@@ -35186,7 +35171,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
|
||||
return sema.failWithOwnedErrorMsg(null, msg);
|
||||
}
|
||||
|
||||
if (struct_type.flagsPtr(ip).assumed_pointer_aligned and
|
||||
if (struct_type.flagsUnordered(ip).assumed_pointer_aligned and
|
||||
big_align.compareStrict(.neq, Alignment.fromByteUnits(@divExact(zcu.getTarget().ptrBitWidth(), 8))))
|
||||
{
|
||||
const msg = try sema.errMsg(
|
||||
@@ -35254,10 +35239,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
|
||||
offsets[i] = @intCast(aligns[i].forward(offset));
|
||||
offset = offsets[i] + sizes[i];
|
||||
}
|
||||
struct_type.size(ip).* = @intCast(big_align.forward(offset));
|
||||
const flags = struct_type.flagsPtr(ip);
|
||||
flags.alignment = big_align;
|
||||
flags.layout_resolved = true;
|
||||
struct_type.setLayoutResolved(ip, @intCast(big_align.forward(offset)), big_align);
|
||||
_ = try sema.typeRequiresComptime(ty);
|
||||
}
|
||||
|
||||
@@ -35350,13 +35332,13 @@ fn semaBackingIntType(pt: Zcu.PerThread, struct_type: InternPool.LoadedStructTyp
|
||||
};
|
||||
|
||||
try sema.checkBackingIntType(&block, backing_int_src, backing_int_ty, fields_bit_sum);
|
||||
struct_type.backingIntType(ip).* = backing_int_ty.toIntern();
|
||||
struct_type.setBackingIntType(ip, backing_int_ty.toIntern());
|
||||
} else {
|
||||
if (fields_bit_sum > std.math.maxInt(u16)) {
|
||||
return sema.fail(&block, block.nodeOffset(0), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum});
|
||||
}
|
||||
const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum));
|
||||
struct_type.backingIntType(ip).* = backing_int_ty.toIntern();
|
||||
struct_type.setBackingIntType(ip, backing_int_ty.toIntern());
|
||||
}
|
||||
|
||||
try sema.flushExports();
|
||||
@@ -35430,15 +35412,12 @@ pub fn resolveUnionAlignment(
|
||||
|
||||
assert(!union_type.haveLayout(ip));
|
||||
|
||||
if (union_type.flagsPtr(ip).status == .field_types_wip) {
|
||||
// We'll guess "pointer-aligned", if the union has an
|
||||
// underaligned pointer field then some allocations
|
||||
// might require explicit alignment.
|
||||
union_type.flagsPtr(ip).assumed_pointer_aligned = true;
|
||||
const result = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8));
|
||||
union_type.flagsPtr(ip).alignment = result;
|
||||
return;
|
||||
}
|
||||
const ptr_align = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8));
|
||||
|
||||
// We'll guess "pointer-aligned", if the union has an
|
||||
// underaligned pointer field then some allocations
|
||||
// might require explicit alignment.
|
||||
if (union_type.assumePointerAlignedIfFieldTypesWip(ip, ptr_align)) return;
|
||||
|
||||
try sema.resolveTypeFieldsUnion(ty, union_type);
|
||||
|
||||
@@ -35456,7 +35435,7 @@ pub fn resolveUnionAlignment(
|
||||
max_align = max_align.max(field_align);
|
||||
}
|
||||
|
||||
union_type.flagsPtr(ip).alignment = max_align;
|
||||
union_type.setAlignment(ip, max_align);
|
||||
}
|
||||
|
||||
/// This logic must be kept in sync with `Module.getUnionLayout`.
|
||||
@@ -35471,7 +35450,8 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
|
||||
|
||||
assert(sema.ownerUnit().unwrap().decl == union_type.decl);
|
||||
|
||||
switch (union_type.flagsPtr(ip).status) {
|
||||
const old_flags = union_type.flagsUnordered(ip);
|
||||
switch (old_flags.status) {
|
||||
.none, .have_field_types => {},
|
||||
.field_types_wip, .layout_wip => {
|
||||
const msg = try sema.errMsg(
|
||||
@@ -35484,12 +35464,9 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
|
||||
.have_layout, .fully_resolved_wip, .fully_resolved => return,
|
||||
}
|
||||
|
||||
const prev_status = union_type.flagsPtr(ip).status;
|
||||
errdefer if (union_type.flagsPtr(ip).status == .layout_wip) {
|
||||
union_type.flagsPtr(ip).status = prev_status;
|
||||
};
|
||||
errdefer union_type.setStatusIfLayoutWip(ip, old_flags.status);
|
||||
|
||||
union_type.flagsPtr(ip).status = .layout_wip;
|
||||
union_type.setStatus(ip, .layout_wip);
|
||||
|
||||
var max_size: u64 = 0;
|
||||
var max_align: Alignment = .@"1";
|
||||
@@ -35516,8 +35493,8 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
|
||||
max_align = max_align.max(field_align);
|
||||
}
|
||||
|
||||
const flags = union_type.flagsPtr(ip);
|
||||
const has_runtime_tag = flags.runtime_tag.hasTag() and try sema.typeHasRuntimeBits(Type.fromInterned(union_type.enum_tag_ty));
|
||||
const has_runtime_tag = union_type.flagsUnordered(ip).runtime_tag.hasTag() and
|
||||
try sema.typeHasRuntimeBits(Type.fromInterned(union_type.enum_tag_ty));
|
||||
const size, const alignment, const padding = if (has_runtime_tag) layout: {
|
||||
const enum_tag_type = Type.fromInterned(union_type.enum_tag_ty);
|
||||
const tag_align = try sema.typeAbiAlignment(enum_tag_type);
|
||||
@@ -35551,12 +35528,9 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
|
||||
break :layout .{ size, max_align.max(tag_align), padding };
|
||||
} else .{ max_align.forward(max_size), max_align, 0 };
|
||||
|
||||
union_type.size(ip).* = @intCast(size);
|
||||
union_type.padding(ip).* = padding;
|
||||
flags.alignment = alignment;
|
||||
flags.status = .have_layout;
|
||||
union_type.setHaveLayout(ip, @intCast(size), padding, alignment);
|
||||
|
||||
if (union_type.flagsPtr(ip).assumed_runtime_bits and !(try sema.typeHasRuntimeBits(ty))) {
|
||||
if (union_type.flagsUnordered(ip).assumed_runtime_bits and !(try sema.typeHasRuntimeBits(ty))) {
|
||||
const msg = try sema.errMsg(
|
||||
ty.srcLoc(pt.zcu),
|
||||
"union layout depends on it having runtime bits",
|
||||
@@ -35565,7 +35539,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
|
||||
return sema.failWithOwnedErrorMsg(null, msg);
|
||||
}
|
||||
|
||||
if (union_type.flagsPtr(ip).assumed_pointer_aligned and
|
||||
if (union_type.flagsUnordered(ip).assumed_pointer_aligned and
|
||||
alignment.compareStrict(.neq, Alignment.fromByteUnits(@divExact(pt.zcu.getTarget().ptrBitWidth(), 8))))
|
||||
{
|
||||
const msg = try sema.errMsg(
|
||||
@@ -35612,7 +35586,7 @@ pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void {
|
||||
|
||||
assert(sema.ownerUnit().unwrap().decl == union_obj.decl);
|
||||
|
||||
switch (union_obj.flagsPtr(ip).status) {
|
||||
switch (union_obj.flagsUnordered(ip).status) {
|
||||
.none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
|
||||
.fully_resolved_wip, .fully_resolved => return,
|
||||
}
|
||||
@@ -35621,15 +35595,15 @@ pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void {
|
||||
// After we have resolve union layout we have to go over the fields again to
|
||||
// make sure pointer fields get their child types resolved as well.
|
||||
// See also similar code for structs.
|
||||
const prev_status = union_obj.flagsPtr(ip).status;
|
||||
errdefer union_obj.flagsPtr(ip).status = prev_status;
|
||||
const prev_status = union_obj.flagsUnordered(ip).status;
|
||||
errdefer union_obj.setStatus(ip, prev_status);
|
||||
|
||||
union_obj.flagsPtr(ip).status = .fully_resolved_wip;
|
||||
union_obj.setStatus(ip, .fully_resolved_wip);
|
||||
for (0..union_obj.field_types.len) |field_index| {
|
||||
const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
|
||||
try field_ty.resolveFully(pt);
|
||||
}
|
||||
union_obj.flagsPtr(ip).status = .fully_resolved;
|
||||
union_obj.setStatus(ip, .fully_resolved);
|
||||
}
|
||||
|
||||
// And let's not forget comptime-only status.
|
||||
@@ -35662,7 +35636,7 @@ pub fn resolveTypeFieldsStruct(
|
||||
|
||||
if (struct_type.haveFieldTypes(ip)) return;
|
||||
|
||||
if (struct_type.setTypesWip(ip)) {
|
||||
if (struct_type.setFieldTypesWip(ip)) {
|
||||
const msg = try sema.errMsg(
|
||||
Type.fromInterned(ty).srcLoc(zcu),
|
||||
"struct '{}' depends on itself",
|
||||
@@ -35670,7 +35644,7 @@ pub fn resolveTypeFieldsStruct(
|
||||
);
|
||||
return sema.failWithOwnedErrorMsg(null, msg);
|
||||
}
|
||||
defer struct_type.clearTypesWip(ip);
|
||||
defer struct_type.clearFieldTypesWip(ip);
|
||||
|
||||
semaStructFields(pt, sema.arena, struct_type) catch |err| switch (err) {
|
||||
error.AnalysisFail => {
|
||||
@@ -35739,7 +35713,7 @@ pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.Load
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
switch (union_type.flagsPtr(ip).status) {
|
||||
switch (union_type.flagsUnordered(ip).status) {
|
||||
.none => {},
|
||||
.field_types_wip => {
|
||||
const msg = try sema.errMsg(
|
||||
@@ -35757,8 +35731,8 @@ pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.Load
|
||||
=> return,
|
||||
}
|
||||
|
||||
union_type.flagsPtr(ip).status = .field_types_wip;
|
||||
errdefer union_type.flagsPtr(ip).status = .none;
|
||||
union_type.setStatus(ip, .field_types_wip);
|
||||
errdefer union_type.setStatus(ip, .none);
|
||||
semaUnionFields(pt, sema.arena, union_type) catch |err| switch (err) {
|
||||
error.AnalysisFail => {
|
||||
if (owner_decl.analysis == .complete) {
|
||||
@@ -35769,7 +35743,7 @@ pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.Load
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.ComptimeBreak, error.ComptimeReturn, error.GenericPoison => unreachable,
|
||||
};
|
||||
union_type.flagsPtr(ip).status = .have_field_types;
|
||||
union_type.setStatus(ip, .have_field_types);
|
||||
}
|
||||
|
||||
/// Returns a normal error set corresponding to the fully populated inferred
|
||||
@@ -35790,10 +35764,10 @@ fn resolveInferredErrorSet(
|
||||
|
||||
// TODO: during an incremental update this might not be `.none`, but the
|
||||
// function might be out-of-date!
|
||||
const resolved_ty = func.resolvedErrorSet(ip).*;
|
||||
const resolved_ty = func.resolvedErrorSetUnordered(ip);
|
||||
if (resolved_ty != .none) return resolved_ty;
|
||||
|
||||
if (func.analysis(ip).state == .in_progress)
|
||||
if (func.analysisUnordered(ip).state == .in_progress)
|
||||
return sema.fail(block, src, "unable to resolve inferred error set", .{});
|
||||
|
||||
// In order to ensure that all dependencies are properly added to the set,
|
||||
@@ -35830,7 +35804,7 @@ fn resolveInferredErrorSet(
|
||||
|
||||
// This will now have been resolved by the logic at the end of `Module.analyzeFnBody`
|
||||
// which calls `resolveInferredErrorSetPtr`.
|
||||
const final_resolved_ty = func.resolvedErrorSet(ip).*;
|
||||
const final_resolved_ty = func.resolvedErrorSetUnordered(ip);
|
||||
assert(final_resolved_ty != .none);
|
||||
return final_resolved_ty;
|
||||
}
|
||||
@@ -35996,8 +35970,7 @@ fn semaStructFields(
|
||||
return;
|
||||
},
|
||||
.auto, .@"extern" => {
|
||||
struct_type.size(ip).* = 0;
|
||||
struct_type.flagsPtr(ip).layout_resolved = true;
|
||||
struct_type.setLayoutResolved(ip, 0, .none);
|
||||
return;
|
||||
},
|
||||
};
|
||||
@@ -36191,7 +36164,7 @@ fn semaStructFields(
|
||||
extra_index += zir_field.init_body_len;
|
||||
}
|
||||
|
||||
struct_type.clearTypesWip(ip);
|
||||
struct_type.clearFieldTypesWip(ip);
|
||||
if (!any_inits) struct_type.setHaveFieldInits(ip);
|
||||
|
||||
try sema.flushExports();
|
||||
@@ -36467,7 +36440,7 @@ fn semaUnionFields(pt: Zcu.PerThread, arena: Allocator, union_type: InternPool.L
|
||||
}
|
||||
} else {
|
||||
// The provided type is the enum tag type.
|
||||
union_type.tagTypePtr(ip).* = provided_ty.toIntern();
|
||||
union_type.setTagType(ip, provided_ty.toIntern());
|
||||
const enum_type = switch (ip.indexToKey(provided_ty.toIntern())) {
|
||||
.enum_type => ip.loadEnumType(provided_ty.toIntern()),
|
||||
else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{}'", .{provided_ty.fmt(pt)}),
|
||||
@@ -36605,10 +36578,11 @@ fn semaUnionFields(pt: Zcu.PerThread, arena: Allocator, union_type: InternPool.L
|
||||
}
|
||||
|
||||
if (explicit_tags_seen.len > 0) {
|
||||
const tag_info = ip.loadEnumType(union_type.tagTypePtr(ip).*);
|
||||
const tag_ty = union_type.tagTypeUnordered(ip);
|
||||
const tag_info = ip.loadEnumType(tag_ty);
|
||||
const enum_index = tag_info.nameIndex(ip, field_name) orelse {
|
||||
return sema.fail(&block_scope, name_src, "no field named '{}' in enum '{}'", .{
|
||||
field_name.fmt(ip), Type.fromInterned(union_type.tagTypePtr(ip).*).fmt(pt),
|
||||
field_name.fmt(ip), Type.fromInterned(tag_ty).fmt(pt),
|
||||
});
|
||||
};
|
||||
|
||||
@@ -36645,7 +36619,7 @@ fn semaUnionFields(pt: Zcu.PerThread, arena: Allocator, union_type: InternPool.L
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(&block_scope, msg);
|
||||
}
|
||||
const layout = union_type.getLayout(ip);
|
||||
const layout = union_type.flagsUnordered(ip).layout;
|
||||
if (layout == .@"extern" and
|
||||
!try sema.validateExternType(field_ty, .union_field))
|
||||
{
|
||||
@@ -36688,7 +36662,8 @@ fn semaUnionFields(pt: Zcu.PerThread, arena: Allocator, union_type: InternPool.L
|
||||
union_type.setFieldAligns(ip, field_aligns.items);
|
||||
|
||||
if (explicit_tags_seen.len > 0) {
|
||||
const tag_info = ip.loadEnumType(union_type.tagTypePtr(ip).*);
|
||||
const tag_ty = union_type.tagTypeUnordered(ip);
|
||||
const tag_info = ip.loadEnumType(tag_ty);
|
||||
if (tag_info.names.len > fields_len) {
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(src, "enum field(s) missing in union", .{});
|
||||
@@ -36696,21 +36671,21 @@ fn semaUnionFields(pt: Zcu.PerThread, arena: Allocator, union_type: InternPool.L
|
||||
|
||||
for (tag_info.names.get(ip), 0..) |field_name, field_index| {
|
||||
if (explicit_tags_seen[field_index]) continue;
|
||||
try sema.addFieldErrNote(Type.fromInterned(union_type.tagTypePtr(ip).*), field_index, msg, "field '{}' missing, declared here", .{
|
||||
try sema.addFieldErrNote(Type.fromInterned(tag_ty), field_index, msg, "field '{}' missing, declared here", .{
|
||||
field_name.fmt(ip),
|
||||
});
|
||||
}
|
||||
try sema.addDeclaredHereNote(msg, Type.fromInterned(union_type.tagTypePtr(ip).*));
|
||||
try sema.addDeclaredHereNote(msg, Type.fromInterned(tag_ty));
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(&block_scope, msg);
|
||||
}
|
||||
} else if (enum_field_vals.count() > 0) {
|
||||
const enum_ty = try sema.generateUnionTagTypeNumbered(&block_scope, enum_field_names, enum_field_vals.keys(), zcu.declPtr(union_type.decl));
|
||||
union_type.tagTypePtr(ip).* = enum_ty;
|
||||
union_type.setTagType(ip, enum_ty);
|
||||
} else {
|
||||
const enum_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, zcu.declPtr(union_type.decl));
|
||||
union_type.tagTypePtr(ip).* = enum_ty;
|
||||
union_type.setTagType(ip, enum_ty);
|
||||
}
|
||||
|
||||
try sema.flushExports();
|
||||
@@ -37086,7 +37061,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||
try ty.resolveLayout(pt);
|
||||
|
||||
const union_obj = ip.loadUnionType(ty.toIntern());
|
||||
const tag_val = (try sema.typeHasOnePossibleValue(Type.fromInterned(union_obj.tagTypePtr(ip).*))) orelse
|
||||
const tag_val = (try sema.typeHasOnePossibleValue(Type.fromInterned(union_obj.tagTypeUnordered(ip)))) orelse
|
||||
return null;
|
||||
if (union_obj.field_types.len == 0) {
|
||||
const only = try pt.intern(.{ .empty_enum_value = ty.toIntern() });
|
||||
|
||||
Reference in New Issue
Block a user