compiler: eliminate legacy Type.Tag.optional

Now optional types are only stored in InternPool.
This commit is contained in:
Andrew Kelley 2023-05-18 20:02:10 -07:00
parent f21ca3da19
commit 607737d841
2 changed files with 19 additions and 184 deletions

View File

@ -18589,12 +18589,10 @@ fn fieldType(
return sema.addType(field.ty);
},
.Optional => {
if (cur_ty.castTag(.optional)) |some| {
// Struct/array init through optional requires the child type to not be a pointer.
// If the child of .optional is a pointer it'll error on the next loop.
cur_ty = some.data;
continue;
}
// Struct/array init through optional requires the child type to not be a pointer.
// If the child of .optional is a pointer it'll error on the next loop.
cur_ty = mod.intern_pool.indexToKey(cur_ty.ip_index).opt_type.toType();
continue;
},
.ErrorUnion => {
cur_ty = cur_ty.errorUnionPayload();
@ -20390,7 +20388,7 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
ptr_info.@"align" = dest_align;
var dest_ty = try Type.ptr(sema.arena, sema.mod, ptr_info);
if (ptr_ty.zigTypeTag(mod) == .Optional) {
dest_ty = try Type.Tag.optional.create(sema.arena, dest_ty);
dest_ty = try mod.optionalType(dest_ty.toIntern());
}
if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |val| {
@ -31622,10 +31620,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
}
},
.optional => {
return sema.resolveTypeRequiresComptime(ty.optionalChild(mod));
},
.error_union => return sema.resolveTypeRequiresComptime(ty.errorUnionPayload()),
},
else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
@ -33057,15 +33051,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
.pointer,
=> return null,
.optional => {
const child_ty = ty.optionalChild(mod);
if (child_ty.isNoReturn()) {
return Value.null;
} else {
return null;
}
},
.inferred_alloc_const => unreachable,
.inferred_alloc_mut => unreachable,
},
@ -33628,26 +33613,6 @@ fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type {
.inferred_alloc_const => unreachable,
.inferred_alloc_mut => unreachable,
.optional => {
const child_type = ty.optionalChild(mod);
if (child_type.zigTypeTag(mod) != .Pointer) return null;
const info = child_type.ptrInfo(mod);
switch (info.size) {
.Slice, .C => return null,
.Many, .One => {
if (info.@"allowzero") return null;
// optionals of zero sized types behave like bools, not pointers
if ((try sema.typeHasOnePossibleValue(child_type)) != null) {
return null;
}
return child_type;
},
}
},
else => return null,
}
}
@ -33682,10 +33647,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
}
},
.optional => {
return sema.typeRequiresComptime(ty.optionalChild(mod));
},
.error_union => return sema.typeRequiresComptime(ty.errorUnionPayload()),
},
else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
@ -33705,6 +33666,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
.array_type => |array_type| return sema.typeRequiresComptime(array_type.child.toType()),
.vector_type => |vector_type| return sema.typeRequiresComptime(vector_type.child.toType()),
.opt_type => |child| return sema.typeRequiresComptime(child.toType()),
.error_union_type => |error_union_type| {
return sema.typeRequiresComptime(error_union_type.payload_type.toType());
},

View File

@ -47,8 +47,6 @@ pub const Type = struct {
.inferred_alloc_mut,
=> return .Pointer,
.optional => return .Optional,
.error_union => return .ErrorUnion,
},
else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
@ -283,10 +281,6 @@ pub const Type = struct {
return switch (ty.ip_index) {
.none => switch (ty.tag()) {
.pointer => ty.castTag(.pointer).?.data,
.optional => b: {
const child_type = ty.optionalChild(mod);
break :b child_type.ptrInfo(mod);
},
else => unreachable,
},
@ -387,12 +381,6 @@ pub const Type = struct {
return true;
},
.optional => {
if (b.zigTypeTag(mod) != .Optional) return false;
return a.optionalChild(mod).eql(b.optionalChild(mod), mod);
},
.error_union => {
if (b.zigTypeTag(mod) != .ErrorUnion) return false;
@ -466,12 +454,6 @@ pub const Type = struct {
std.hash.autoHash(hasher, info.size);
},
.optional => {
std.hash.autoHash(hasher, std.builtin.TypeId.Optional);
hashWithHasher(ty.optionalChild(mod), hasher, mod);
},
.error_union => {
std.hash.autoHash(hasher, std.builtin.TypeId.ErrorUnion);
@ -530,19 +512,6 @@ pub const Type = struct {
.inferred_alloc_mut,
=> unreachable,
.optional => {
const payload = self.cast(Payload.ElemType).?;
const new_payload = try allocator.create(Payload.ElemType);
new_payload.* = .{
.base = .{ .tag = payload.base.tag },
.data = try payload.data.copy(allocator),
};
return Type{
.ip_index = .none,
.legacy = .{ .ptr_otherwise = &new_payload.base },
};
},
.pointer => {
const payload = self.castTag(.pointer).?.data;
const sent: ?Value = if (payload.sentinel) |some|
@ -654,13 +623,6 @@ pub const Type = struct {
while (true) {
const t = ty.tag();
switch (t) {
.optional => {
const child_type = ty.castTag(.optional).?.data;
try writer.writeByte('?');
ty = child_type;
continue;
},
.pointer => {
const payload = ty.castTag(.pointer).?.data;
if (payload.sentinel) |some| switch (payload.size) {
@ -813,11 +775,6 @@ pub const Type = struct {
try print(info.pointee_type, writer, mod);
},
.optional => {
const child_type = ty.castTag(.optional).?.data;
try writer.writeByte('?');
try print(child_type, writer, mod);
},
.error_set => {
const names = ty.castTag(.error_set).?.data.names.keys();
try writer.writeAll("error{");
@ -911,8 +868,7 @@ pub const Type = struct {
},
.opt_type => |child| {
try writer.writeByte('?');
try print(child.toType(), writer, mod);
return;
return print(child.toType(), writer, mod);
},
.error_union_type => |error_union_type| {
try print(error_union_type.error_set_type.toType(), writer, mod);
@ -1090,21 +1046,6 @@ pub const Type = struct {
}
},
.optional => {
const child_ty = ty.optionalChild(mod);
if (child_ty.isNoReturn()) {
// Then the optional is comptime-known to be null.
return false;
}
if (ignore_comptime_only) {
return true;
} else if (strat == .sema) {
return !(try strat.sema.typeRequiresComptime(child_ty));
} else {
return !comptimeOnly(child_ty, mod);
}
},
.inferred_alloc_const => unreachable,
.inferred_alloc_mut => unreachable,
},
@ -1301,8 +1242,6 @@ pub const Type = struct {
.inferred_alloc_mut => unreachable,
.inferred_alloc_const => unreachable,
.optional => ty.isPtrLikeOptional(mod),
},
else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
.int_type,
@ -1319,7 +1258,7 @@ pub const Type = struct {
=> false,
.array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod),
.opt_type => |child| child.toType().isPtrLikeOptional(mod),
.opt_type => ty.isPtrLikeOptional(mod),
.simple_type => |t| switch (t) {
.f16,
@ -1484,7 +1423,6 @@ pub const Type = struct {
return (ptr_info.pointee_type.abiAlignmentAdvanced(mod, .eager) catch unreachable).scalar;
}
},
.optional => return ty.castTag(.optional).?.data.ptrAlignmentAdvanced(mod, opt_sema),
else => unreachable,
},
@ -1510,11 +1448,6 @@ pub const Type = struct {
.none => switch (ty.tag()) {
.pointer => ty.castTag(.pointer).?.data.@"addrspace",
.optional => {
const child_type = ty.optionalChild(mod);
return child_type.ptrAddressSpace(mod);
},
else => unreachable,
},
else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
@ -1580,7 +1513,6 @@ pub const Type = struct {
.error_set_merged,
=> return AbiAlignmentAdvanced{ .scalar = 2 },
.optional => return abiAlignmentAdvancedOptional(ty, mod, strat),
.error_union => return abiAlignmentAdvancedErrorUnion(ty, mod, strat),
.inferred_alloc_const,
@ -1962,8 +1894,6 @@ pub const Type = struct {
.error_set_single,
=> return AbiSizeAdvanced{ .scalar = 2 },
.optional => return ty.abiSizeAdvancedOptional(mod, strat),
.error_union => {
// This code needs to be kept in sync with the equivalent switch prong
// in abiAlignmentAdvanced.
@ -2282,7 +2212,7 @@ pub const Type = struct {
.error_set_merged,
=> return 16, // TODO revisit this when we have the concept of the error tag type
.optional, .error_union => {
.error_union => {
// Optionals and error unions are not packed so their bitsize
// includes padding bits.
return (try abiSizeAdvanced(ty, mod, strat)).scalar * 8;
@ -2310,7 +2240,11 @@ pub const Type = struct {
const elem_bit_size = try bitSizeAdvanced(child_ty, mod, opt_sema);
return elem_bit_size * vector_type.len;
},
.opt_type => @panic("TODO"),
.opt_type => {
// Optionals and error unions are not packed so their bitsize
// includes padding bits.
return (try abiSizeAdvanced(ty, mod, strat)).scalar * 8;
},
.error_union_type => @panic("TODO"),
.func_type => unreachable, // represents machine code; not a pointer
.simple_type => |t| switch (t) {
@ -2499,7 +2433,6 @@ pub const Type = struct {
}
pub const SlicePtrFieldTypeBuffer = union {
elem_type: Payload.ElemType,
pointer: Payload.Pointer,
};
@ -2600,16 +2533,6 @@ pub const Type = struct {
.One, .Many, .C => return true,
},
.optional => {
const child_type = ty.optionalChild(mod);
if (child_type.zigTypeTag(mod) != .Pointer) return false;
const info = child_type.ptrInfo(mod);
switch (info.size) {
.Slice, .C => return false,
.Many, .One => return !info.@"allowzero",
}
},
else => return false,
},
else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
@ -2655,21 +2578,6 @@ pub const Type = struct {
else => false,
};
switch (ty.tag()) {
.optional => {
const child_ty = ty.castTag(.optional).?.data;
switch (child_ty.zigTypeTag(mod)) {
.Pointer => {
const info = child_ty.ptrInfo(mod);
switch (info.size) {
.C => return false,
.Slice, .Many, .One => return !info.@"allowzero",
}
},
.ErrorSet => return true,
else => return false,
}
},
.pointer => return ty.castTag(.pointer).?.data.size == .C,
else => return false,
@ -2692,16 +2600,6 @@ pub const Type = struct {
else => false,
};
switch (ty.tag()) {
.optional => {
const child_ty = ty.castTag(.optional).?.data;
if (child_ty.zigTypeTag(mod) != .Pointer) return false;
const info = child_ty.ptrInfo(mod);
switch (info.size) {
.Slice, .C => return false,
.Many, .One => return !info.@"allowzero",
}
},
.pointer => return ty.castTag(.pointer).?.data.size == .C,
else => return false,
@ -2747,7 +2645,6 @@ pub const Type = struct {
return child_ty;
}
},
.optional => ty.castTag(.optional).?.data.childType(mod),
else => unreachable,
},
@ -2784,13 +2681,10 @@ pub const Type = struct {
}
/// Asserts that the type is an optional.
/// Resulting `Type` will have inner memory referencing `buf`.
/// Note that for C pointers this returns the type unmodified.
pub fn optionalChild(ty: Type, mod: *const Module) Type {
return switch (ty.ip_index) {
.none => switch (ty.tag()) {
.optional => ty.castTag(.optional).?.data,
.pointer, // here we assume it is a C pointer
=> return ty,
@ -3305,15 +3199,6 @@ pub const Type = struct {
.pointer,
=> return null,
.optional => {
const child_ty = ty.optionalChild(mod);
if (child_ty.isNoReturn()) {
return Value.null;
} else {
return null;
}
},
.inferred_alloc_const => unreachable,
.inferred_alloc_mut => unreachable,
},
@ -3524,10 +3409,6 @@ pub const Type = struct {
}
},
.optional => {
return ty.optionalChild(mod).comptimeOnly(mod);
},
.error_union => return ty.errorUnionPayload().comptimeOnly(mod),
},
else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
@ -4216,7 +4097,6 @@ pub const Type = struct {
// After this, the tag requires a payload.
pointer,
optional,
error_union,
error_set,
error_set_single,
@ -4233,8 +4113,6 @@ pub const Type = struct {
.inferred_alloc_mut,
=> @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
.optional => Payload.ElemType,
.error_set => Payload.ErrorSet,
.error_set_inferred => Payload.ErrorSetInferred,
.error_set_merged => Payload.ErrorSetMerged,
@ -4326,11 +4204,6 @@ pub const Type = struct {
data: u64,
};
pub const ElemType = struct {
base: Payload,
data: Type,
};
pub const Bits = struct {
base: Payload,
data: u16,
@ -4570,11 +4443,11 @@ pub const Type = struct {
}
pub fn optional(arena: Allocator, child_type: Type, mod: *Module) Allocator.Error!Type {
if (child_type.ip_index != .none) {
return mod.optionalType(child_type.ip_index);
} else {
return Type.Tag.optional.create(arena, child_type);
}
// TODO: update callsites of this function to directly call
// mod.optionalType and then delete this function.
_ = arena;
return mod.optionalType(child_type.ip_index);
}
pub fn errorUnion(