stage2: isGenericPoison InternPool awareness

This commit is contained in:
Andrew Kelley 2023-05-02 20:01:32 -07:00
parent 00f82f1c46
commit 50f33734c6
4 changed files with 47 additions and 31 deletions

View file

@ -5728,7 +5728,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
const param_ty = if (func.comptime_args) |comptime_args| t: { const param_ty = if (func.comptime_args) |comptime_args| t: {
const arg_tv = comptime_args[total_param_index]; const arg_tv = comptime_args[total_param_index];
const arg_val = if (arg_tv.val.tag() != .generic_poison) const arg_val = if (!arg_tv.val.isGenericPoison())
arg_tv.val arg_tv.val
else if (arg_tv.ty.onePossibleValue(mod)) |opv| else if (arg_tv.ty.onePossibleValue(mod)) |opv|
opv opv

View file

@ -300,7 +300,7 @@ pub const Block = struct {
const src_decl = sema.mod.declPtr(rt.block.src_decl); const src_decl = sema.mod.declPtr(rt.block.src_decl);
break :blk rt.func_src.toSrcLoc(src_decl); break :blk rt.func_src.toSrcLoc(src_decl);
}; };
if (rt.return_ty.tag() == .generic_poison) { if (rt.return_ty.isGenericPoison()) {
return sema.mod.errNoteNonLazy(src_loc, parent, prefix ++ "the generic function was instantiated with a comptime-only return type", .{}); return sema.mod.errNoteNonLazy(src_loc, parent, prefix ++ "the generic function was instantiated with a comptime-only return type", .{});
} }
try sema.mod.errNoteNonLazy( try sema.mod.errNoteNonLazy(
@ -1730,7 +1730,7 @@ pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
// The last section of indexes refers to the map of ZIR => AIR. // The last section of indexes refers to the map of ZIR => AIR.
const inst = sema.inst_map.get(i - InternPool.static_len).?; const inst = sema.inst_map.get(i - InternPool.static_len).?;
const ty = sema.typeOf(inst); const ty = sema.typeOf(inst);
if (ty.tag() == .generic_poison) return error.GenericPoison; if (ty.isGenericPoison()) return error.GenericPoison;
return inst; return inst;
} }
@ -1766,7 +1766,7 @@ pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Ins
const air_inst = try sema.resolveInst(zir_ref); const air_inst = try sema.resolveInst(zir_ref);
assert(air_inst != .var_args_param_type); assert(air_inst != .var_args_param_type);
const ty = try sema.analyzeAsType(block, src, air_inst); const ty = try sema.analyzeAsType(block, src, air_inst);
if (ty.tag() == .generic_poison) return error.GenericPoison; if (ty.isGenericPoison()) return error.GenericPoison;
return ty; return ty;
} }
@ -1827,7 +1827,7 @@ fn resolveValue(
reason: []const u8, reason: []const u8,
) CompileError!Value { ) CompileError!Value {
if (try sema.resolveMaybeUndefValAllowVariables(air_ref)) |val| { if (try sema.resolveMaybeUndefValAllowVariables(air_ref)) |val| {
if (val.tag() == .generic_poison) return error.GenericPoison; if (val.isGenericPoison()) return error.GenericPoison;
return val; return val;
} }
return sema.failWithNeededComptime(block, src, reason); return sema.failWithNeededComptime(block, src, reason);
@ -6549,8 +6549,8 @@ const GenericCallAdapter = struct {
const other_comptime_args = other_key.comptime_args.?; const other_comptime_args = other_key.comptime_args.?;
for (other_comptime_args[0..ctx.func_ty_info.param_types.len], 0..) |other_arg, i| { for (other_comptime_args[0..ctx.func_ty_info.param_types.len], 0..) |other_arg, i| {
const this_arg = ctx.args[i]; const this_arg = ctx.args[i];
const this_is_comptime = this_arg.val.tag() != .generic_poison; const this_is_comptime = !this_arg.val.isGenericPoison();
const other_is_comptime = other_arg.val.tag() != .generic_poison; const other_is_comptime = !other_arg.val.isGenericPoison();
const this_is_anytype = this_arg.is_anytype; const this_is_anytype = this_arg.is_anytype;
const other_is_anytype = other_key.isAnytypeParam(ctx.module, @intCast(u32, i)); const other_is_anytype = other_key.isAnytypeParam(ctx.module, @intCast(u32, i));
@ -7189,7 +7189,7 @@ fn analyzeInlineCallArg(
const param_body = sema.code.extra[extra.end..][0..extra.data.body_len]; const param_body = sema.code.extra[extra.end..][0..extra.data.body_len];
const param_ty = param_ty: { const param_ty = param_ty: {
const raw_param_ty = raw_param_types[arg_i.*]; const raw_param_ty = raw_param_types[arg_i.*];
if (raw_param_ty.tag() != .generic_poison) break :param_ty raw_param_ty; if (!raw_param_ty.isGenericPoison()) break :param_ty raw_param_ty;
const param_ty_inst = try sema.resolveBody(param_block, param_body, inst); const param_ty_inst = try sema.resolveBody(param_block, param_body, inst);
break :param_ty try sema.analyzeAsType(param_block, param_src, param_ty_inst); break :param_ty try sema.analyzeAsType(param_block, param_src, param_ty_inst);
}; };
@ -7317,7 +7317,7 @@ fn analyzeGenericCallArg(
runtime_i: *u32, runtime_i: *u32,
) !void { ) !void {
const mod = sema.mod; const mod = sema.mod;
const is_runtime = comptime_arg.val.tag() == .generic_poison and const is_runtime = comptime_arg.val.isGenericPoison() and
comptime_arg.ty.hasRuntimeBits(mod) and comptime_arg.ty.hasRuntimeBits(mod) and
!(try sema.typeRequiresComptime(comptime_arg.ty)); !(try sema.typeRequiresComptime(comptime_arg.ty));
if (is_runtime) { if (is_runtime) {
@ -8882,7 +8882,7 @@ fn funcCommon(
const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset }; const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset };
const func_src = LazySrcLoc.nodeOffset(src_node_offset); const func_src = LazySrcLoc.nodeOffset(src_node_offset);
var is_generic = bare_return_type.tag() == .generic_poison or var is_generic = bare_return_type.isGenericPoison() or
alignment == null or alignment == null or
address_space == null or address_space == null or
section == .generic or section == .generic or
@ -8965,7 +8965,7 @@ fn funcCommon(
var ret_ty_requires_comptime = false; var ret_ty_requires_comptime = false;
const ret_poison = if (sema.typeRequiresComptime(bare_return_type)) |ret_comptime| rp: { const ret_poison = if (sema.typeRequiresComptime(bare_return_type)) |ret_comptime| rp: {
ret_ty_requires_comptime = ret_comptime; ret_ty_requires_comptime = ret_comptime;
break :rp bare_return_type.tag() == .generic_poison; break :rp bare_return_type.isGenericPoison();
} else |err| switch (err) { } else |err| switch (err) {
error.GenericPoison => rp: { error.GenericPoison => rp: {
is_generic = true; is_generic = true;
@ -9208,7 +9208,7 @@ fn analyzeParameter(
const mod = sema.mod; const mod = sema.mod;
const requires_comptime = try sema.typeRequiresComptime(param.ty); const requires_comptime = try sema.typeRequiresComptime(param.ty);
comptime_params[i] = param.is_comptime or requires_comptime; comptime_params[i] = param.is_comptime or requires_comptime;
const this_generic = param.ty.tag() == .generic_poison; const this_generic = param.ty.isGenericPoison();
is_generic.* = is_generic.* or this_generic; is_generic.* = is_generic.* or this_generic;
const target = mod.getTarget(); const target = mod.getTarget();
if (param.is_comptime and !Type.fnCallingConventionAllowsZigTypes(target, cc)) { if (param.is_comptime and !Type.fnCallingConventionAllowsZigTypes(target, cc)) {
@ -15872,7 +15872,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const param_vals = try params_anon_decl.arena().alloc(Value, info.param_types.len); const param_vals = try params_anon_decl.arena().alloc(Value, info.param_types.len);
for (param_vals, 0..) |*param_val, i| { for (param_vals, 0..) |*param_val, i| {
const param_ty = info.param_types[i]; const param_ty = info.param_types[i];
const is_generic = param_ty.tag() == .generic_poison; const is_generic = param_ty.isGenericPoison();
const param_ty_val = if (is_generic) const param_ty_val = if (is_generic)
Value.null Value.null
else else
@ -15936,7 +15936,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
}); });
}; };
const ret_ty_opt = if (info.return_type.tag() != .generic_poison) const ret_ty_opt = if (!info.return_type.isGenericPoison())
try Value.Tag.opt_payload.create( try Value.Tag.opt_payload.create(
sema.arena, sema.arena,
try Value.Tag.ty.create(sema.arena, info.return_type), try Value.Tag.ty.create(sema.arena, info.return_type),
@ -16713,7 +16713,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
const operand = try sema.resolveBody(&child_block, body, inst); const operand = try sema.resolveBody(&child_block, body, inst);
const operand_ty = sema.typeOf(operand); const operand_ty = sema.typeOf(operand);
if (operand_ty.tag() == .generic_poison) return error.GenericPoison; if (operand_ty.isGenericPoison()) return error.GenericPoison;
return sema.addType(operand_ty); return sema.addType(operand_ty);
} }
@ -17589,7 +17589,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
} }
return err; return err;
}; };
if (ty.tag() == .generic_poison) return error.GenericPoison; if (ty.isGenericPoison()) return error.GenericPoison;
break :blk ty; break :blk ty;
}; };
const target = sema.mod.getTarget(); const target = sema.mod.getTarget();
@ -22575,7 +22575,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
extra_index += body.len; extra_index += body.len;
const val = try sema.resolveGenericBody(block, align_src, body, inst, Type.u29, "alignment must be comptime-known"); const val = try sema.resolveGenericBody(block, align_src, body, inst, Type.u29, "alignment must be comptime-known");
if (val.tag() == .generic_poison) { if (val.isGenericPoison()) {
break :blk null; break :blk null;
} }
const alignment = @intCast(u32, val.toUnsignedInt(mod)); const alignment = @intCast(u32, val.toUnsignedInt(mod));
@ -22611,7 +22611,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
const addrspace_ty = try sema.getBuiltinType("AddressSpace"); const addrspace_ty = try sema.getBuiltinType("AddressSpace");
const val = try sema.resolveGenericBody(block, addrspace_src, body, inst, addrspace_ty, "addrespace must be comptime-known"); const val = try sema.resolveGenericBody(block, addrspace_src, body, inst, addrspace_ty, "addrespace must be comptime-known");
if (val.tag() == .generic_poison) { if (val.isGenericPoison()) {
break :blk null; break :blk null;
} }
break :blk val.toEnum(std.builtin.AddressSpace); break :blk val.toEnum(std.builtin.AddressSpace);
@ -22635,7 +22635,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
const ty = Type.initTag(.const_slice_u8); const ty = Type.initTag(.const_slice_u8);
const val = try sema.resolveGenericBody(block, section_src, body, inst, ty, "linksection must be comptime-known"); const val = try sema.resolveGenericBody(block, section_src, body, inst, ty, "linksection must be comptime-known");
if (val.tag() == .generic_poison) { if (val.isGenericPoison()) {
break :blk FuncLinkSection{ .generic = {} }; break :blk FuncLinkSection{ .generic = {} };
} }
break :blk FuncLinkSection{ .explicit = try val.toAllocatedBytes(ty, sema.arena, sema.mod) }; break :blk FuncLinkSection{ .explicit = try val.toAllocatedBytes(ty, sema.arena, sema.mod) };
@ -22659,7 +22659,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
const cc_ty = try sema.getBuiltinType("CallingConvention"); const cc_ty = try sema.getBuiltinType("CallingConvention");
const val = try sema.resolveGenericBody(block, cc_src, body, inst, cc_ty, "calling convention must be comptime-known"); const val = try sema.resolveGenericBody(block, cc_src, body, inst, cc_ty, "calling convention must be comptime-known");
if (val.tag() == .generic_poison) { if (val.isGenericPoison()) {
break :blk null; break :blk null;
} }
break :blk val.toEnum(std.builtin.CallingConvention); break :blk val.toEnum(std.builtin.CallingConvention);
@ -31790,7 +31790,7 @@ fn resolveInferredErrorSet(
// if ies declared by a inline function with generic return type, the return_type should be generic_poison, // if ies declared by a inline function with generic return type, the return_type should be generic_poison,
// because inline function does not create a new declaration, and the ies has been filled with analyzeCall, // because inline function does not create a new declaration, and the ies has been filled with analyzeCall,
// so here we can simply skip this case. // so here we can simply skip this case.
if (ies_func_info.return_type.tag() == .generic_poison) { if (ies_func_info.return_type.isGenericPoison()) {
assert(ies_func_info.cc == .Inline); assert(ies_func_info.cc == .Inline);
} else if (ies_func_info.return_type.errorUnionSet().castTag(.error_set_inferred).?.data == ies) { } else if (ies_func_info.return_type.errorUnionSet().castTag(.error_set_inferred).?.data == ies) {
if (ies_func_info.is_generic) { if (ies_func_info.is_generic) {
@ -32048,7 +32048,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
else => |e| return e, else => |e| return e,
}; };
}; };
if (field_ty.tag() == .generic_poison) { if (field_ty.isGenericPoison()) {
return error.GenericPoison; return error.GenericPoison;
} }
@ -32442,7 +32442,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
else => |e| return e, else => |e| return e,
}; };
if (field_ty.tag() == .generic_poison) { if (field_ty.isGenericPoison()) {
return error.GenericPoison; return error.GenericPoison;
} }

View file

@ -727,8 +727,8 @@ pub const Type = struct {
const a_info = a.fnInfo(); const a_info = a.fnInfo();
const b_info = b.fnInfo(); const b_info = b.fnInfo();
if (a_info.return_type.tag() != .generic_poison and if (!a_info.return_type.isGenericPoison() and
b_info.return_type.tag() != .generic_poison and !b_info.return_type.isGenericPoison() and
!eql(a_info.return_type, b_info.return_type, mod)) !eql(a_info.return_type, b_info.return_type, mod))
return false; return false;
@ -758,8 +758,8 @@ pub const Type = struct {
if (a_info.comptime_params[i] != b_info.comptime_params[i]) if (a_info.comptime_params[i] != b_info.comptime_params[i])
return false; return false;
if (a_param_ty.tag() == .generic_poison) continue; if (a_param_ty.isGenericPoison()) continue;
if (b_param_ty.tag() == .generic_poison) continue; if (b_param_ty.isGenericPoison()) continue;
if (!eql(a_param_ty, b_param_ty, mod)) if (!eql(a_param_ty, b_param_ty, mod))
return false; return false;
@ -1131,7 +1131,7 @@ pub const Type = struct {
std.hash.autoHash(hasher, std.builtin.TypeId.Fn); std.hash.autoHash(hasher, std.builtin.TypeId.Fn);
const fn_info = ty.fnInfo(); const fn_info = ty.fnInfo();
if (fn_info.return_type.tag() != .generic_poison) { if (!fn_info.return_type.isGenericPoison()) {
hashWithHasher(fn_info.return_type, hasher, mod); hashWithHasher(fn_info.return_type, hasher, mod);
} }
if (!fn_info.align_is_generic) { if (!fn_info.align_is_generic) {
@ -1148,7 +1148,7 @@ pub const Type = struct {
std.hash.autoHash(hasher, fn_info.param_types.len); std.hash.autoHash(hasher, fn_info.param_types.len);
for (fn_info.param_types, 0..) |param_ty, i| { for (fn_info.param_types, 0..) |param_ty, i| {
std.hash.autoHash(hasher, fn_info.paramIsComptime(i)); std.hash.autoHash(hasher, fn_info.paramIsComptime(i));
if (param_ty.tag() == .generic_poison) continue; if (param_ty.isGenericPoison()) continue;
hashWithHasher(param_ty, hasher, mod); hashWithHasher(param_ty, hasher, mod);
} }
}, },
@ -2154,7 +2154,7 @@ pub const Type = struct {
if (std.math.cast(u5, i)) |index| if (@truncate(u1, fn_info.noalias_bits >> index) != 0) { if (std.math.cast(u5, i)) |index| if (@truncate(u1, fn_info.noalias_bits >> index) != 0) {
try writer.writeAll("noalias "); try writer.writeAll("noalias ");
}; };
if (param_ty.tag() == .generic_poison) { if (param_ty.isGenericPoison()) {
try writer.writeAll("anytype"); try writer.writeAll("anytype");
} else { } else {
try print(param_ty, writer, mod); try print(param_ty, writer, mod);
@ -2175,7 +2175,7 @@ pub const Type = struct {
try writer.writeAll(@tagName(fn_info.cc)); try writer.writeAll(@tagName(fn_info.cc));
try writer.writeAll(") "); try writer.writeAll(") ");
} }
if (fn_info.return_type.tag() == .generic_poison) { if (fn_info.return_type.isGenericPoison()) {
try writer.writeAll("anytype"); try writer.writeAll("anytype");
} else { } else {
try print(fn_info.return_type, writer, mod); try print(fn_info.return_type, writer, mod);
@ -6075,6 +6075,14 @@ pub const Type = struct {
} }
} }
pub fn isGenericPoison(ty: Type) bool {
return switch (ty.ip_index) {
.generic_poison_type => true,
.none => ty.tag() == .generic_poison,
else => false,
};
}
/// This enum does not directly correspond to `std.builtin.TypeId` because /// This enum does not directly correspond to `std.builtin.TypeId` because
/// it has extra enum tags in it, as a way of using less memory. For example, /// it has extra enum tags in it, as a way of using less memory. For example,
/// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types

View file

@ -5416,6 +5416,14 @@ pub const Value = struct {
return initPayload(&value_buffer.base); return initPayload(&value_buffer.base);
} }
pub fn isGenericPoison(val: Value) bool {
return switch (val.ip_index) {
.generic_poison => true,
.none => val.tag() == .generic_poison,
else => false,
};
}
/// This type is not copyable since it may contain pointers to its inner data. /// This type is not copyable since it may contain pointers to its inner data.
pub const Payload = struct { pub const Payload = struct {
tag: Tag, tag: Tag,