Commit 607737d841

Andrew Kelley <andrew@ziglang.org>
2023-05-19 05:02:10
compiler: eliminate legacy Type.Tag.optional
Now optional types are only stored in InternPool.
1 parent f21ca3d
Changed files (2)
src/Sema.zig
@@ -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());
             },
src/type.zig
@@ -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(