mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 21:08:36 +00:00
stage2: move most simple types to InternPool
This commit is contained in:
parent
bcd4bb8afb
commit
836d8a1f64
@ -1333,7 +1333,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index, ip: InternPool) Type {
|
||||
.ret_load,
|
||||
.unreach,
|
||||
.trap,
|
||||
=> return Type.initTag(.noreturn),
|
||||
=> return Type.noreturn,
|
||||
|
||||
.breakpoint,
|
||||
.dbg_stmt,
|
||||
@ -1370,7 +1370,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index, ip: InternPool) Type {
|
||||
.wasm_memory_grow => return Type.i32,
|
||||
.wasm_memory_size => return Type.u32,
|
||||
|
||||
.bool_to_int => return Type.initTag(.u1),
|
||||
.bool_to_int => return Type.u1,
|
||||
|
||||
.tag_name, .error_name => return Type.initTag(.const_slice_u8_sentinel_0),
|
||||
|
||||
|
||||
@ -1005,7 +1005,7 @@ pub const Struct = struct {
|
||||
/// If the layout is packed, this is the backing integer type of the packed struct.
|
||||
/// Whether zig chooses this type or the user specifies it, it is stored here.
|
||||
/// This will be set to the noreturn type until status is `have_layout`.
|
||||
backing_int_ty: Type = Type.initTag(.noreturn),
|
||||
backing_int_ty: Type = Type.noreturn,
|
||||
status: enum {
|
||||
none,
|
||||
field_types_wip,
|
||||
@ -1705,31 +1705,34 @@ pub const Fn = struct {
|
||||
is_resolved: bool = false,
|
||||
|
||||
pub fn addErrorSet(self: *InferredErrorSet, gpa: Allocator, err_set_ty: Type) !void {
|
||||
switch (err_set_ty.tag()) {
|
||||
.error_set => {
|
||||
const names = err_set_ty.castTag(.error_set).?.data.names.keys();
|
||||
for (names) |name| {
|
||||
try self.errors.put(gpa, name, {});
|
||||
}
|
||||
},
|
||||
.error_set_single => {
|
||||
const name = err_set_ty.castTag(.error_set_single).?.data;
|
||||
try self.errors.put(gpa, name, {});
|
||||
},
|
||||
.error_set_inferred => {
|
||||
const ies = err_set_ty.castTag(.error_set_inferred).?.data;
|
||||
try self.inferred_error_sets.put(gpa, ies, {});
|
||||
},
|
||||
.error_set_merged => {
|
||||
const names = err_set_ty.castTag(.error_set_merged).?.data.keys();
|
||||
for (names) |name| {
|
||||
try self.errors.put(gpa, name, {});
|
||||
}
|
||||
},
|
||||
.anyerror => {
|
||||
switch (err_set_ty.ip_index) {
|
||||
.anyerror_type => {
|
||||
self.is_anyerror = true;
|
||||
},
|
||||
else => unreachable,
|
||||
.none => switch (err_set_ty.tag()) {
|
||||
.error_set => {
|
||||
const names = err_set_ty.castTag(.error_set).?.data.names.keys();
|
||||
for (names) |name| {
|
||||
try self.errors.put(gpa, name, {});
|
||||
}
|
||||
},
|
||||
.error_set_single => {
|
||||
const name = err_set_ty.castTag(.error_set_single).?.data;
|
||||
try self.errors.put(gpa, name, {});
|
||||
},
|
||||
.error_set_inferred => {
|
||||
const ies = err_set_ty.castTag(.error_set_inferred).?.data;
|
||||
try self.inferred_error_sets.put(gpa, ies, {});
|
||||
},
|
||||
.error_set_merged => {
|
||||
const names = err_set_ty.castTag(.error_set_merged).?.data.keys();
|
||||
for (names) |name| {
|
||||
try self.errors.put(gpa, name, {});
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
else => @panic("TODO"),
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -4566,7 +4569,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
|
||||
const struct_obj = try new_decl_arena_allocator.create(Module.Struct);
|
||||
const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj);
|
||||
const struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty);
|
||||
const ty_ty = comptime Type.initTag(.type);
|
||||
const ty_ty = comptime Type.type;
|
||||
struct_obj.* = .{
|
||||
.owner_decl = undefined, // set below
|
||||
.fields = .{},
|
||||
|
||||
509
src/Sema.zig
509
src/Sema.zig
@ -1776,7 +1776,7 @@ fn analyzeAsType(
|
||||
src: LazySrcLoc,
|
||||
air_inst: Air.Inst.Ref,
|
||||
) !Type {
|
||||
const wanted_type = Type.initTag(.type);
|
||||
const wanted_type = Type.type;
|
||||
const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);
|
||||
const val = try sema.resolveConstValue(block, src, coerced_inst, "types must be comptime-known");
|
||||
const ty = val.toType();
|
||||
@ -3132,7 +3132,7 @@ fn zirUnionDecl(
|
||||
errdefer mod.abortAnonDecl(new_decl_index);
|
||||
union_obj.* = .{
|
||||
.owner_decl = new_decl_index,
|
||||
.tag_ty = Type.initTag(.null),
|
||||
.tag_ty = Type.null,
|
||||
.fields = .{},
|
||||
.zir_index = inst,
|
||||
.layout = small.layout,
|
||||
@ -6362,7 +6362,7 @@ fn zirCall(
|
||||
if (arg_index >= fn_params_len)
|
||||
break :inst Air.Inst.Ref.var_args_param_type;
|
||||
|
||||
if (func_ty_info.param_types[arg_index].tag() == .generic_poison)
|
||||
if (func_ty_info.param_types[arg_index].isGenericPoison())
|
||||
break :inst Air.Inst.Ref.generic_poison_type;
|
||||
|
||||
break :inst try sema.addType(func_ty_info.param_types[arg_index]);
|
||||
@ -8175,7 +8175,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
|
||||
return sema.fail(block, rhs_src, "expected error set type, found '{}'", .{rhs_ty.fmt(sema.mod)});
|
||||
|
||||
// Anything merged with anyerror is anyerror.
|
||||
if (lhs_ty.tag() == .anyerror or rhs_ty.tag() == .anyerror) {
|
||||
if (lhs_ty.ip_index == .anyerror_type or rhs_ty.ip_index == .anyerror_type) {
|
||||
return Air.Inst.Ref.anyerror_type;
|
||||
}
|
||||
|
||||
@ -8206,7 +8206,7 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
|
||||
const duped_name = try sema.arena.dupe(u8, inst_data.get(sema.code));
|
||||
return sema.addConstant(
|
||||
Type.initTag(.enum_literal),
|
||||
.{ .ip_index = .enum_literal_type, .legacy = undefined },
|
||||
try Value.Tag.enum_literal.create(sema.arena, duped_name),
|
||||
);
|
||||
}
|
||||
@ -8503,6 +8503,7 @@ fn analyzeErrUnionPayload(
|
||||
operand_src: LazySrcLoc,
|
||||
safety_check: bool,
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const mod = sema.mod;
|
||||
const payload_ty = err_union_ty.errorUnionPayload();
|
||||
if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| {
|
||||
if (val.getError()) |name| {
|
||||
@ -8516,7 +8517,7 @@ fn analyzeErrUnionPayload(
|
||||
|
||||
// If the error set has no fields then no safety check is needed.
|
||||
if (safety_check and block.wantSafety() and
|
||||
!err_union_ty.errorUnionSet().errorSetIsEmpty())
|
||||
!err_union_ty.errorUnionSet().errorSetIsEmpty(mod))
|
||||
{
|
||||
try sema.panicUnwrapError(block, operand, .unwrap_errunion_err, .is_non_err);
|
||||
}
|
||||
@ -8602,7 +8603,7 @@ fn analyzeErrUnionPayloadPtr(
|
||||
|
||||
// If the error set has no fields then no safety check is needed.
|
||||
if (safety_check and block.wantSafety() and
|
||||
!err_union_ty.errorUnionSet().errorSetIsEmpty())
|
||||
!err_union_ty.errorUnionSet().errorSetIsEmpty(mod))
|
||||
{
|
||||
try sema.panicUnwrapError(block, operand, .unwrap_errunion_err_ptr, .is_non_err_ptr);
|
||||
}
|
||||
@ -8701,7 +8702,7 @@ fn zirFunc(
|
||||
break :blk ret_ty;
|
||||
} else |err| switch (err) {
|
||||
error.GenericPoison => {
|
||||
break :blk Type.initTag(.generic_poison);
|
||||
break :blk Type.generic_poison;
|
||||
},
|
||||
else => |e| return e,
|
||||
}
|
||||
@ -8778,7 +8779,7 @@ fn resolveGenericBody(
|
||||
};
|
||||
switch (err) {
|
||||
error.GenericPoison => {
|
||||
if (dest_ty.tag() == .type) {
|
||||
if (dest_ty.ip_index == .type_type) {
|
||||
return Value.initTag(.generic_poison_type);
|
||||
} else {
|
||||
return Value.initTag(.generic_poison);
|
||||
@ -9319,7 +9320,7 @@ fn zirParam(
|
||||
// We result the param instruction with a poison value and
|
||||
// insert an anytype parameter.
|
||||
try block.params.append(sema.gpa, .{
|
||||
.ty = Type.initTag(.generic_poison),
|
||||
.ty = Type.generic_poison,
|
||||
.is_comptime = comptime_syntax,
|
||||
.name = param_name,
|
||||
});
|
||||
@ -9340,7 +9341,7 @@ fn zirParam(
|
||||
// We result the param instruction with a poison value and
|
||||
// insert an anytype parameter.
|
||||
try block.params.append(sema.gpa, .{
|
||||
.ty = Type.initTag(.generic_poison),
|
||||
.ty = Type.generic_poison,
|
||||
.is_comptime = comptime_syntax,
|
||||
.name = param_name,
|
||||
});
|
||||
@ -9438,7 +9439,7 @@ fn zirParamAnytype(
|
||||
// We are evaluating a generic function without any comptime args provided.
|
||||
|
||||
try block.params.append(sema.gpa, .{
|
||||
.ty = Type.initTag(.generic_poison),
|
||||
.ty = Type.generic_poison,
|
||||
.is_comptime = comptime_syntax,
|
||||
.name = param_name,
|
||||
});
|
||||
@ -18877,7 +18878,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
|
||||
},
|
||||
.ErrorSet => {
|
||||
const payload_val = union_val.val.optionalValue(mod) orelse
|
||||
return sema.addType(Type.initTag(.anyerror));
|
||||
return sema.addType(Type.anyerror);
|
||||
const slice_val = payload_val.castTag(.slice).?.data;
|
||||
|
||||
const len = try sema.usizeCast(block, src, slice_val.len.toUnsignedInt(mod));
|
||||
@ -19150,7 +19151,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
|
||||
errdefer mod.abortAnonDecl(new_decl_index);
|
||||
union_obj.* = .{
|
||||
.owner_decl = new_decl_index,
|
||||
.tag_ty = Type.initTag(.null),
|
||||
.tag_ty = Type.null,
|
||||
.fields = .{},
|
||||
.zir_index = inst,
|
||||
.layout = layout,
|
||||
@ -22697,7 +22698,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
||||
extra_index += 1;
|
||||
const ret_ty_tv = sema.resolveInstConst(block, ret_src, ret_ty_ref, "return type must be comptime-known") catch |err| switch (err) {
|
||||
error.GenericPoison => {
|
||||
break :blk Type.initTag(.generic_poison);
|
||||
break :blk Type.generic_poison;
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
@ -23022,7 +23023,7 @@ fn zirBuiltinExtern(
|
||||
new_decl.src_line = sema.owner_decl.src_line;
|
||||
// We only access this decl through the decl_ref with the correct type created
|
||||
// below, so this type doesn't matter
|
||||
new_decl.ty = Type.Tag.init(.anyopaque);
|
||||
new_decl.ty = Type.anyopaque;
|
||||
new_decl.val = try Value.Tag.variable.create(new_decl_arena_allocator, new_var);
|
||||
new_decl.@"align" = 0;
|
||||
new_decl.@"linksection" = null;
|
||||
@ -24380,9 +24381,8 @@ fn fieldCallBind(
|
||||
decl_type.fnParamLen() >= 1)
|
||||
{
|
||||
const first_param_type = decl_type.fnParamType(0);
|
||||
const first_param_tag = first_param_type.tag();
|
||||
// zig fmt: off
|
||||
if (first_param_tag == .generic_poison or (
|
||||
if (first_param_type.isGenericPoison() or (
|
||||
first_param_type.zigTypeTag(mod) == .Pointer and
|
||||
(first_param_type.ptrSize() == .One or
|
||||
first_param_type.ptrSize() == .C) and
|
||||
@ -25535,10 +25535,7 @@ fn coerceExtra(
|
||||
inst_src: LazySrcLoc,
|
||||
opts: CoerceOpts,
|
||||
) CoersionError!Air.Inst.Ref {
|
||||
switch (dest_ty_unresolved.tag()) {
|
||||
.generic_poison => return inst,
|
||||
else => {},
|
||||
}
|
||||
if (dest_ty_unresolved.isGenericPoison()) return inst;
|
||||
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));
|
||||
@ -25577,7 +25574,8 @@ fn coerceExtra(
|
||||
|
||||
// cast from ?*T and ?[*]T to ?*anyopaque
|
||||
// but don't do it if the source type is a double pointer
|
||||
if (dest_ty.isPtrLikeOptional(mod) and dest_ty.elemType2(mod).tag() == .anyopaque and
|
||||
if (dest_ty.isPtrLikeOptional(mod) and
|
||||
dest_ty.elemType2(mod).ip_index == .anyopaque_type and
|
||||
inst_ty.isPtrAtRuntime(mod))
|
||||
anyopaque_check: {
|
||||
if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :optional;
|
||||
@ -25715,7 +25713,7 @@ fn coerceExtra(
|
||||
|
||||
// cast from *T and [*]T to *anyopaque
|
||||
// but don't do it if the source type is a double pointer
|
||||
if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag(mod) == .Pointer) to_anyopaque: {
|
||||
if (dest_info.pointee_type.ip_index == .anyopaque_type and inst_ty.zigTypeTag(mod) == .Pointer) to_anyopaque: {
|
||||
if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;
|
||||
const elem_ty = inst_ty.elemType2(mod);
|
||||
if (elem_ty.zigTypeTag(mod) == .Pointer or elem_ty.isPtrLikeOptional(mod)) {
|
||||
@ -26759,6 +26757,8 @@ fn coerceInMemoryAllowedErrorSets(
|
||||
dest_src: LazySrcLoc,
|
||||
src_src: LazySrcLoc,
|
||||
) !InMemoryCoercionResult {
|
||||
const mod = sema.mod;
|
||||
|
||||
// Coercion to `anyerror`. Note that this check can return false negatives
|
||||
// in case the error sets did not get resolved.
|
||||
if (dest_ty.isAnyError()) {
|
||||
@ -26769,36 +26769,41 @@ fn coerceInMemoryAllowedErrorSets(
|
||||
const dst_ies = dst_payload.data;
|
||||
// We will make an effort to return `ok` without resolving either error set, to
|
||||
// avoid unnecessary "unable to resolve error set" dependency loop errors.
|
||||
switch (src_ty.tag()) {
|
||||
.error_set_inferred => {
|
||||
// If both are inferred error sets of functions, and
|
||||
// the dest includes the source function, the coercion is OK.
|
||||
// This check is important because it works without forcing a full resolution
|
||||
// of inferred error sets.
|
||||
const src_ies = src_ty.castTag(.error_set_inferred).?.data;
|
||||
switch (src_ty.ip_index) {
|
||||
.none => switch (src_ty.tag()) {
|
||||
.error_set_inferred => {
|
||||
// If both are inferred error sets of functions, and
|
||||
// the dest includes the source function, the coercion is OK.
|
||||
// This check is important because it works without forcing a full resolution
|
||||
// of inferred error sets.
|
||||
const src_ies = src_ty.castTag(.error_set_inferred).?.data;
|
||||
|
||||
if (dst_ies.inferred_error_sets.contains(src_ies)) {
|
||||
return .ok;
|
||||
}
|
||||
if (dst_ies.inferred_error_sets.contains(src_ies)) {
|
||||
return .ok;
|
||||
}
|
||||
},
|
||||
.error_set_single => {
|
||||
const name = src_ty.castTag(.error_set_single).?.data;
|
||||
if (dst_ies.errors.contains(name)) return .ok;
|
||||
},
|
||||
.error_set_merged => {
|
||||
const names = src_ty.castTag(.error_set_merged).?.data.keys();
|
||||
for (names) |name| {
|
||||
if (!dst_ies.errors.contains(name)) break;
|
||||
} else return .ok;
|
||||
},
|
||||
.error_set => {
|
||||
const names = src_ty.castTag(.error_set).?.data.names.keys();
|
||||
for (names) |name| {
|
||||
if (!dst_ies.errors.contains(name)) break;
|
||||
} else return .ok;
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
.error_set_single => {
|
||||
const name = src_ty.castTag(.error_set_single).?.data;
|
||||
if (dst_ies.errors.contains(name)) return .ok;
|
||||
.anyerror_type => {},
|
||||
else => switch (mod.intern_pool.indexToKey(src_ty.ip_index)) {
|
||||
else => @panic("TODO"),
|
||||
},
|
||||
.error_set_merged => {
|
||||
const names = src_ty.castTag(.error_set_merged).?.data.keys();
|
||||
for (names) |name| {
|
||||
if (!dst_ies.errors.contains(name)) break;
|
||||
} else return .ok;
|
||||
},
|
||||
.error_set => {
|
||||
const names = src_ty.castTag(.error_set).?.data.names.keys();
|
||||
for (names) |name| {
|
||||
if (!dst_ies.errors.contains(name)) break;
|
||||
} else return .ok;
|
||||
},
|
||||
.anyerror => {},
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
if (dst_ies.func == sema.owner_func) {
|
||||
@ -26818,79 +26823,87 @@ fn coerceInMemoryAllowedErrorSets(
|
||||
var missing_error_buf = std.ArrayList([]const u8).init(sema.gpa);
|
||||
defer missing_error_buf.deinit();
|
||||
|
||||
switch (src_ty.tag()) {
|
||||
.error_set_inferred => {
|
||||
const src_data = src_ty.castTag(.error_set_inferred).?.data;
|
||||
switch (src_ty.ip_index) {
|
||||
.none => switch (src_ty.tag()) {
|
||||
.error_set_inferred => {
|
||||
const src_data = src_ty.castTag(.error_set_inferred).?.data;
|
||||
|
||||
try sema.resolveInferredErrorSet(block, src_src, src_data);
|
||||
// src anyerror status might have changed after the resolution.
|
||||
if (src_ty.isAnyError()) {
|
||||
// dest_ty.isAnyError() == true is already checked for at this point.
|
||||
return .from_anyerror;
|
||||
}
|
||||
|
||||
for (src_data.errors.keys()) |key| {
|
||||
if (!dest_ty.errorSetHasField(key)) {
|
||||
try missing_error_buf.append(key);
|
||||
try sema.resolveInferredErrorSet(block, src_src, src_data);
|
||||
// src anyerror status might have changed after the resolution.
|
||||
if (src_ty.isAnyError()) {
|
||||
// dest_ty.isAnyError() == true is already checked for at this point.
|
||||
return .from_anyerror;
|
||||
}
|
||||
}
|
||||
|
||||
if (missing_error_buf.items.len != 0) {
|
||||
return InMemoryCoercionResult{
|
||||
.missing_error = try sema.arena.dupe([]const u8, missing_error_buf.items),
|
||||
};
|
||||
}
|
||||
for (src_data.errors.keys()) |key| {
|
||||
if (!dest_ty.errorSetHasField(key)) {
|
||||
try missing_error_buf.append(key);
|
||||
}
|
||||
}
|
||||
|
||||
if (missing_error_buf.items.len != 0) {
|
||||
return InMemoryCoercionResult{
|
||||
.missing_error = try sema.arena.dupe([]const u8, missing_error_buf.items),
|
||||
};
|
||||
}
|
||||
|
||||
return .ok;
|
||||
},
|
||||
.error_set_single => {
|
||||
const name = src_ty.castTag(.error_set_single).?.data;
|
||||
if (dest_ty.errorSetHasField(name)) {
|
||||
return .ok;
|
||||
}
|
||||
const list = try sema.arena.alloc([]const u8, 1);
|
||||
list[0] = name;
|
||||
return InMemoryCoercionResult{ .missing_error = list };
|
||||
},
|
||||
.error_set_merged => {
|
||||
const names = src_ty.castTag(.error_set_merged).?.data.keys();
|
||||
for (names) |name| {
|
||||
if (!dest_ty.errorSetHasField(name)) {
|
||||
try missing_error_buf.append(name);
|
||||
},
|
||||
.error_set_single => {
|
||||
const name = src_ty.castTag(.error_set_single).?.data;
|
||||
if (dest_ty.errorSetHasField(name)) {
|
||||
return .ok;
|
||||
}
|
||||
}
|
||||
|
||||
if (missing_error_buf.items.len != 0) {
|
||||
return InMemoryCoercionResult{
|
||||
.missing_error = try sema.arena.dupe([]const u8, missing_error_buf.items),
|
||||
};
|
||||
}
|
||||
|
||||
return .ok;
|
||||
},
|
||||
.error_set => {
|
||||
const names = src_ty.castTag(.error_set).?.data.names.keys();
|
||||
for (names) |name| {
|
||||
if (!dest_ty.errorSetHasField(name)) {
|
||||
try missing_error_buf.append(name);
|
||||
const list = try sema.arena.alloc([]const u8, 1);
|
||||
list[0] = name;
|
||||
return InMemoryCoercionResult{ .missing_error = list };
|
||||
},
|
||||
.error_set_merged => {
|
||||
const names = src_ty.castTag(.error_set_merged).?.data.keys();
|
||||
for (names) |name| {
|
||||
if (!dest_ty.errorSetHasField(name)) {
|
||||
try missing_error_buf.append(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (missing_error_buf.items.len != 0) {
|
||||
return InMemoryCoercionResult{
|
||||
.missing_error = try sema.arena.dupe([]const u8, missing_error_buf.items),
|
||||
};
|
||||
}
|
||||
if (missing_error_buf.items.len != 0) {
|
||||
return InMemoryCoercionResult{
|
||||
.missing_error = try sema.arena.dupe([]const u8, missing_error_buf.items),
|
||||
};
|
||||
}
|
||||
|
||||
return .ok;
|
||||
},
|
||||
.anyerror => switch (dest_ty.tag()) {
|
||||
.error_set_inferred => unreachable, // Caught by dest_ty.isAnyError() above.
|
||||
.error_set_single, .error_set_merged, .error_set => return .from_anyerror,
|
||||
.anyerror => unreachable, // Filtered out above.
|
||||
return .ok;
|
||||
},
|
||||
.error_set => {
|
||||
const names = src_ty.castTag(.error_set).?.data.names.keys();
|
||||
for (names) |name| {
|
||||
if (!dest_ty.errorSetHasField(name)) {
|
||||
try missing_error_buf.append(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (missing_error_buf.items.len != 0) {
|
||||
return InMemoryCoercionResult{
|
||||
.missing_error = try sema.arena.dupe([]const u8, missing_error_buf.items),
|
||||
};
|
||||
}
|
||||
|
||||
return .ok;
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
else => unreachable,
|
||||
|
||||
.anyerror_type => switch (dest_ty.ip_index) {
|
||||
.none => switch (dest_ty.tag()) {
|
||||
.error_set_inferred => unreachable, // Caught by dest_ty.isAnyError() above.
|
||||
.error_set_single, .error_set_merged, .error_set => return .from_anyerror,
|
||||
else => unreachable,
|
||||
},
|
||||
.anyerror_type => unreachable, // Filtered out above.
|
||||
else => @panic("TODO"),
|
||||
},
|
||||
|
||||
else => @panic("TODO"),
|
||||
}
|
||||
|
||||
unreachable;
|
||||
@ -29355,42 +29368,49 @@ fn analyzeIsNonErrComptimeOnly(
|
||||
// exception if the error union error set is known to be empty,
|
||||
// we allow the comparison but always make it comptime-known.
|
||||
const set_ty = operand_ty.errorUnionSet();
|
||||
switch (set_ty.tag()) {
|
||||
.anyerror => {},
|
||||
.error_set_inferred => blk: {
|
||||
// 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.
|
||||
const ies = set_ty.castTag(.error_set_inferred).?.data;
|
||||
if (ies.is_anyerror) break :blk;
|
||||
if (ies.errors.count() != 0) break :blk;
|
||||
if (maybe_operand_val == null) {
|
||||
// Try to avoid resolving inferred error set if possible.
|
||||
switch (set_ty.ip_index) {
|
||||
.none => switch (set_ty.tag()) {
|
||||
.error_set_inferred => blk: {
|
||||
// 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.
|
||||
const ies = set_ty.castTag(.error_set_inferred).?.data;
|
||||
if (ies.is_anyerror) break :blk;
|
||||
if (ies.errors.count() != 0) break :blk;
|
||||
if (ies.is_anyerror) break :blk;
|
||||
for (ies.inferred_error_sets.keys()) |other_ies| {
|
||||
if (ies == other_ies) continue;
|
||||
try sema.resolveInferredErrorSet(block, src, other_ies);
|
||||
if (other_ies.is_anyerror) {
|
||||
ies.is_anyerror = true;
|
||||
ies.is_resolved = true;
|
||||
break :blk;
|
||||
}
|
||||
if (maybe_operand_val == null) {
|
||||
// Try to avoid resolving inferred error set if possible.
|
||||
if (ies.errors.count() != 0) break :blk;
|
||||
if (ies.is_anyerror) break :blk;
|
||||
for (ies.inferred_error_sets.keys()) |other_ies| {
|
||||
if (ies == other_ies) continue;
|
||||
try sema.resolveInferredErrorSet(block, src, other_ies);
|
||||
if (other_ies.is_anyerror) {
|
||||
ies.is_anyerror = true;
|
||||
ies.is_resolved = true;
|
||||
break :blk;
|
||||
}
|
||||
|
||||
if (other_ies.errors.count() != 0) break :blk;
|
||||
if (other_ies.errors.count() != 0) break :blk;
|
||||
}
|
||||
if (ies.func == sema.owner_func) {
|
||||
// We're checking the inferred errorset of the current function and none of
|
||||
// its child inferred error sets contained any errors meaning that any value
|
||||
// so far with this type can't contain errors either.
|
||||
return Air.Inst.Ref.bool_true;
|
||||
}
|
||||
try sema.resolveInferredErrorSet(block, src, ies);
|
||||
if (ies.is_anyerror) break :blk;
|
||||
if (ies.errors.count() == 0) return Air.Inst.Ref.bool_true;
|
||||
}
|
||||
if (ies.func == sema.owner_func) {
|
||||
// We're checking the inferred errorset of the current function and none of
|
||||
// its child inferred error sets contained any errors meaning that any value
|
||||
// so far with this type can't contain errors either.
|
||||
return Air.Inst.Ref.bool_true;
|
||||
}
|
||||
try sema.resolveInferredErrorSet(block, src, ies);
|
||||
if (ies.is_anyerror) break :blk;
|
||||
if (ies.errors.count() == 0) return Air.Inst.Ref.bool_true;
|
||||
}
|
||||
},
|
||||
else => if (set_ty.errorSetNames().len == 0) return Air.Inst.Ref.bool_true,
|
||||
},
|
||||
|
||||
.anyerror_type => {},
|
||||
|
||||
else => switch (mod.intern_pool.indexToKey(set_ty.ip_index)) {
|
||||
else => @panic("TODO"),
|
||||
},
|
||||
else => if (set_ty.errorSetNames().len == 0) return Air.Inst.Ref.bool_true,
|
||||
}
|
||||
|
||||
if (maybe_operand_val) |err_union| {
|
||||
@ -30308,43 +30328,48 @@ fn wrapErrorUnionSet(
|
||||
const inst_ty = sema.typeOf(inst);
|
||||
const dest_err_set_ty = dest_ty.errorUnionSet();
|
||||
if (try sema.resolveMaybeUndefVal(inst)) |val| {
|
||||
switch (dest_err_set_ty.tag()) {
|
||||
.anyerror => {},
|
||||
.error_set_single => ok: {
|
||||
const expected_name = val.castTag(.@"error").?.data.name;
|
||||
const n = dest_err_set_ty.castTag(.error_set_single).?.data;
|
||||
if (mem.eql(u8, expected_name, n)) break :ok;
|
||||
return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
|
||||
},
|
||||
.error_set => {
|
||||
const expected_name = val.castTag(.@"error").?.data.name;
|
||||
const error_set = dest_err_set_ty.castTag(.error_set).?.data;
|
||||
if (!error_set.names.contains(expected_name)) {
|
||||
return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
|
||||
}
|
||||
},
|
||||
.error_set_inferred => ok: {
|
||||
const expected_name = val.castTag(.@"error").?.data.name;
|
||||
const ies = dest_err_set_ty.castTag(.error_set_inferred).?.data;
|
||||
switch (dest_err_set_ty.ip_index) {
|
||||
.anyerror_type => {},
|
||||
|
||||
// We carefully do this in an order that avoids unnecessarily
|
||||
// resolving the destination error set type.
|
||||
if (ies.is_anyerror) break :ok;
|
||||
if (ies.errors.contains(expected_name)) break :ok;
|
||||
if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) {
|
||||
break :ok;
|
||||
}
|
||||
|
||||
return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
|
||||
},
|
||||
.error_set_merged => {
|
||||
const expected_name = val.castTag(.@"error").?.data.name;
|
||||
const error_set = dest_err_set_ty.castTag(.error_set_merged).?.data;
|
||||
if (!error_set.contains(expected_name)) {
|
||||
.none => switch (dest_err_set_ty.tag()) {
|
||||
.error_set_single => ok: {
|
||||
const expected_name = val.castTag(.@"error").?.data.name;
|
||||
const n = dest_err_set_ty.castTag(.error_set_single).?.data;
|
||||
if (mem.eql(u8, expected_name, n)) break :ok;
|
||||
return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
|
||||
}
|
||||
},
|
||||
.error_set => {
|
||||
const expected_name = val.castTag(.@"error").?.data.name;
|
||||
const error_set = dest_err_set_ty.castTag(.error_set).?.data;
|
||||
if (!error_set.names.contains(expected_name)) {
|
||||
return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
|
||||
}
|
||||
},
|
||||
.error_set_inferred => ok: {
|
||||
const expected_name = val.castTag(.@"error").?.data.name;
|
||||
const ies = dest_err_set_ty.castTag(.error_set_inferred).?.data;
|
||||
|
||||
// We carefully do this in an order that avoids unnecessarily
|
||||
// resolving the destination error set type.
|
||||
if (ies.is_anyerror) break :ok;
|
||||
if (ies.errors.contains(expected_name)) break :ok;
|
||||
if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) {
|
||||
break :ok;
|
||||
}
|
||||
|
||||
return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
|
||||
},
|
||||
.error_set_merged => {
|
||||
const expected_name = val.castTag(.@"error").?.data.name;
|
||||
const error_set = dest_err_set_ty.castTag(.error_set_merged).?.data;
|
||||
if (!error_set.contains(expected_name)) {
|
||||
return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
else => unreachable,
|
||||
|
||||
else => @panic("TODO"),
|
||||
}
|
||||
return sema.addConstant(dest_ty, val);
|
||||
}
|
||||
@ -30380,7 +30405,7 @@ fn resolvePeerTypes(
|
||||
) !Type {
|
||||
const mod = sema.mod;
|
||||
switch (instructions.len) {
|
||||
0 => return Type.initTag(.noreturn),
|
||||
0 => return Type.noreturn,
|
||||
1 => return sema.typeOf(instructions[0]),
|
||||
else => {},
|
||||
}
|
||||
@ -31445,24 +31470,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
|
||||
.i64,
|
||||
.u128,
|
||||
.i128,
|
||||
.anyopaque,
|
||||
.bool,
|
||||
.void,
|
||||
.anyerror,
|
||||
.noreturn,
|
||||
.@"anyframe",
|
||||
.null,
|
||||
.undefined,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.address_space,
|
||||
.float_mode,
|
||||
.reduce_op,
|
||||
.modifier,
|
||||
.prefetch_options,
|
||||
.export_options,
|
||||
.extern_options,
|
||||
|
||||
.manyptr_u8,
|
||||
.manyptr_const_u8,
|
||||
.manyptr_const_u8_sentinel_0,
|
||||
@ -31476,17 +31484,12 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
|
||||
.error_set_inferred,
|
||||
.error_set_merged,
|
||||
.@"opaque",
|
||||
.generic_poison,
|
||||
.array_u8,
|
||||
.array_u8_sentinel_0,
|
||||
.enum_simple,
|
||||
=> false,
|
||||
|
||||
.single_const_pointer_to_comptime_int,
|
||||
.type,
|
||||
.comptime_int,
|
||||
.enum_literal,
|
||||
.type_info,
|
||||
.function,
|
||||
=> true,
|
||||
|
||||
@ -31709,17 +31712,6 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
|
||||
try sema.resolveTypeFieldsUnion(ty, union_obj);
|
||||
return ty;
|
||||
},
|
||||
.type_info => return sema.getBuiltinType("Type"),
|
||||
.extern_options => return sema.getBuiltinType("ExternOptions"),
|
||||
.export_options => return sema.getBuiltinType("ExportOptions"),
|
||||
.atomic_order => return sema.getBuiltinType("AtomicOrder"),
|
||||
.atomic_rmw_op => return sema.getBuiltinType("AtomicRmwOp"),
|
||||
.calling_convention => return sema.getBuiltinType("CallingConvention"),
|
||||
.address_space => return sema.getBuiltinType("AddressSpace"),
|
||||
.float_mode => return sema.getBuiltinType("FloatMode"),
|
||||
.reduce_op => return sema.getBuiltinType("ReduceOp"),
|
||||
.modifier => return sema.getBuiltinType("CallModifier"),
|
||||
.prefetch_options => return sema.getBuiltinType("PrefetchOptions"),
|
||||
|
||||
else => return ty,
|
||||
},
|
||||
@ -31772,6 +31764,7 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
|
||||
.const_slice_u8_type,
|
||||
.anyerror_void_error_union_type,
|
||||
.generic_poison_type,
|
||||
.var_args_param_type,
|
||||
.empty_struct_type,
|
||||
=> return ty,
|
||||
|
||||
@ -31789,7 +31782,6 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
|
||||
.bool_false => unreachable,
|
||||
.empty_struct => unreachable,
|
||||
.generic_poison => unreachable,
|
||||
.var_args_param_type => unreachable,
|
||||
|
||||
.type_info_type => return sema.getBuiltinType("Type"),
|
||||
.extern_options_type => return sema.getBuiltinType("ExternOptions"),
|
||||
@ -32118,7 +32110,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
|
||||
return sema.failWithOwnedErrorMsg(msg);
|
||||
}
|
||||
gop.value_ptr.* = .{
|
||||
.ty = Type.initTag(.noreturn),
|
||||
.ty = Type.noreturn,
|
||||
.abi_align = 0,
|
||||
.default_val = Value.initTag(.unreachable_value),
|
||||
.is_comptime = is_comptime,
|
||||
@ -32552,7 +32544,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
|
||||
const field_ty: Type = if (!has_type)
|
||||
Type.void
|
||||
else if (field_type_ref == .none)
|
||||
Type.initTag(.noreturn)
|
||||
Type.noreturn
|
||||
else
|
||||
sema.resolveType(&block_scope, .unneeded, field_type_ref) catch |err| switch (err) {
|
||||
error.NeededSourceLocation => {
|
||||
@ -32956,7 +32948,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||
};
|
||||
|
||||
switch (ty.tag()) {
|
||||
.comptime_int,
|
||||
.u1,
|
||||
.u8,
|
||||
.i8,
|
||||
@ -32969,9 +32960,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||
.i64,
|
||||
.u128,
|
||||
.i128,
|
||||
.bool,
|
||||
.type,
|
||||
.anyerror,
|
||||
|
||||
.error_set_single,
|
||||
.error_set,
|
||||
.error_set_merged,
|
||||
@ -32984,28 +32973,14 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||
.const_slice_u8_sentinel_0,
|
||||
.const_slice,
|
||||
.mut_slice,
|
||||
.anyopaque,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
.enum_literal,
|
||||
.anyerror_void_error_union,
|
||||
.error_set_inferred,
|
||||
.@"opaque",
|
||||
.manyptr_u8,
|
||||
.manyptr_const_u8,
|
||||
.manyptr_const_u8_sentinel_0,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.address_space,
|
||||
.float_mode,
|
||||
.reduce_op,
|
||||
.modifier,
|
||||
.prefetch_options,
|
||||
.export_options,
|
||||
.extern_options,
|
||||
.type_info,
|
||||
.@"anyframe",
|
||||
.anyframe_T,
|
||||
.many_const_pointer,
|
||||
.many_mut_pointer,
|
||||
@ -33138,10 +33113,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||
},
|
||||
|
||||
.empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),
|
||||
.void => return Value.void,
|
||||
.noreturn => return Value.initTag(.unreachable_value),
|
||||
.null => return Value.null,
|
||||
.undefined => return Value.initTag(.undef),
|
||||
|
||||
.vector, .array, .array_u8 => {
|
||||
if (ty.arrayLen() == 0)
|
||||
@ -33154,7 +33125,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||
|
||||
.inferred_alloc_const => unreachable,
|
||||
.inferred_alloc_mut => unreachable,
|
||||
.generic_poison => return error.GenericPoison,
|
||||
}
|
||||
}
|
||||
|
||||
@ -33194,34 +33164,12 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {
|
||||
.i64 => return .i64_type,
|
||||
.u128 => return .u128_type,
|
||||
.i128 => return .i128_type,
|
||||
.anyopaque => return .anyopaque_type,
|
||||
.bool => return .bool_type,
|
||||
.void => return .void_type,
|
||||
.type => return .type_type,
|
||||
.anyerror => return .anyerror_type,
|
||||
.comptime_int => return .comptime_int_type,
|
||||
.noreturn => return .noreturn_type,
|
||||
.@"anyframe" => return .anyframe_type,
|
||||
.null => return .null_type,
|
||||
.undefined => return .undefined_type,
|
||||
.enum_literal => return .enum_literal_type,
|
||||
.atomic_order => return .atomic_order_type,
|
||||
.atomic_rmw_op => return .atomic_rmw_op_type,
|
||||
.calling_convention => return .calling_convention_type,
|
||||
.address_space => return .address_space_type,
|
||||
.float_mode => return .float_mode_type,
|
||||
.reduce_op => return .reduce_op_type,
|
||||
.modifier => return .call_modifier_type,
|
||||
.prefetch_options => return .prefetch_options_type,
|
||||
.export_options => return .export_options_type,
|
||||
.extern_options => return .extern_options_type,
|
||||
.type_info => return .type_info_type,
|
||||
|
||||
.manyptr_u8 => return .manyptr_u8_type,
|
||||
.manyptr_const_u8 => return .manyptr_const_u8_type,
|
||||
.single_const_pointer_to_comptime_int => return .single_const_pointer_to_comptime_int_type,
|
||||
.const_slice_u8 => return .const_slice_u8_type,
|
||||
.anyerror_void_error_union => return .anyerror_void_error_union_type,
|
||||
.generic_poison => return .generic_poison_type,
|
||||
else => {},
|
||||
}
|
||||
try sema.air_instructions.append(sema.gpa, .{
|
||||
@ -33658,22 +33606,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
|
||||
.i64,
|
||||
.u128,
|
||||
.i128,
|
||||
.anyopaque,
|
||||
.bool,
|
||||
.void,
|
||||
.anyerror,
|
||||
.noreturn,
|
||||
.@"anyframe",
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.address_space,
|
||||
.float_mode,
|
||||
.reduce_op,
|
||||
.modifier,
|
||||
.prefetch_options,
|
||||
.export_options,
|
||||
.extern_options,
|
||||
|
||||
.manyptr_u8,
|
||||
.manyptr_const_u8,
|
||||
.manyptr_const_u8_sentinel_0,
|
||||
@ -33687,19 +33620,12 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
|
||||
.error_set_inferred,
|
||||
.error_set_merged,
|
||||
.@"opaque",
|
||||
.generic_poison,
|
||||
.array_u8,
|
||||
.array_u8_sentinel_0,
|
||||
.enum_simple,
|
||||
=> false,
|
||||
|
||||
.single_const_pointer_to_comptime_int,
|
||||
.type,
|
||||
.comptime_int,
|
||||
.enum_literal,
|
||||
.null,
|
||||
.undefined,
|
||||
.type_info,
|
||||
.function,
|
||||
=> true,
|
||||
|
||||
@ -34476,17 +34402,6 @@ fn enumHasInt(sema: *Sema, ty: Type, int: Value) CompileError!bool {
|
||||
const tag_ty = try mod.intType(.unsigned, bits);
|
||||
return sema.intInRange(tag_ty, int, fields_len);
|
||||
},
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.address_space,
|
||||
.float_mode,
|
||||
.reduce_op,
|
||||
.modifier,
|
||||
.prefetch_options,
|
||||
.export_options,
|
||||
.extern_options,
|
||||
=> unreachable,
|
||||
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
@ -3071,7 +3071,7 @@ fn errUnionErr(
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const err_ty = error_union_ty.errorUnionSet();
|
||||
const payload_ty = error_union_ty.errorUnionPayload();
|
||||
if (err_ty.errorSetIsEmpty()) {
|
||||
if (err_ty.errorSetIsEmpty(mod)) {
|
||||
return MCValue{ .immediate = 0 };
|
||||
}
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||
@ -3151,7 +3151,7 @@ fn errUnionPayload(
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const err_ty = error_union_ty.errorUnionSet();
|
||||
const payload_ty = error_union_ty.errorUnionPayload();
|
||||
if (err_ty.errorSetIsEmpty()) {
|
||||
if (err_ty.errorSetIsEmpty(mod)) {
|
||||
return try error_union_bind.resolveToMcv(self);
|
||||
}
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||
@ -4905,9 +4905,10 @@ fn isErr(
|
||||
error_union_bind: ReadArg.Bind,
|
||||
error_union_ty: Type,
|
||||
) !MCValue {
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const error_type = error_union_ty.errorUnionSet();
|
||||
|
||||
if (error_type.errorSetIsEmpty()) {
|
||||
if (error_type.errorSetIsEmpty(mod)) {
|
||||
return MCValue{ .immediate = 0 }; // always false
|
||||
}
|
||||
|
||||
|
||||
@ -2047,7 +2047,7 @@ fn errUnionErr(
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const err_ty = error_union_ty.errorUnionSet();
|
||||
const payload_ty = error_union_ty.errorUnionPayload();
|
||||
if (err_ty.errorSetIsEmpty()) {
|
||||
if (err_ty.errorSetIsEmpty(mod)) {
|
||||
return MCValue{ .immediate = 0 };
|
||||
}
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||
@ -2124,7 +2124,7 @@ fn errUnionPayload(
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const err_ty = error_union_ty.errorUnionSet();
|
||||
const payload_ty = error_union_ty.errorUnionPayload();
|
||||
if (err_ty.errorSetIsEmpty()) {
|
||||
if (err_ty.errorSetIsEmpty(mod)) {
|
||||
return try error_union_bind.resolveToMcv(self);
|
||||
}
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||
@ -4882,9 +4882,10 @@ fn isErr(
|
||||
error_union_bind: ReadArg.Bind,
|
||||
error_union_ty: Type,
|
||||
) !MCValue {
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const error_type = error_union_ty.errorUnionSet();
|
||||
|
||||
if (error_type.errorSetIsEmpty()) {
|
||||
if (error_type.errorSetIsEmpty(mod)) {
|
||||
return MCValue{ .immediate = 0 }; // always false
|
||||
}
|
||||
|
||||
|
||||
@ -3530,7 +3530,7 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type)
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const err_ty = error_union_ty.errorUnionSet();
|
||||
const payload_ty = error_union_ty.errorUnionPayload();
|
||||
if (err_ty.errorSetIsEmpty()) {
|
||||
if (err_ty.errorSetIsEmpty(mod)) {
|
||||
return error_union_mcv;
|
||||
}
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||
|
||||
@ -1036,8 +1036,8 @@ fn genValtype(ty: Type, mod: *Module) u8 {
|
||||
/// Differently from `genValtype` this also allows `void` to create a block
|
||||
/// with no return type
|
||||
fn genBlockType(ty: Type, mod: *Module) u8 {
|
||||
return switch (ty.tag()) {
|
||||
.void, .noreturn => wasm.block_empty,
|
||||
return switch (ty.ip_index) {
|
||||
.void_type, .noreturn_type => wasm.block_empty,
|
||||
else => genValtype(ty, mod),
|
||||
};
|
||||
}
|
||||
@ -3948,7 +3948,7 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro
|
||||
const pl_ty = err_union_ty.errorUnionPayload();
|
||||
|
||||
const result = result: {
|
||||
if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {
|
||||
if (err_union_ty.errorUnionSet().errorSetIsEmpty(mod)) {
|
||||
switch (opcode) {
|
||||
.i32_ne => break :result WValue{ .imm32 = 0 },
|
||||
.i32_eq => break :result WValue{ .imm32 = 1 },
|
||||
@ -4013,7 +4013,7 @@ fn airUnwrapErrUnionError(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool)
|
||||
const payload_ty = err_ty.errorUnionPayload();
|
||||
|
||||
const result = result: {
|
||||
if (err_ty.errorUnionSet().errorSetIsEmpty()) {
|
||||
if (err_ty.errorUnionSet().errorSetIsEmpty(mod)) {
|
||||
break :result WValue{ .imm32 = 0 };
|
||||
}
|
||||
|
||||
@ -6214,7 +6214,7 @@ fn lowerTry(
|
||||
const pl_ty = err_union_ty.errorUnionPayload();
|
||||
const pl_has_bits = pl_ty.hasRuntimeBitsIgnoreComptime(mod);
|
||||
|
||||
if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) {
|
||||
if (!err_union_ty.errorUnionSet().errorSetIsEmpty(mod)) {
|
||||
// Block we can jump out of when error is not set
|
||||
try func.startBlock(.block, wasm.block_empty);
|
||||
|
||||
|
||||
@ -3624,7 +3624,7 @@ fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const operand = try self.resolveInst(ty_op.operand);
|
||||
|
||||
const result: MCValue = result: {
|
||||
if (err_ty.errorSetIsEmpty()) {
|
||||
if (err_ty.errorSetIsEmpty(mod)) {
|
||||
break :result MCValue{ .immediate = 0 };
|
||||
}
|
||||
|
||||
@ -5811,7 +5811,7 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air:
|
||||
switch (tag) {
|
||||
.not => {
|
||||
const limb_abi_size = @intCast(u16, @min(src_ty.abiSize(mod), 8));
|
||||
const int_info = if (src_ty.tag() == .bool)
|
||||
const int_info = if (src_ty.ip_index == .bool_type)
|
||||
std.builtin.Type.Int{ .signedness = .unsigned, .bits = 1 }
|
||||
else
|
||||
src_ty.intInfo(mod);
|
||||
@ -8716,7 +8716,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
|
||||
try self.asmRegisterRegister(.{ ._, .@"test" }, alias_reg, alias_reg);
|
||||
return .{ .eflags = .z };
|
||||
}
|
||||
assert(some_info.ty.tag() == .bool);
|
||||
assert(some_info.ty.ip_index == .bool_type);
|
||||
const opt_abi_size = @intCast(u32, opt_ty.abiSize(mod));
|
||||
try self.asmRegisterImmediate(
|
||||
.{ ._, .bt },
|
||||
@ -8808,7 +8808,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const err_type = ty.errorUnionSet();
|
||||
|
||||
if (err_type.errorSetIsEmpty()) {
|
||||
if (err_type.errorSetIsEmpty(mod)) {
|
||||
return MCValue{ .immediate = 0 }; // always false
|
||||
}
|
||||
|
||||
|
||||
@ -1508,7 +1508,7 @@ pub const DeclGen = struct {
|
||||
}
|
||||
if (fn_decl.val.castTag(.function)) |func_payload|
|
||||
if (func_payload.data.is_cold) try w.writeAll("zig_cold ");
|
||||
if (fn_info.return_type.tag() == .noreturn) try w.writeAll("zig_noreturn ");
|
||||
if (fn_info.return_type.ip_index == .noreturn_type) try w.writeAll("zig_noreturn ");
|
||||
|
||||
const trailing = try renderTypePrefix(
|
||||
dg.decl_index,
|
||||
@ -3783,7 +3783,7 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
const ty_op = f.air.instructions.items(.data)[inst].ty_op;
|
||||
const operand_ty = f.typeOf(ty_op.operand);
|
||||
const scalar_ty = operand_ty.scalarType(mod);
|
||||
if (scalar_ty.tag() != .bool) return try airUnBuiltinCall(f, inst, "not", .bits);
|
||||
if (scalar_ty.ip_index != .bool_type) return try airUnBuiltinCall(f, inst, "not", .bits);
|
||||
|
||||
const op = try f.resolveInst(ty_op.operand);
|
||||
try reap(f, inst, &.{ty_op.operand});
|
||||
@ -4292,7 +4292,7 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
const writer = f.object.writer();
|
||||
|
||||
const inst_ty = f.typeOfIndex(inst);
|
||||
const result = if (inst_ty.tag() != .void and !f.liveness.isUnused(inst))
|
||||
const result = if (inst_ty.ip_index != .void_type and !f.liveness.isUnused(inst))
|
||||
try f.allocLocal(inst, inst_ty)
|
||||
else
|
||||
.none;
|
||||
@ -4354,7 +4354,7 @@ fn lowerTry(
|
||||
const payload_ty = err_union_ty.errorUnionPayload();
|
||||
const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod);
|
||||
|
||||
if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) {
|
||||
if (!err_union_ty.errorUnionSet().errorSetIsEmpty(mod)) {
|
||||
try writer.writeAll("if (");
|
||||
if (!payload_has_bits) {
|
||||
if (is_ptr)
|
||||
@ -5549,7 +5549,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
if (!payload_ty.hasRuntimeBits(mod)) {
|
||||
try f.writeCValue(writer, operand, .Other);
|
||||
} else {
|
||||
if (!error_ty.errorSetIsEmpty())
|
||||
if (!error_ty.errorSetIsEmpty(mod))
|
||||
if (operand_is_ptr)
|
||||
try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
|
||||
else
|
||||
@ -5768,7 +5768,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
|
||||
try f.writeCValue(writer, local, .Other);
|
||||
try writer.writeAll(" = ");
|
||||
|
||||
if (!error_ty.errorSetIsEmpty())
|
||||
if (!error_ty.errorSetIsEmpty(mod))
|
||||
if (payload_ty.hasRuntimeBits(mod))
|
||||
if (is_ptr)
|
||||
try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
|
||||
@ -6032,7 +6032,7 @@ fn airCmpBuiltinCall(
|
||||
try writer.writeByte(')');
|
||||
if (!ref_ret) try writer.print(" {s} {}", .{
|
||||
compareOperatorC(operator),
|
||||
try f.fmtIntLiteral(Type.initTag(.i32), Value.zero),
|
||||
try f.fmtIntLiteral(Type.i32, Value.zero),
|
||||
});
|
||||
try writer.writeAll(";\n");
|
||||
try v.end(f, inst, writer);
|
||||
@ -7749,7 +7749,7 @@ const LowerFnRetTyBuffer = struct {
|
||||
payload: Type.Payload.AnonStruct,
|
||||
};
|
||||
fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, mod: *const Module) Type {
|
||||
if (ret_ty.zigTypeTag(mod) == .NoReturn) return Type.initTag(.noreturn);
|
||||
if (ret_ty.zigTypeTag(mod) == .NoReturn) return Type.noreturn;
|
||||
|
||||
if (lowersToArray(ret_ty, mod)) {
|
||||
buffer.names = [1][]const u8{"array"};
|
||||
|
||||
@ -1730,7 +1730,7 @@ pub const Object = struct {
|
||||
return ptr_di_ty;
|
||||
},
|
||||
.Opaque => {
|
||||
if (ty.tag() == .anyopaque) {
|
||||
if (ty.ip_index == .anyopaque_type) {
|
||||
const di_ty = dib.createBasicType("anyopaque", 0, DW.ATE.signed);
|
||||
gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);
|
||||
return di_ty;
|
||||
@ -2847,25 +2847,23 @@ pub const DeclGen = struct {
|
||||
const llvm_addrspace = toLlvmAddressSpace(ptr_info.@"addrspace", target);
|
||||
return dg.context.pointerType(llvm_addrspace);
|
||||
},
|
||||
.Opaque => switch (t.tag()) {
|
||||
.@"opaque" => {
|
||||
const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .mod = dg.module });
|
||||
if (gop.found_existing) return gop.value_ptr.*;
|
||||
.Opaque => {
|
||||
if (t.ip_index == .anyopaque_type) return dg.context.intType(8);
|
||||
|
||||
// The Type memory is ephemeral; since we want to store a longer-lived
|
||||
// reference, we need to copy it here.
|
||||
gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
|
||||
const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .mod = dg.module });
|
||||
if (gop.found_existing) return gop.value_ptr.*;
|
||||
|
||||
const opaque_obj = t.castTag(.@"opaque").?.data;
|
||||
const name = try opaque_obj.getFullyQualifiedName(dg.module);
|
||||
defer gpa.free(name);
|
||||
// The Type memory is ephemeral; since we want to store a longer-lived
|
||||
// reference, we need to copy it here.
|
||||
gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
|
||||
|
||||
const llvm_struct_ty = dg.context.structCreateNamed(name);
|
||||
gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
|
||||
return llvm_struct_ty;
|
||||
},
|
||||
.anyopaque => return dg.context.intType(8),
|
||||
else => unreachable,
|
||||
const opaque_obj = t.castTag(.@"opaque").?.data;
|
||||
const name = try opaque_obj.getFullyQualifiedName(dg.module);
|
||||
defer gpa.free(name);
|
||||
|
||||
const llvm_struct_ty = dg.context.structCreateNamed(name);
|
||||
gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
|
||||
return llvm_struct_ty;
|
||||
},
|
||||
.Array => {
|
||||
const elem_ty = t.childType();
|
||||
@ -5531,7 +5529,7 @@ pub const FuncGen = struct {
|
||||
const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod);
|
||||
const err_union_llvm_ty = try fg.dg.lowerType(err_union_ty);
|
||||
|
||||
if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) {
|
||||
if (!err_union_ty.errorUnionSet().errorSetIsEmpty(mod)) {
|
||||
const is_err = err: {
|
||||
const err_set_ty = try fg.dg.lowerType(Type.anyerror);
|
||||
const zero = err_set_ty.constNull();
|
||||
@ -6715,7 +6713,7 @@ pub const FuncGen = struct {
|
||||
const err_set_ty = try self.dg.lowerType(Type.anyerror);
|
||||
const zero = err_set_ty.constNull();
|
||||
|
||||
if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {
|
||||
if (err_union_ty.errorUnionSet().errorSetIsEmpty(mod)) {
|
||||
const llvm_i1 = self.context.intType(1);
|
||||
switch (op) {
|
||||
.EQ => return llvm_i1.constInt(1, .False), // 0 == 0
|
||||
@ -6864,7 +6862,7 @@ pub const FuncGen = struct {
|
||||
const operand = try self.resolveInst(ty_op.operand);
|
||||
const operand_ty = self.typeOf(ty_op.operand);
|
||||
const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
|
||||
if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {
|
||||
if (err_union_ty.errorUnionSet().errorSetIsEmpty(mod)) {
|
||||
const err_llvm_ty = try self.dg.lowerType(Type.anyerror);
|
||||
if (operand_is_ptr) {
|
||||
return operand;
|
||||
|
||||
@ -2849,6 +2849,7 @@ pub const DeclGen = struct {
|
||||
}
|
||||
|
||||
fn airTry(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
|
||||
const mod = self.module;
|
||||
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
|
||||
const err_union_id = try self.resolve(pl_op.operand);
|
||||
const extra = self.air.extraData(Air.Try, pl_op.payload);
|
||||
@ -2862,7 +2863,7 @@ pub const DeclGen = struct {
|
||||
|
||||
const eu_layout = self.errorUnionLayout(payload_ty);
|
||||
|
||||
if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) {
|
||||
if (!err_union_ty.errorUnionSet().errorSetIsEmpty(mod)) {
|
||||
const err_id = if (eu_layout.payload_has_bits)
|
||||
try self.extractField(Type.anyerror, err_union_id, eu_layout.errorFieldIndex())
|
||||
else
|
||||
@ -2910,12 +2911,13 @@ pub const DeclGen = struct {
|
||||
fn airErrUnionErr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
|
||||
if (self.liveness.isUnused(inst)) return null;
|
||||
|
||||
const mod = self.module;
|
||||
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||
const operand_id = try self.resolve(ty_op.operand);
|
||||
const err_union_ty = self.typeOf(ty_op.operand);
|
||||
const err_ty_ref = try self.resolveType(Type.anyerror, .direct);
|
||||
|
||||
if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {
|
||||
if (err_union_ty.errorUnionSet().errorSetIsEmpty(mod)) {
|
||||
// No error possible, so just return undefined.
|
||||
return try self.spv.constUndef(err_ty_ref);
|
||||
}
|
||||
|
||||
@ -370,7 +370,6 @@ const Writer = struct {
|
||||
switch (t) {
|
||||
.inferred_alloc_const => try s.writeAll("(inferred_alloc_const)"),
|
||||
.inferred_alloc_mut => try s.writeAll("(inferred_alloc_mut)"),
|
||||
.generic_poison => try s.writeAll("(generic_poison)"),
|
||||
else => try ty.print(s, w.module),
|
||||
}
|
||||
}
|
||||
|
||||
737
src/type.zig
737
src/type.zig
File diff suppressed because it is too large
Load Diff
@ -991,26 +991,26 @@ pub const Value = struct {
|
||||
.null_type => Type.null,
|
||||
.undefined_type => Type.undefined,
|
||||
.single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int),
|
||||
.anyframe_type => Type.initTag(.@"anyframe"),
|
||||
.anyframe_type => Type.@"anyframe",
|
||||
.const_slice_u8_type => Type.initTag(.const_slice_u8),
|
||||
.const_slice_u8_sentinel_0_type => Type.initTag(.const_slice_u8_sentinel_0),
|
||||
.anyerror_void_error_union_type => Type.initTag(.anyerror_void_error_union),
|
||||
.generic_poison_type => Type.initTag(.generic_poison),
|
||||
.enum_literal_type => Type.initTag(.enum_literal),
|
||||
.generic_poison_type => .{ .ip_index = .generic_poison_type, .legacy = undefined },
|
||||
.enum_literal_type => .{ .ip_index = .enum_literal_type, .legacy = undefined },
|
||||
.manyptr_u8_type => Type.initTag(.manyptr_u8),
|
||||
.manyptr_const_u8_type => Type.initTag(.manyptr_const_u8),
|
||||
.manyptr_const_u8_sentinel_0_type => Type.initTag(.manyptr_const_u8_sentinel_0),
|
||||
.atomic_order_type => Type.initTag(.atomic_order),
|
||||
.atomic_rmw_op_type => Type.initTag(.atomic_rmw_op),
|
||||
.calling_convention_type => Type.initTag(.calling_convention),
|
||||
.address_space_type => Type.initTag(.address_space),
|
||||
.float_mode_type => Type.initTag(.float_mode),
|
||||
.reduce_op_type => Type.initTag(.reduce_op),
|
||||
.modifier_type => Type.initTag(.modifier),
|
||||
.prefetch_options_type => Type.initTag(.prefetch_options),
|
||||
.export_options_type => Type.initTag(.export_options),
|
||||
.extern_options_type => Type.initTag(.extern_options),
|
||||
.type_info_type => Type.initTag(.type_info),
|
||||
.atomic_order_type => .{ .ip_index = .atomic_order_type, .legacy = undefined },
|
||||
.atomic_rmw_op_type => .{ .ip_index = .atomic_rmw_op_type, .legacy = undefined },
|
||||
.calling_convention_type => .{ .ip_index = .calling_convention_type, .legacy = undefined },
|
||||
.address_space_type => .{ .ip_index = .address_space_type, .legacy = undefined },
|
||||
.float_mode_type => .{ .ip_index = .float_mode_type, .legacy = undefined },
|
||||
.reduce_op_type => .{ .ip_index = .reduce_op_type, .legacy = undefined },
|
||||
.modifier_type => .{ .ip_index = .call_modifier_type, .legacy = undefined },
|
||||
.prefetch_options_type => .{ .ip_index = .prefetch_options_type, .legacy = undefined },
|
||||
.export_options_type => .{ .ip_index = .export_options_type, .legacy = undefined },
|
||||
.extern_options_type => .{ .ip_index = .extern_options_type, .legacy = undefined },
|
||||
.type_info_type => .{ .ip_index = .type_info_type, .legacy = undefined },
|
||||
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user