mirror of
https://github.com/ziglang/zig.git
synced 2026-01-14 03:15:14 +00:00
Merge pull request #16815 from mlugg/internpool-same-resolved-index
InternPool: preserve indices of builtin types when resolved
This commit is contained in:
commit
340a45683c
@ -8384,10 +8384,7 @@ fn builtinCall(
|
||||
local_val.used = ident_token;
|
||||
_ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{
|
||||
.operand = local_val.inst,
|
||||
// TODO: the result location here should be `.{ .coerced_ty = .export_options_type }`, but
|
||||
// that currently hits assertions in Sema due to type resolution issues.
|
||||
// See #16603
|
||||
.options = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]),
|
||||
.options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .export_options_type } }, params[1]),
|
||||
});
|
||||
return rvalue(gz, ri, .void_value, node);
|
||||
}
|
||||
@ -8402,10 +8399,7 @@ fn builtinCall(
|
||||
const loaded = try gz.addUnNode(.load, local_ptr.ptr, node);
|
||||
_ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{
|
||||
.operand = loaded,
|
||||
// TODO: the result location here should be `.{ .coerced_ty = .export_options_type }`, but
|
||||
// that currently hits assertions in Sema due to type resolution issues.
|
||||
// See #16603
|
||||
.options = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]),
|
||||
.options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .export_options_type } }, params[1]),
|
||||
});
|
||||
return rvalue(gz, ri, .void_value, node);
|
||||
}
|
||||
@ -8439,10 +8433,7 @@ fn builtinCall(
|
||||
},
|
||||
else => return astgen.failNode(params[0], "symbol to export must identify a declaration", .{}),
|
||||
}
|
||||
// TODO: the result location here should be `.{ .coerced_ty = .export_options_type }`, but
|
||||
// that currently hits assertions in Sema due to type resolution issues.
|
||||
// See #16603
|
||||
const options = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]);
|
||||
const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .export_options_type } }, params[1]);
|
||||
_ = try gz.addPlNode(.@"export", node, Zir.Inst.Export{
|
||||
.namespace = namespace,
|
||||
.decl_name = decl_name,
|
||||
@ -8452,10 +8443,7 @@ fn builtinCall(
|
||||
},
|
||||
.@"extern" => {
|
||||
const type_inst = try typeExpr(gz, scope, params[0]);
|
||||
// TODO: the result location here should be `.{ .coerced_ty = .extern_options_type }`, but
|
||||
// that currently hits assertions in Sema due to type resolution issues.
|
||||
// See #16603
|
||||
const options = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]);
|
||||
const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .extern_options_type } }, params[1]);
|
||||
const result = try gz.addExtendedPayload(.builtin_extern, Zir.Inst.BinNode{
|
||||
.node = gz.nodeIndexToRelative(node),
|
||||
.lhs = type_inst,
|
||||
@ -8559,10 +8547,7 @@ fn builtinCall(
|
||||
// zig fmt: on
|
||||
|
||||
.Type => {
|
||||
// TODO: the result location here should be `.{ .coerced_ty = .type_info_type }`, but
|
||||
// that currently hits assertions in Sema due to type resolution issues.
|
||||
// See #16603
|
||||
const operand = try expr(gz, scope, .{ .rl = .none }, params[0]);
|
||||
const operand = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .type_info_type } }, params[0]);
|
||||
|
||||
const gpa = gz.astgen.gpa;
|
||||
|
||||
@ -8834,10 +8819,7 @@ fn builtinCall(
|
||||
},
|
||||
.prefetch => {
|
||||
const ptr = try expr(gz, scope, .{ .rl = .none }, params[0]);
|
||||
// TODO: the result location here should be `.{ .coerced_ty = .preftech_options_type }`, but
|
||||
// that currently hits assertions in Sema due to type resolution issues.
|
||||
// See #16603
|
||||
const options = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]);
|
||||
const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .prefetch_options_type } }, params[1]);
|
||||
_ = try gz.addExtendedPayload(.prefetch, Zir.Inst.BinNode{
|
||||
.node = gz.nodeIndexToRelative(node),
|
||||
.lhs = ptr,
|
||||
|
||||
@ -7176,3 +7176,33 @@ fn unwrapCoercedFunc(ip: *const InternPool, i: Index) Index {
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
/// Having resolved a builtin type to a real struct/union/enum (which is now at `resolverd_index`),
|
||||
/// make `want_index` refer to this type instead. This invalidates `resolved_index`, so must be
|
||||
/// called only when it is guaranteed that no reference to `resolved_index` exists.
|
||||
pub fn resolveBuiltinType(ip: *InternPool, want_index: Index, resolved_index: Index) void {
|
||||
assert(@intFromEnum(want_index) >= @intFromEnum(Index.first_type));
|
||||
assert(@intFromEnum(want_index) <= @intFromEnum(Index.last_type));
|
||||
|
||||
// Make sure the type isn't already resolved!
|
||||
assert(ip.indexToKey(want_index) == .simple_type);
|
||||
|
||||
// Make sure it's the same kind of type
|
||||
assert((ip.zigTypeTagOrPoison(want_index) catch unreachable) ==
|
||||
(ip.zigTypeTagOrPoison(resolved_index) catch unreachable));
|
||||
|
||||
// Copy the data
|
||||
const item = ip.items.get(@intFromEnum(resolved_index));
|
||||
ip.items.set(@intFromEnum(want_index), item);
|
||||
|
||||
if (std.debug.runtime_safety) {
|
||||
// Make the value unreachable - this is a weird value which will make (incorrect) existing
|
||||
// references easier to spot
|
||||
ip.items.set(@intFromEnum(resolved_index), .{
|
||||
.tag = .simple_value,
|
||||
.data = @intFromEnum(SimpleValue.@"unreachable"),
|
||||
});
|
||||
} else {
|
||||
// TODO: add the index to a free-list for reuse
|
||||
}
|
||||
}
|
||||
|
||||
@ -770,9 +770,8 @@ pub const Decl = struct {
|
||||
|
||||
/// Gets the namespace that this Decl creates by being a struct, union,
|
||||
/// enum, or opaque.
|
||||
/// Only returns it if the Decl is the owner.
|
||||
pub fn getOwnedInnerNamespaceIndex(decl: Decl, mod: *Module) Namespace.OptionalIndex {
|
||||
if (!decl.owns_tv) return .none;
|
||||
pub fn getInnerNamespaceIndex(decl: Decl, mod: *Module) Namespace.OptionalIndex {
|
||||
if (!decl.has_tv) return .none;
|
||||
return switch (decl.val.ip_index) {
|
||||
.empty_struct_type => .none,
|
||||
.none => .none,
|
||||
@ -786,11 +785,22 @@ pub const Decl = struct {
|
||||
};
|
||||
}
|
||||
|
||||
/// Same as `getInnerNamespaceIndex` but additionally obtains the pointer.
|
||||
/// Like `getInnerNamespaceIndex`, but only returns it if the Decl is the owner.
|
||||
pub fn getOwnedInnerNamespaceIndex(decl: Decl, mod: *Module) Namespace.OptionalIndex {
|
||||
if (!decl.owns_tv) return .none;
|
||||
return decl.getInnerNamespaceIndex(mod);
|
||||
}
|
||||
|
||||
/// Same as `getOwnedInnerNamespaceIndex` but additionally obtains the pointer.
|
||||
pub fn getOwnedInnerNamespace(decl: Decl, mod: *Module) ?*Namespace {
|
||||
return mod.namespacePtrUnwrap(decl.getOwnedInnerNamespaceIndex(mod));
|
||||
}
|
||||
|
||||
/// Same as `getInnerNamespaceIndex` but additionally obtains the pointer.
|
||||
pub fn getInnerNamespace(decl: Decl, mod: *Module) ?*Namespace {
|
||||
return mod.namespacePtrUnwrap(decl.getInnerNamespaceIndex(mod));
|
||||
}
|
||||
|
||||
pub fn dump(decl: *Decl) void {
|
||||
const loc = std.zig.findLineColumn(decl.scope.source.bytes, decl.src);
|
||||
std.debug.print("{s}:{d}:{d} name={d} status={s}", .{
|
||||
@ -4283,6 +4293,40 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
|
||||
const zir = decl.getFileScope(mod).zir;
|
||||
const zir_datas = zir.instructions.items(.data);
|
||||
|
||||
// TODO: figure out how this works under incremental changes to builtin.zig!
|
||||
const builtin_type_target_index: InternPool.Index = blk: {
|
||||
const std_mod = mod.main_pkg.table.get("std").?;
|
||||
if (decl.getFileScope(mod).pkg != std_mod) break :blk .none;
|
||||
// We're in the std module.
|
||||
const std_file = (try mod.importPkg(std_mod)).file;
|
||||
const std_decl = mod.declPtr(std_file.root_decl.unwrap().?);
|
||||
const std_namespace = std_decl.getInnerNamespace(mod).?;
|
||||
const builtin_str = try mod.intern_pool.getOrPutString(gpa, "builtin");
|
||||
const builtin_decl = mod.declPtr(std_namespace.decls.getKeyAdapted(builtin_str, DeclAdapter{ .mod = mod }) orelse break :blk .none);
|
||||
const builtin_namespace = builtin_decl.getInnerNamespaceIndex(mod).unwrap() orelse break :blk .none;
|
||||
if (decl.src_namespace != builtin_namespace) break :blk .none;
|
||||
// We're in builtin.zig. This could be a builtin we need to add to a specific InternPool index.
|
||||
const decl_name = mod.intern_pool.stringToSlice(decl.name);
|
||||
for ([_]struct { []const u8, InternPool.Index }{
|
||||
.{ "AtomicOrder", .atomic_order_type },
|
||||
.{ "AtomicRmwOp", .atomic_rmw_op_type },
|
||||
.{ "CallingConvention", .calling_convention_type },
|
||||
.{ "AddressSpace", .address_space_type },
|
||||
.{ "FloatMode", .float_mode_type },
|
||||
.{ "ReduceOp", .reduce_op_type },
|
||||
.{ "CallModifier", .call_modifier_type },
|
||||
.{ "PrefetchOptions", .prefetch_options_type },
|
||||
.{ "ExportOptions", .export_options_type },
|
||||
.{ "ExternOptions", .extern_options_type },
|
||||
.{ "Type", .type_info_type },
|
||||
}) |pair| {
|
||||
if (std.mem.eql(u8, decl_name, pair[0])) {
|
||||
break :blk pair[1];
|
||||
}
|
||||
}
|
||||
break :blk .none;
|
||||
};
|
||||
|
||||
decl.analysis = .in_progress;
|
||||
|
||||
var analysis_arena = std.heap.ArenaAllocator.init(gpa);
|
||||
@ -4304,6 +4348,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
|
||||
.fn_ret_ty_ies = null,
|
||||
.owner_func_index = .none,
|
||||
.comptime_mutable_decls = &comptime_mutable_decls,
|
||||
.builtin_type_target_index = builtin_type_target_index,
|
||||
};
|
||||
defer sema.deinit();
|
||||
|
||||
@ -4340,6 +4385,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
|
||||
const extra = zir.extraData(Zir.Inst.Block, inst_data.payload_index);
|
||||
const body = zir.extra[extra.end..][0..extra.data.body_len];
|
||||
const result_ref = (try sema.analyzeBodyBreak(&block_scope, body)).?.operand;
|
||||
// We'll do some other bits with the Sema. Clear the type target index just in case they analyze any type.
|
||||
sema.builtin_type_target_index = .none;
|
||||
try wip_captures.finalize();
|
||||
for (comptime_mutable_decls.items) |ct_decl_index| {
|
||||
const ct_decl = mod.declPtr(ct_decl_index);
|
||||
|
||||
377
src/Sema.zig
377
src/Sema.zig
@ -107,6 +107,10 @@ comptime_mutable_decls: *std.ArrayList(Decl.Index),
|
||||
/// one encountered, the conflicting source location can be shown.
|
||||
prev_stack_alignment_src: ?LazySrcLoc = null,
|
||||
|
||||
/// While analyzing a type which has a special InternPool index, this is set to the index at which
|
||||
/// the struct/enum/union type created should be placed. Otherwise, it is `.none`.
|
||||
builtin_type_target_index: InternPool.Index = .none,
|
||||
|
||||
const std = @import("std");
|
||||
const math = std.math;
|
||||
const mem = std.mem;
|
||||
@ -1956,8 +1960,8 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)
|
||||
const addrs_ptr = try err_trace_block.addTy(.alloc, try mod.singleMutPtrType(addr_arr_ty));
|
||||
|
||||
// var st: StackTrace = undefined;
|
||||
const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
|
||||
const stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
try sema.resolveTypeFields(stack_trace_ty);
|
||||
const st_ptr = try err_trace_block.addTy(.alloc, try mod.singleMutPtrType(stack_trace_ty));
|
||||
|
||||
// st.instruction_addresses = &addrs;
|
||||
@ -2890,10 +2894,17 @@ fn zirStructDecl(
|
||||
});
|
||||
errdefer mod.destroyStruct(struct_index);
|
||||
|
||||
const struct_ty = try mod.intern_pool.get(gpa, .{ .struct_type = .{
|
||||
.index = struct_index.toOptional(),
|
||||
.namespace = new_namespace_index.toOptional(),
|
||||
} });
|
||||
const struct_ty = ty: {
|
||||
const ty = try mod.intern_pool.get(gpa, .{ .struct_type = .{
|
||||
.index = struct_index.toOptional(),
|
||||
.namespace = new_namespace_index.toOptional(),
|
||||
} });
|
||||
if (sema.builtin_type_target_index != .none) {
|
||||
mod.intern_pool.resolveBuiltinType(sema.builtin_type_target_index, ty);
|
||||
break :ty sema.builtin_type_target_index;
|
||||
}
|
||||
break :ty ty;
|
||||
};
|
||||
// TODO: figure out InternPool removals for incremental compilation
|
||||
//errdefer mod.intern_pool.remove(struct_ty);
|
||||
|
||||
@ -3084,18 +3095,25 @@ fn zirEnumDecl(
|
||||
if (bag != 0) break true;
|
||||
} else false;
|
||||
|
||||
const incomplete_enum = try mod.intern_pool.getIncompleteEnum(gpa, .{
|
||||
.decl = new_decl_index,
|
||||
.namespace = new_namespace_index.toOptional(),
|
||||
.fields_len = fields_len,
|
||||
.has_values = any_values,
|
||||
.tag_mode = if (small.nonexhaustive)
|
||||
.nonexhaustive
|
||||
else if (tag_type_ref == .none)
|
||||
.auto
|
||||
else
|
||||
.explicit,
|
||||
});
|
||||
const incomplete_enum = incomplete_enum: {
|
||||
var incomplete_enum = try mod.intern_pool.getIncompleteEnum(gpa, .{
|
||||
.decl = new_decl_index,
|
||||
.namespace = new_namespace_index.toOptional(),
|
||||
.fields_len = fields_len,
|
||||
.has_values = any_values,
|
||||
.tag_mode = if (small.nonexhaustive)
|
||||
.nonexhaustive
|
||||
else if (tag_type_ref == .none)
|
||||
.auto
|
||||
else
|
||||
.explicit,
|
||||
});
|
||||
if (sema.builtin_type_target_index != .none) {
|
||||
mod.intern_pool.resolveBuiltinType(sema.builtin_type_target_index, incomplete_enum.index);
|
||||
incomplete_enum.index = sema.builtin_type_target_index;
|
||||
}
|
||||
break :incomplete_enum incomplete_enum;
|
||||
};
|
||||
// TODO: figure out InternPool removals for incremental compilation
|
||||
//errdefer if (!done) mod.intern_pool.remove(incomplete_enum.index);
|
||||
|
||||
@ -3336,17 +3354,24 @@ fn zirUnionDecl(
|
||||
});
|
||||
errdefer mod.destroyUnion(union_index);
|
||||
|
||||
const union_ty = try mod.intern_pool.get(gpa, .{ .union_type = .{
|
||||
.index = union_index,
|
||||
.runtime_tag = if (small.has_tag_type or small.auto_enum_tag)
|
||||
.tagged
|
||||
else if (small.layout != .Auto)
|
||||
.none
|
||||
else switch (block.sema.mod.optimizeMode()) {
|
||||
.Debug, .ReleaseSafe => .safety,
|
||||
.ReleaseFast, .ReleaseSmall => .none,
|
||||
},
|
||||
} });
|
||||
const union_ty = ty: {
|
||||
const ty = try mod.intern_pool.get(gpa, .{ .union_type = .{
|
||||
.index = union_index,
|
||||
.runtime_tag = if (small.has_tag_type or small.auto_enum_tag)
|
||||
.tagged
|
||||
else if (small.layout != .Auto)
|
||||
.none
|
||||
else switch (block.sema.mod.optimizeMode()) {
|
||||
.Debug, .ReleaseSafe => .safety,
|
||||
.ReleaseFast, .ReleaseSmall => .none,
|
||||
},
|
||||
} });
|
||||
if (sema.builtin_type_target_index != .none) {
|
||||
mod.intern_pool.resolveBuiltinType(sema.builtin_type_target_index, ty);
|
||||
break :ty sema.builtin_type_target_index;
|
||||
}
|
||||
break :ty ty;
|
||||
};
|
||||
// TODO: figure out InternPool removals for incremental compilation
|
||||
//errdefer mod.intern_pool.remove(union_ty);
|
||||
|
||||
@ -3473,8 +3498,8 @@ fn zirRetPtr(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
|
||||
defer tracy.end();
|
||||
|
||||
if (block.is_comptime or try sema.typeRequiresComptime(sema.fn_ret_ty)) {
|
||||
const fn_ret_ty = try sema.resolveTypeFields(sema.fn_ret_ty);
|
||||
return sema.analyzeComptimeAlloc(block, fn_ret_ty, .none);
|
||||
try sema.resolveTypeFields(sema.fn_ret_ty);
|
||||
return sema.analyzeComptimeAlloc(block, sema.fn_ret_ty, .none);
|
||||
}
|
||||
|
||||
const target = sema.mod.getTarget();
|
||||
@ -4371,7 +4396,7 @@ fn zirValidateArrayInitTy(
|
||||
return;
|
||||
},
|
||||
.Struct => if (ty.isTuple(mod)) {
|
||||
_ = try sema.resolveTypeFields(ty);
|
||||
try sema.resolveTypeFields(ty);
|
||||
const array_len = ty.arrayLen(mod);
|
||||
if (extra.init_count > array_len) {
|
||||
return sema.fail(block, src, "expected at most {d} tuple fields; found {d}", .{
|
||||
@ -6476,11 +6501,11 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref
|
||||
if (block.is_comptime)
|
||||
return .none;
|
||||
|
||||
const unresolved_stack_trace_ty = sema.getBuiltinType("StackTrace") catch |err| switch (err) {
|
||||
const stack_trace_ty = sema.getBuiltinType("StackTrace") catch |err| switch (err) {
|
||||
error.NeededSourceLocation, error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
|
||||
else => |e| return e,
|
||||
};
|
||||
const stack_trace_ty = sema.resolveTypeFields(unresolved_stack_trace_ty) catch |err| switch (err) {
|
||||
sema.resolveTypeFields(stack_trace_ty) catch |err| switch (err) {
|
||||
error.NeededSourceLocation, error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
|
||||
else => |e| return e,
|
||||
};
|
||||
@ -6522,8 +6547,8 @@ fn popErrorReturnTrace(
|
||||
// AstGen determined this result does not go to an error-handling expr (try/catch/return etc.), or
|
||||
// the result is comptime-known to be a non-error. Either way, pop unconditionally.
|
||||
|
||||
const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
|
||||
const stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
try sema.resolveTypeFields(stack_trace_ty);
|
||||
const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);
|
||||
const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
|
||||
const field_name = try mod.intern_pool.getOrPutString(gpa, "index");
|
||||
@ -6548,8 +6573,8 @@ fn popErrorReturnTrace(
|
||||
defer then_block.instructions.deinit(gpa);
|
||||
|
||||
// If non-error, then pop the error return trace by restoring the index.
|
||||
const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
|
||||
const stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
try sema.resolveTypeFields(stack_trace_ty);
|
||||
const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);
|
||||
const err_return_trace = try then_block.addTy(.err_return_trace, ptr_stack_trace_ty);
|
||||
const field_name = try mod.intern_pool.getOrPutString(gpa, "index");
|
||||
@ -6671,8 +6696,8 @@ fn zirCall(
|
||||
// If any input is an error-type, we might need to pop any trace it generated. Otherwise, we only
|
||||
// need to clean-up our own trace if we were passed to a non-error-handling expression.
|
||||
if (input_is_error or (pop_error_return_trace and return_ty.isError(mod))) {
|
||||
const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
|
||||
const stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
try sema.resolveTypeFields(stack_trace_ty);
|
||||
const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "index");
|
||||
const field_index = try sema.structFieldIndex(block, stack_trace_ty, field_name, call_src);
|
||||
|
||||
@ -8084,7 +8109,7 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
|
||||
fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
const mod = sema.mod;
|
||||
const bin = sema.code.instructions.items(.data)[inst].bin;
|
||||
const operand = sema.resolveType(block, .unneeded, bin.lhs) catch |err| switch (err) {
|
||||
const indexable_ty = sema.resolveType(block, .unneeded, bin.lhs) catch |err| switch (err) {
|
||||
// Since this is a ZIR instruction that returns a type, encountering
|
||||
// generic poison should not result in a failed compilation, but the
|
||||
// generic poison type. This prevents unnecessary failures when
|
||||
@ -8092,7 +8117,7 @@ fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
|
||||
error.GenericPoison => return .generic_poison_type,
|
||||
else => |e| return e,
|
||||
};
|
||||
const indexable_ty = try sema.resolveTypeFields(operand);
|
||||
try sema.resolveTypeFields(indexable_ty);
|
||||
assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction
|
||||
if (indexable_ty.zigTypeTag(mod) == .Struct) {
|
||||
const elem_type = indexable_ty.structFieldType(@intFromEnum(bin.rhs), mod);
|
||||
@ -8420,8 +8445,8 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
||||
const enum_tag: Air.Inst.Ref = switch (operand_ty.zigTypeTag(mod)) {
|
||||
.Enum => operand,
|
||||
.Union => blk: {
|
||||
const union_ty = try sema.resolveTypeFields(operand_ty);
|
||||
const tag_ty = union_ty.unionTagType(mod) orelse {
|
||||
try sema.resolveTypeFields(operand_ty);
|
||||
const tag_ty = operand_ty.unionTagType(mod) orelse {
|
||||
return sema.fail(
|
||||
block,
|
||||
operand_src,
|
||||
@ -9573,7 +9598,7 @@ fn finishFunc(
|
||||
// Make sure that StackTrace's fields are resolved so that the backend can
|
||||
// lower this fn type.
|
||||
const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
_ = try sema.resolveTypeFields(unresolved_stack_trace_ty);
|
||||
try sema.resolveTypeFields(unresolved_stack_trace_ty);
|
||||
}
|
||||
|
||||
return Air.internedToRef(if (opt_func_index != .none) opt_func_index else func_ty);
|
||||
@ -10890,12 +10915,12 @@ fn switchCond(
|
||||
},
|
||||
|
||||
.Union => {
|
||||
const union_ty = try sema.resolveTypeFields(operand_ty);
|
||||
const enum_ty = union_ty.unionTagType(mod) orelse {
|
||||
try sema.resolveTypeFields(operand_ty);
|
||||
const enum_ty = operand_ty.unionTagType(mod) orelse {
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(block, src, "switch on union with no attached enum", .{});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
if (union_ty.declSrcLocOrNull(mod)) |union_src| {
|
||||
if (operand_ty.declSrcLocOrNull(mod)) |union_src| {
|
||||
try mod.errNoteNonLazy(union_src, msg, "consider 'union(enum)' here", .{});
|
||||
}
|
||||
break :msg msg;
|
||||
@ -12780,9 +12805,9 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
|
||||
const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||
const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
|
||||
const unresolved_ty = try sema.resolveType(block, ty_src, extra.lhs);
|
||||
const ty = try sema.resolveType(block, ty_src, extra.lhs);
|
||||
const field_name = try sema.resolveConstStringIntern(block, name_src, extra.rhs, "field name must be comptime-known");
|
||||
const ty = try sema.resolveTypeFields(unresolved_ty);
|
||||
try sema.resolveTypeFields(ty);
|
||||
const ip = &mod.intern_pool;
|
||||
|
||||
const has_field = hf: {
|
||||
@ -16141,7 +16166,8 @@ fn analyzeCmpUnionTag(
|
||||
op: std.math.CompareOperator,
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const mod = sema.mod;
|
||||
const union_ty = try sema.resolveTypeFields(sema.typeOf(un));
|
||||
const union_ty = sema.typeOf(un);
|
||||
try sema.resolveTypeFields(union_ty);
|
||||
const union_tag_ty = union_ty.unionTagType(mod) orelse {
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(block, un_src, "comparison of union and enum literal is only valid for tagged union types", .{});
|
||||
@ -17278,11 +17304,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
break :t union_field_ty_decl.val.toType();
|
||||
};
|
||||
|
||||
const union_ty = try sema.resolveTypeFields(ty);
|
||||
try sema.resolveTypeLayout(ty); // Getting alignment requires type layout
|
||||
const layout = union_ty.containerLayout(mod);
|
||||
const layout = ty.containerLayout(mod);
|
||||
|
||||
const union_fields = union_ty.unionFields(mod);
|
||||
const union_fields = ty.unionFields(mod);
|
||||
const union_field_vals = try gpa.alloc(InternPool.Index, union_fields.count());
|
||||
defer gpa.free(union_field_vals);
|
||||
|
||||
@ -17357,11 +17382,11 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
} });
|
||||
};
|
||||
|
||||
const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, union_ty.getNamespaceIndex(mod));
|
||||
const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ty.getNamespaceIndex(mod));
|
||||
|
||||
const enum_tag_ty_val = try mod.intern(.{ .opt = .{
|
||||
.ty = (try mod.optionalType(.type_type)).toIntern(),
|
||||
.val = if (union_ty.unionTagType(mod)) |tag_ty| tag_ty.toIntern() else .none,
|
||||
.val = if (ty.unionTagType(mod)) |tag_ty| tag_ty.toIntern() else .none,
|
||||
} });
|
||||
|
||||
const container_layout_ty = t: {
|
||||
@ -17429,18 +17454,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
break :t struct_field_ty_decl.val.toType();
|
||||
};
|
||||
|
||||
const struct_ty = try sema.resolveTypeFields(ty);
|
||||
try sema.resolveTypeLayout(ty); // Getting alignment requires type layout
|
||||
const layout = struct_ty.containerLayout(mod);
|
||||
const layout = ty.containerLayout(mod);
|
||||
|
||||
var struct_field_vals: []InternPool.Index = &.{};
|
||||
defer gpa.free(struct_field_vals);
|
||||
fv: {
|
||||
const struct_type = switch (ip.indexToKey(struct_ty.toIntern())) {
|
||||
const struct_type = switch (ip.indexToKey(ty.toIntern())) {
|
||||
.anon_struct_type => |tuple| {
|
||||
struct_field_vals = try gpa.alloc(InternPool.Index, tuple.types.len);
|
||||
for (struct_field_vals, 0..) |*struct_field_val, i| {
|
||||
const anon_struct_type = ip.indexToKey(struct_ty.toIntern()).anon_struct_type;
|
||||
const anon_struct_type = ip.indexToKey(ty.toIntern()).anon_struct_type;
|
||||
const field_ty = anon_struct_type.types[i];
|
||||
const field_val = anon_struct_type.values[i];
|
||||
const name_val = v: {
|
||||
@ -17449,7 +17473,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
// TODO: write something like getCoercedInts to avoid needing to dupe
|
||||
const bytes = if (tuple.names.len != 0)
|
||||
// https://github.com/ziglang/zig/issues/15709
|
||||
try sema.arena.dupe(u8, ip.stringToSlice(ip.indexToKey(struct_ty.toIntern()).anon_struct_type.names[i]))
|
||||
try sema.arena.dupe(u8, ip.stringToSlice(ip.indexToKey(ty.toIntern()).anon_struct_type.names[i]))
|
||||
else
|
||||
try std.fmt.allocPrint(sema.arena, "{d}", .{i});
|
||||
const new_decl_ty = try mod.arrayType(.{
|
||||
@ -17582,12 +17606,12 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
} });
|
||||
};
|
||||
|
||||
const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, struct_ty.getNamespaceIndex(mod));
|
||||
const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ty.getNamespaceIndex(mod));
|
||||
|
||||
const backing_integer_val = try mod.intern(.{ .opt = .{
|
||||
.ty = (try mod.optionalType(.type_type)).toIntern(),
|
||||
.val = if (layout == .Packed) val: {
|
||||
const struct_obj = mod.typeToStruct(struct_ty).?;
|
||||
const struct_obj = mod.typeToStruct(ty).?;
|
||||
assert(struct_obj.haveLayout());
|
||||
assert(struct_obj.backing_int_ty.isInt(mod));
|
||||
break :val struct_obj.backing_int_ty.toIntern();
|
||||
@ -17617,7 +17641,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
// decls: []const Declaration,
|
||||
decls_val,
|
||||
// is_tuple: bool,
|
||||
Value.makeBool(struct_ty.isTuple(mod)).toIntern(),
|
||||
Value.makeBool(ty.isTuple(mod)).toIntern(),
|
||||
};
|
||||
return Air.internedToRef((try mod.intern(.{ .un = .{
|
||||
.ty = type_info_ty.toIntern(),
|
||||
@ -17644,8 +17668,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
break :t type_opaque_ty_decl.val.toType();
|
||||
};
|
||||
|
||||
const opaque_ty = try sema.resolveTypeFields(ty);
|
||||
const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, opaque_ty.getNamespaceIndex(mod));
|
||||
try sema.resolveTypeFields(ty);
|
||||
const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ty.getNamespaceIndex(mod));
|
||||
|
||||
const field_values = .{
|
||||
// decls: []const Declaration,
|
||||
@ -18511,8 +18535,8 @@ fn retWithErrTracing(
|
||||
else => true,
|
||||
};
|
||||
const gpa = sema.gpa;
|
||||
const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
|
||||
const stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
try sema.resolveTypeFields(stack_trace_ty);
|
||||
const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);
|
||||
const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
|
||||
const return_err_fn = try sema.getBuiltin("returnError");
|
||||
@ -18874,14 +18898,14 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
|
||||
fn structInitEmpty(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
obj_ty: Type,
|
||||
struct_ty: Type,
|
||||
dest_src: LazySrcLoc,
|
||||
init_src: LazySrcLoc,
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const mod = sema.mod;
|
||||
const gpa = sema.gpa;
|
||||
// This logic must be synchronized with that in `zirStructInit`.
|
||||
const struct_ty = try sema.resolveTypeFields(obj_ty);
|
||||
try sema.resolveTypeFields(struct_ty);
|
||||
|
||||
// The init values to use for the struct instance.
|
||||
const field_inits = try gpa.alloc(Air.Inst.Ref, struct_ty.structFieldCount(mod));
|
||||
@ -19674,8 +19698,7 @@ fn fieldType(
|
||||
const mod = sema.mod;
|
||||
var cur_ty = aggregate_ty;
|
||||
while (true) {
|
||||
const resolved_ty = try sema.resolveTypeFields(cur_ty);
|
||||
cur_ty = resolved_ty;
|
||||
try sema.resolveTypeFields(cur_ty);
|
||||
switch (cur_ty.zigTypeTag(mod)) {
|
||||
.Struct => switch (mod.intern_pool.indexToKey(cur_ty.toIntern())) {
|
||||
.anon_struct_type => |anon_struct| {
|
||||
@ -19709,7 +19732,7 @@ fn fieldType(
|
||||
else => {},
|
||||
}
|
||||
return sema.fail(block, ty_src, "expected struct or union; found '{}'", .{
|
||||
resolved_ty.fmt(sema.mod),
|
||||
cur_ty.fmt(sema.mod),
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -19721,8 +19744,8 @@ fn zirErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
|
||||
fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
|
||||
const mod = sema.mod;
|
||||
const ip = &mod.intern_pool;
|
||||
const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
|
||||
const stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
try sema.resolveTypeFields(stack_trace_ty);
|
||||
const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);
|
||||
const opt_ptr_stack_trace_ty = try mod.optionalType(ptr_stack_trace_ty.toIntern());
|
||||
|
||||
@ -20048,14 +20071,10 @@ fn zirReify(
|
||||
(try alignment_val.getUnsignedIntAdvanced(mod, sema)).?,
|
||||
);
|
||||
|
||||
const unresolved_elem_ty = child_val.toType();
|
||||
const elem_ty = if (abi_align == .none)
|
||||
unresolved_elem_ty
|
||||
else t: {
|
||||
const elem_ty = try sema.resolveTypeFields(unresolved_elem_ty);
|
||||
const elem_ty = child_val.toType();
|
||||
if (abi_align != .none) {
|
||||
try sema.resolveTypeLayout(elem_ty);
|
||||
break :t elem_ty;
|
||||
};
|
||||
}
|
||||
|
||||
const ptr_size = mod.toEnum(std.builtin.Type.Pointer.Size, size_val);
|
||||
|
||||
@ -25070,8 +25089,8 @@ fn prepareSimplePanic(sema: *Sema, block: *Block) !void {
|
||||
}
|
||||
|
||||
if (mod.null_stack_trace == .none) {
|
||||
const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
|
||||
const stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
try sema.resolveTypeFields(stack_trace_ty);
|
||||
const target = mod.getTarget();
|
||||
const ptr_stack_trace_ty = try mod.ptrType(.{
|
||||
.child = stack_trace_ty.toIntern(),
|
||||
@ -25523,14 +25542,14 @@ fn fieldVal(
|
||||
return inst;
|
||||
}
|
||||
}
|
||||
const union_ty = try sema.resolveTypeFields(child_type);
|
||||
if (union_ty.unionTagType(mod)) |enum_ty| {
|
||||
try sema.resolveTypeFields(child_type);
|
||||
if (child_type.unionTagType(mod)) |enum_ty| {
|
||||
if (enum_ty.enumFieldIndex(field_name, mod)) |field_index_usize| {
|
||||
const field_index = @as(u32, @intCast(field_index_usize));
|
||||
return Air.internedToRef((try mod.enumValueFieldIndex(enum_ty, field_index)).toIntern());
|
||||
}
|
||||
}
|
||||
return sema.failWithBadMemberAccess(block, union_ty, field_name_src, field_name);
|
||||
return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);
|
||||
},
|
||||
.Enum => {
|
||||
if (child_type.getNamespaceIndex(mod).unwrap()) |namespace| {
|
||||
@ -25749,8 +25768,8 @@ fn fieldPtr(
|
||||
return inst;
|
||||
}
|
||||
}
|
||||
const union_ty = try sema.resolveTypeFields(child_type);
|
||||
if (union_ty.unionTagType(mod)) |enum_ty| {
|
||||
try sema.resolveTypeFields(child_type);
|
||||
if (child_type.unionTagType(mod)) |enum_ty| {
|
||||
if (enum_ty.enumFieldIndex(field_name, mod)) |field_index| {
|
||||
const field_index_u32 = @as(u32, @intCast(field_index));
|
||||
var anon_decl = try block.startAnonDecl();
|
||||
@ -25854,35 +25873,35 @@ fn fieldCallBind(
|
||||
find_field: {
|
||||
switch (concrete_ty.zigTypeTag(mod)) {
|
||||
.Struct => {
|
||||
const struct_ty = try sema.resolveTypeFields(concrete_ty);
|
||||
if (mod.typeToStruct(struct_ty)) |struct_obj| {
|
||||
try sema.resolveTypeFields(concrete_ty);
|
||||
if (mod.typeToStruct(concrete_ty)) |struct_obj| {
|
||||
const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
|
||||
break :find_field;
|
||||
const field_index = @as(u32, @intCast(field_index_usize));
|
||||
const field = struct_obj.fields.values()[field_index];
|
||||
|
||||
return sema.finishFieldCallBind(block, src, ptr_ty, field.ty, field_index, object_ptr);
|
||||
} else if (struct_ty.isTuple(mod)) {
|
||||
} else if (concrete_ty.isTuple(mod)) {
|
||||
if (ip.stringEqlSlice(field_name, "len")) {
|
||||
return .{ .direct = try mod.intRef(Type.usize, struct_ty.structFieldCount(mod)) };
|
||||
return .{ .direct = try mod.intRef(Type.usize, concrete_ty.structFieldCount(mod)) };
|
||||
}
|
||||
if (field_name.toUnsigned(ip)) |field_index| {
|
||||
if (field_index >= struct_ty.structFieldCount(mod)) break :find_field;
|
||||
return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(field_index, mod), field_index, object_ptr);
|
||||
if (field_index >= concrete_ty.structFieldCount(mod)) break :find_field;
|
||||
return sema.finishFieldCallBind(block, src, ptr_ty, concrete_ty.structFieldType(field_index, mod), field_index, object_ptr);
|
||||
}
|
||||
} else {
|
||||
const max = struct_ty.structFieldCount(mod);
|
||||
const max = concrete_ty.structFieldCount(mod);
|
||||
for (0..max) |i_usize| {
|
||||
const i = @as(u32, @intCast(i_usize));
|
||||
if (field_name == struct_ty.structFieldName(i, mod)) {
|
||||
return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(i, mod), i, object_ptr);
|
||||
if (field_name == concrete_ty.structFieldName(i, mod)) {
|
||||
return sema.finishFieldCallBind(block, src, ptr_ty, concrete_ty.structFieldType(i, mod), i, object_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
.Union => {
|
||||
const union_ty = try sema.resolveTypeFields(concrete_ty);
|
||||
const fields = union_ty.unionFields(mod);
|
||||
try sema.resolveTypeFields(concrete_ty);
|
||||
const fields = concrete_ty.unionFields(mod);
|
||||
const field_index_usize = fields.getIndex(field_name) orelse break :find_field;
|
||||
const field_index = @as(u32, @intCast(field_index_usize));
|
||||
const field = fields.values()[field_index];
|
||||
@ -26081,13 +26100,13 @@ fn structFieldPtr(
|
||||
struct_ptr: Air.Inst.Ref,
|
||||
field_name: InternPool.NullTerminatedString,
|
||||
field_name_src: LazySrcLoc,
|
||||
unresolved_struct_ty: Type,
|
||||
struct_ty: Type,
|
||||
initializing: bool,
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const mod = sema.mod;
|
||||
assert(unresolved_struct_ty.zigTypeTag(mod) == .Struct);
|
||||
assert(struct_ty.zigTypeTag(mod) == .Struct);
|
||||
|
||||
const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);
|
||||
try sema.resolveTypeFields(struct_ty);
|
||||
try sema.resolveStructLayout(struct_ty);
|
||||
|
||||
if (struct_ty.isTuple(mod)) {
|
||||
@ -26234,12 +26253,12 @@ fn structFieldVal(
|
||||
struct_byval: Air.Inst.Ref,
|
||||
field_name: InternPool.NullTerminatedString,
|
||||
field_name_src: LazySrcLoc,
|
||||
unresolved_struct_ty: Type,
|
||||
struct_ty: Type,
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const mod = sema.mod;
|
||||
assert(unresolved_struct_ty.zigTypeTag(mod) == .Struct);
|
||||
assert(struct_ty.zigTypeTag(mod) == .Struct);
|
||||
|
||||
const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);
|
||||
try sema.resolveTypeFields(struct_ty);
|
||||
switch (mod.intern_pool.indexToKey(struct_ty.toIntern())) {
|
||||
.struct_type => |struct_type| {
|
||||
const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
|
||||
@ -26361,17 +26380,17 @@ fn unionFieldPtr(
|
||||
union_ptr: Air.Inst.Ref,
|
||||
field_name: InternPool.NullTerminatedString,
|
||||
field_name_src: LazySrcLoc,
|
||||
unresolved_union_ty: Type,
|
||||
union_ty: Type,
|
||||
initializing: bool,
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const mod = sema.mod;
|
||||
const ip = &mod.intern_pool;
|
||||
|
||||
assert(unresolved_union_ty.zigTypeTag(mod) == .Union);
|
||||
assert(union_ty.zigTypeTag(mod) == .Union);
|
||||
|
||||
const union_ptr_ty = sema.typeOf(union_ptr);
|
||||
const union_ptr_info = union_ptr_ty.ptrInfo(mod);
|
||||
const union_ty = try sema.resolveTypeFields(unresolved_union_ty);
|
||||
try sema.resolveTypeFields(union_ty);
|
||||
const union_obj = mod.typeToUnion(union_ty).?;
|
||||
const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src);
|
||||
const field = union_obj.fields.values()[field_index];
|
||||
@ -26467,13 +26486,13 @@ fn unionFieldVal(
|
||||
union_byval: Air.Inst.Ref,
|
||||
field_name: InternPool.NullTerminatedString,
|
||||
field_name_src: LazySrcLoc,
|
||||
unresolved_union_ty: Type,
|
||||
union_ty: Type,
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const mod = sema.mod;
|
||||
const ip = &mod.intern_pool;
|
||||
assert(unresolved_union_ty.zigTypeTag(mod) == .Union);
|
||||
assert(union_ty.zigTypeTag(mod) == .Union);
|
||||
|
||||
const union_ty = try sema.resolveTypeFields(unresolved_union_ty);
|
||||
try sema.resolveTypeFields(union_ty);
|
||||
const union_obj = mod.typeToUnion(union_ty).?;
|
||||
const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src);
|
||||
const field = union_obj.fields.values()[field_index];
|
||||
@ -26733,7 +26752,7 @@ fn tupleFieldPtr(
|
||||
const mod = sema.mod;
|
||||
const tuple_ptr_ty = sema.typeOf(tuple_ptr);
|
||||
const tuple_ty = tuple_ptr_ty.childType(mod);
|
||||
_ = try sema.resolveTypeFields(tuple_ty);
|
||||
try sema.resolveTypeFields(tuple_ty);
|
||||
const field_count = tuple_ty.structFieldCount(mod);
|
||||
|
||||
if (field_count == 0) {
|
||||
@ -26790,7 +26809,8 @@ fn tupleField(
|
||||
field_index: u32,
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const mod = sema.mod;
|
||||
const tuple_ty = try sema.resolveTypeFields(sema.typeOf(tuple));
|
||||
const tuple_ty = sema.typeOf(tuple);
|
||||
try sema.resolveTypeFields(tuple_ty);
|
||||
const field_count = tuple_ty.structFieldCount(mod);
|
||||
|
||||
if (field_count == 0) {
|
||||
@ -26872,6 +26892,7 @@ fn elemValArray(
|
||||
|
||||
const runtime_src = if (maybe_undef_array_val != null) elem_index_src else array_src;
|
||||
try sema.requireRuntimeBlock(block, src, runtime_src);
|
||||
try sema.queueFullTypeResolution(array_ty);
|
||||
if (oob_safety and block.wantSafety()) {
|
||||
// Runtime check is only needed if unable to comptime check
|
||||
if (maybe_index_val == null) {
|
||||
@ -27113,16 +27134,17 @@ const CoerceOpts = struct {
|
||||
fn coerceExtra(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
dest_ty_unresolved: Type,
|
||||
dest_ty: Type,
|
||||
inst: Air.Inst.Ref,
|
||||
inst_src: LazySrcLoc,
|
||||
opts: CoerceOpts,
|
||||
) CoersionError!Air.Inst.Ref {
|
||||
if (dest_ty_unresolved.isGenericPoison()) return inst;
|
||||
if (dest_ty.isGenericPoison()) return inst;
|
||||
const mod = sema.mod;
|
||||
const dest_ty_src = inst_src; // TODO better source location
|
||||
const dest_ty = try sema.resolveTypeFields(dest_ty_unresolved);
|
||||
const inst_ty = try sema.resolveTypeFields(sema.typeOf(inst));
|
||||
try sema.resolveTypeFields(dest_ty);
|
||||
const inst_ty = sema.typeOf(inst);
|
||||
try sema.resolveTypeFields(inst_ty);
|
||||
const target = mod.getTarget();
|
||||
// If the types are the same, we can return the operand.
|
||||
if (dest_ty.eql(inst_ty, mod))
|
||||
@ -29830,16 +29852,15 @@ fn beginComptimePtrLoad(
|
||||
fn bitCast(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
dest_ty_unresolved: Type,
|
||||
dest_ty: Type,
|
||||
inst: Air.Inst.Ref,
|
||||
inst_src: LazySrcLoc,
|
||||
operand_src: ?LazySrcLoc,
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const mod = sema.mod;
|
||||
const dest_ty = try sema.resolveTypeFields(dest_ty_unresolved);
|
||||
try sema.resolveTypeLayout(dest_ty);
|
||||
|
||||
const old_ty = try sema.resolveTypeFields(sema.typeOf(inst));
|
||||
const old_ty = sema.typeOf(inst);
|
||||
try sema.resolveTypeLayout(old_ty);
|
||||
|
||||
const dest_bits = dest_ty.bitSize(mod);
|
||||
@ -30042,8 +30063,8 @@ fn coerceEnumToUnion(
|
||||
|
||||
const union_obj = mod.typeToUnion(union_ty).?;
|
||||
const field = union_obj.fields.values()[field_index];
|
||||
const field_ty = try sema.resolveTypeFields(field.ty);
|
||||
if (field_ty.zigTypeTag(mod) == .NoReturn) {
|
||||
try sema.resolveTypeFields(field.ty);
|
||||
if (field.ty.zigTypeTag(mod) == .NoReturn) {
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(block, inst_src, "cannot initialize 'noreturn' field of union", .{});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
@ -30057,12 +30078,12 @@ fn coerceEnumToUnion(
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(msg);
|
||||
}
|
||||
const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse {
|
||||
const opv = (try sema.typeHasOnePossibleValue(field.ty)) orelse {
|
||||
const msg = msg: {
|
||||
const field_name = union_obj.fields.keys()[field_index];
|
||||
const msg = try sema.errMsg(block, inst_src, "coercion from enum '{}' to union '{}' must initialize '{}' field '{}'", .{
|
||||
inst_ty.fmt(sema.mod), union_ty.fmt(sema.mod),
|
||||
field_ty.fmt(sema.mod), field_name.fmt(ip),
|
||||
field.ty.fmt(sema.mod), field_name.fmt(ip),
|
||||
});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
|
||||
@ -30426,13 +30447,13 @@ fn coerceTupleToArrayPtrs(
|
||||
fn coerceTupleToStruct(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
dest_ty: Type,
|
||||
struct_ty: Type,
|
||||
inst: Air.Inst.Ref,
|
||||
inst_src: LazySrcLoc,
|
||||
) !Air.Inst.Ref {
|
||||
const mod = sema.mod;
|
||||
const ip = &mod.intern_pool;
|
||||
const struct_ty = try sema.resolveTypeFields(dest_ty);
|
||||
try sema.resolveTypeFields(struct_ty);
|
||||
|
||||
if (struct_ty.isTupleOrAnonStruct(mod)) {
|
||||
return sema.coerceTupleToTuple(block, struct_ty, inst, inst_src);
|
||||
@ -33728,6 +33749,10 @@ fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value {
|
||||
|
||||
pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {
|
||||
const mod = sema.mod;
|
||||
switch (mod.intern_pool.indexToKey(ty.toIntern())) {
|
||||
.simple_type => |simple_type| return sema.resolveSimpleType(simple_type),
|
||||
else => {},
|
||||
}
|
||||
switch (ty.zigTypeTag(mod)) {
|
||||
.Struct => return sema.resolveStructLayout(ty),
|
||||
.Union => return sema.resolveUnionLayout(ty),
|
||||
@ -33768,8 +33793,8 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {
|
||||
|
||||
fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
|
||||
const mod = sema.mod;
|
||||
const resolved_ty = try sema.resolveTypeFields(ty);
|
||||
if (mod.typeToStruct(resolved_ty)) |struct_obj| {
|
||||
try sema.resolveTypeFields(ty);
|
||||
if (mod.typeToStruct(ty)) |struct_obj| {
|
||||
switch (struct_obj.status) {
|
||||
.none, .have_field_types => {},
|
||||
.field_types_wip, .layout_wip => {
|
||||
@ -33805,9 +33830,9 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
|
||||
}
|
||||
|
||||
struct_obj.status = .have_layout;
|
||||
_ = try sema.resolveTypeRequiresComptime(resolved_ty);
|
||||
_ = try sema.resolveTypeRequiresComptime(ty);
|
||||
|
||||
if (struct_obj.assumed_runtime_bits and !(try sema.typeHasRuntimeBits(resolved_ty))) {
|
||||
if (struct_obj.assumed_runtime_bits and !(try sema.typeHasRuntimeBits(ty))) {
|
||||
const msg = try Module.ErrorMsg.create(
|
||||
sema.gpa,
|
||||
struct_obj.srcLoc(mod),
|
||||
@ -34019,8 +34044,8 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void
|
||||
|
||||
fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
|
||||
const mod = sema.mod;
|
||||
const resolved_ty = try sema.resolveTypeFields(ty);
|
||||
const union_obj = mod.typeToUnion(resolved_ty).?;
|
||||
try sema.resolveTypeFields(ty);
|
||||
const union_obj = mod.typeToUnion(ty).?;
|
||||
switch (union_obj.status) {
|
||||
.none, .have_field_types => {},
|
||||
.field_types_wip, .layout_wip => {
|
||||
@ -34051,9 +34076,9 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
|
||||
};
|
||||
}
|
||||
union_obj.status = .have_layout;
|
||||
_ = try sema.resolveTypeRequiresComptime(resolved_ty);
|
||||
_ = try sema.resolveTypeRequiresComptime(ty);
|
||||
|
||||
if (union_obj.assumed_runtime_bits and !(try sema.typeHasRuntimeBits(resolved_ty))) {
|
||||
if (union_obj.assumed_runtime_bits and !(try sema.typeHasRuntimeBits(ty))) {
|
||||
const msg = try Module.ErrorMsg.create(
|
||||
sema.gpa,
|
||||
union_obj.srcLoc(sema.mod),
|
||||
@ -34227,8 +34252,7 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
|
||||
const mod = sema.mod;
|
||||
switch (ty.zigTypeTag(mod)) {
|
||||
.Pointer => {
|
||||
const child_ty = try sema.resolveTypeFields(ty.childType(mod));
|
||||
return sema.resolveTypeFully(child_ty);
|
||||
return sema.resolveTypeFully(ty.childType(mod));
|
||||
},
|
||||
.Struct => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
|
||||
.struct_type => return sema.resolveStructFully(ty),
|
||||
@ -34237,6 +34261,7 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
|
||||
try sema.resolveTypeFully(field_ty.toType());
|
||||
}
|
||||
},
|
||||
.simple_type => |simple_type| try sema.resolveSimpleType(simple_type),
|
||||
else => {},
|
||||
},
|
||||
.Union => return sema.resolveUnionFully(ty),
|
||||
@ -34267,8 +34292,8 @@ fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void {
|
||||
try sema.resolveStructLayout(ty);
|
||||
|
||||
const mod = sema.mod;
|
||||
const resolved_ty = try sema.resolveTypeFields(ty);
|
||||
const struct_obj = mod.typeToStruct(resolved_ty).?;
|
||||
try sema.resolveTypeFields(ty);
|
||||
const struct_obj = mod.typeToStruct(ty).?;
|
||||
|
||||
switch (struct_obj.status) {
|
||||
.none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
|
||||
@ -34297,8 +34322,8 @@ fn resolveUnionFully(sema: *Sema, ty: Type) CompileError!void {
|
||||
try sema.resolveUnionLayout(ty);
|
||||
|
||||
const mod = sema.mod;
|
||||
const resolved_ty = try sema.resolveTypeFields(ty);
|
||||
const union_obj = mod.typeToUnion(resolved_ty).?;
|
||||
try sema.resolveTypeFields(ty);
|
||||
const union_obj = mod.typeToUnion(ty).?;
|
||||
switch (union_obj.status) {
|
||||
.none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
|
||||
.fully_resolved_wip, .fully_resolved => return,
|
||||
@ -34322,7 +34347,7 @@ fn resolveUnionFully(sema: *Sema, ty: Type) CompileError!void {
|
||||
_ = try sema.typeRequiresComptime(ty);
|
||||
}
|
||||
|
||||
pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
|
||||
pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!void {
|
||||
const mod = sema.mod;
|
||||
|
||||
switch (ty.toIntern()) {
|
||||
@ -34385,7 +34410,7 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
|
||||
.anyerror_void_error_union_type,
|
||||
.generic_poison_type,
|
||||
.empty_struct_type,
|
||||
=> return ty,
|
||||
=> {},
|
||||
|
||||
.undef => unreachable,
|
||||
.zero => unreachable,
|
||||
@ -34406,42 +34431,52 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
|
||||
.empty_struct => unreachable,
|
||||
.generic_poison => unreachable,
|
||||
|
||||
.type_info_type => return sema.getBuiltinType("Type"),
|
||||
.extern_options_type => return sema.getBuiltinType("ExternOptions"),
|
||||
.export_options_type => return sema.getBuiltinType("ExportOptions"),
|
||||
.atomic_order_type => return sema.getBuiltinType("AtomicOrder"),
|
||||
.atomic_rmw_op_type => return sema.getBuiltinType("AtomicRmwOp"),
|
||||
.calling_convention_type => return sema.getBuiltinType("CallingConvention"),
|
||||
.address_space_type => return sema.getBuiltinType("AddressSpace"),
|
||||
.float_mode_type => return sema.getBuiltinType("FloatMode"),
|
||||
.reduce_op_type => return sema.getBuiltinType("ReduceOp"),
|
||||
.call_modifier_type => return sema.getBuiltinType("CallModifier"),
|
||||
.prefetch_options_type => return sema.getBuiltinType("PrefetchOptions"),
|
||||
|
||||
_ => switch (mod.intern_pool.items.items(.tag)[@intFromEnum(ty.toIntern())]) {
|
||||
else => switch (mod.intern_pool.items.items(.tag)[@intFromEnum(ty.toIntern())]) {
|
||||
.type_struct,
|
||||
.type_struct_ns,
|
||||
.type_union_tagged,
|
||||
.type_union_untagged,
|
||||
.type_union_safety,
|
||||
.simple_type,
|
||||
=> switch (mod.intern_pool.indexToKey(ty.toIntern())) {
|
||||
.struct_type => |struct_type| {
|
||||
const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return ty;
|
||||
const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return;
|
||||
try sema.resolveTypeFieldsStruct(ty, struct_obj);
|
||||
return ty;
|
||||
},
|
||||
.union_type => |union_type| {
|
||||
const union_obj = mod.unionPtr(union_type.index);
|
||||
try sema.resolveTypeFieldsUnion(ty, union_obj);
|
||||
return ty;
|
||||
},
|
||||
.simple_type => |simple_type| try sema.resolveSimpleType(simple_type),
|
||||
else => unreachable,
|
||||
},
|
||||
else => return ty,
|
||||
else => {},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Fully resolves a simple type. This is usually a nop, but for builtin types with
|
||||
/// special InternPool indices (such as std.builtin.Type) it will analyze and fully
|
||||
/// resolve the container type.
|
||||
fn resolveSimpleType(sema: *Sema, simple_type: InternPool.SimpleType) CompileError!void {
|
||||
const builtin_type_name: []const u8 = switch (simple_type) {
|
||||
.atomic_order => "AtomicOrder",
|
||||
.atomic_rmw_op => "AtomicRmwOp",
|
||||
.calling_convention => "CallingConvention",
|
||||
.address_space => "AddressSpace",
|
||||
.float_mode => "FloatMode",
|
||||
.reduce_op => "ReduceOp",
|
||||
.call_modifier => "CallModifer",
|
||||
.prefetch_options => "PrefetchOptions",
|
||||
.export_options => "ExportOptions",
|
||||
.extern_options => "ExternOptions",
|
||||
.type_info => "Type",
|
||||
else => return,
|
||||
};
|
||||
// This will fully resolve the type.
|
||||
_ = try sema.getBuiltinType(builtin_type_name);
|
||||
}
|
||||
|
||||
fn resolveTypeFieldsStruct(
|
||||
sema: *Sema,
|
||||
ty: Type,
|
||||
@ -35784,7 +35819,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||
},
|
||||
|
||||
.struct_type => |struct_type| {
|
||||
const resolved_ty = try sema.resolveTypeFields(ty);
|
||||
try sema.resolveTypeFields(ty);
|
||||
if (mod.structPtrUnwrap(struct_type.index)) |s| {
|
||||
const field_vals = try sema.arena.alloc(InternPool.Index, s.fields.count());
|
||||
for (field_vals, s.fields.values(), 0..) |*field_val, field, i| {
|
||||
@ -35792,14 +35827,14 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||
field_val.* = field.default_val;
|
||||
continue;
|
||||
}
|
||||
if (field.ty.eql(resolved_ty, sema.mod)) {
|
||||
if (field.ty.eql(ty, sema.mod)) {
|
||||
const msg = try Module.ErrorMsg.create(
|
||||
sema.gpa,
|
||||
s.srcLoc(sema.mod),
|
||||
"struct '{}' depends on itself",
|
||||
.{ty.fmt(sema.mod)},
|
||||
);
|
||||
try sema.addFieldErrNote(resolved_ty, i, msg, "while checking this field", .{});
|
||||
try sema.addFieldErrNote(ty, i, msg, "while checking this field", .{});
|
||||
return sema.failWithOwnedErrorMsg(msg);
|
||||
}
|
||||
if (try sema.typeHasOnePossibleValue(field.ty)) |field_opv| {
|
||||
@ -35837,7 +35872,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||
},
|
||||
|
||||
.union_type => |union_type| {
|
||||
const resolved_ty = try sema.resolveTypeFields(ty);
|
||||
try sema.resolveTypeFields(ty);
|
||||
const union_obj = mod.unionPtr(union_type.index);
|
||||
const tag_val = (try sema.typeHasOnePossibleValue(union_obj.tag_ty)) orelse
|
||||
return null;
|
||||
@ -35847,20 +35882,20 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||
return only.toValue();
|
||||
}
|
||||
const only_field = fields[0];
|
||||
if (only_field.ty.eql(resolved_ty, sema.mod)) {
|
||||
if (only_field.ty.eql(ty, sema.mod)) {
|
||||
const msg = try Module.ErrorMsg.create(
|
||||
sema.gpa,
|
||||
union_obj.srcLoc(sema.mod),
|
||||
"union '{}' depends on itself",
|
||||
.{ty.fmt(sema.mod)},
|
||||
);
|
||||
try sema.addFieldErrNote(resolved_ty, 0, msg, "while checking this field", .{});
|
||||
try sema.addFieldErrNote(ty, 0, msg, "while checking this field", .{});
|
||||
return sema.failWithOwnedErrorMsg(msg);
|
||||
}
|
||||
const val_val = (try sema.typeHasOnePossibleValue(only_field.ty)) orelse
|
||||
return null;
|
||||
const only = try mod.intern(.{ .un = .{
|
||||
.ty = resolved_ty.toIntern(),
|
||||
.ty = ty.toIntern(),
|
||||
.tag = tag_val.toIntern(),
|
||||
.val = val_val.toIntern(),
|
||||
} });
|
||||
@ -36430,12 +36465,12 @@ pub fn fnHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {
|
||||
fn unionFieldIndex(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
unresolved_union_ty: Type,
|
||||
union_ty: Type,
|
||||
field_name: InternPool.NullTerminatedString,
|
||||
field_src: LazySrcLoc,
|
||||
) !u32 {
|
||||
const mod = sema.mod;
|
||||
const union_ty = try sema.resolveTypeFields(unresolved_union_ty);
|
||||
try sema.resolveTypeFields(union_ty);
|
||||
const union_obj = mod.typeToUnion(union_ty).?;
|
||||
const field_index_usize = union_obj.fields.getIndex(field_name) orelse
|
||||
return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name);
|
||||
@ -36445,12 +36480,12 @@ fn unionFieldIndex(
|
||||
fn structFieldIndex(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
unresolved_struct_ty: Type,
|
||||
struct_ty: Type,
|
||||
field_name: InternPool.NullTerminatedString,
|
||||
field_src: LazySrcLoc,
|
||||
) !u32 {
|
||||
const mod = sema.mod;
|
||||
const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);
|
||||
try sema.resolveTypeFields(struct_ty);
|
||||
if (struct_ty.isAnonStruct(mod)) {
|
||||
return sema.anonStructFieldIndex(block, struct_ty, field_name, field_src);
|
||||
} else {
|
||||
|
||||
@ -3134,17 +3134,6 @@ pub const Object = struct {
|
||||
.null_type,
|
||||
.undefined_type,
|
||||
.enum_literal_type,
|
||||
.atomic_order_type,
|
||||
.atomic_rmw_op_type,
|
||||
.calling_convention_type,
|
||||
.address_space_type,
|
||||
.float_mode_type,
|
||||
.reduce_op_type,
|
||||
.call_modifier_type,
|
||||
.prefetch_options_type,
|
||||
.export_options_type,
|
||||
.extern_options_type,
|
||||
.type_info_type,
|
||||
=> unreachable,
|
||||
.manyptr_u8_type,
|
||||
.manyptr_const_u8_type,
|
||||
|
||||
@ -7,5 +7,5 @@ comptime {
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :3:21: error: expected type 'builtin.GlobalLinkage', found 'u32'
|
||||
// :3:51: error: expected type 'builtin.GlobalLinkage', found 'u32'
|
||||
// :?:?: note: enum declared here
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user