Commit f4a249325e

Andrew Kelley <andrew@ziglang.org>
2022-02-02 02:10:19
stage1: avoid anytype fields for type info
prerequisite for #10705
1 parent 5cf9181
lib/std/builtin.zig
@@ -226,11 +226,10 @@ pub const TypeInfo = union(enum) {
         child: type,
         is_allowzero: bool,
 
-        /// This field is an optional type.
         /// The type of the sentinel is the element type of the pointer, which is
         /// the value of the `child` field in this struct. However there is no way
-        /// to refer to that type here, so we use `anytype`.
-        sentinel: anytype,
+        /// to refer to that type here, so we use pointer to `anyopaque`.
+        sentinel: ?*const anyopaque,
 
         /// This data structure is used by the Zig language code generation and
         /// therefore must be kept in sync with the compiler implementation.
@@ -248,11 +247,10 @@ pub const TypeInfo = union(enum) {
         len: comptime_int,
         child: type,
 
-        /// This field is an optional type.
         /// The type of the sentinel is the element type of the array, which is
         /// the value of the `child` field in this struct. However there is no way
-        /// to refer to that type here, so we use `anytype`.
-        sentinel: anytype,
+        /// to refer to that type here, so we use pointer to `anyopaque`.
+        sentinel: ?*const anyopaque,
     };
 
     /// This data structure is used by the Zig language code generation and
@@ -267,8 +265,9 @@ pub const TypeInfo = union(enum) {
     /// therefore must be kept in sync with the compiler implementation.
     pub const StructField = struct {
         name: []const u8,
+        /// TODO rename to `type`
         field_type: type,
-        default_value: anytype,
+        default_value: ?*const anyopaque,
         is_comptime: bool,
         alignment: comptime_int,
     };
@@ -369,7 +368,7 @@ pub const TypeInfo = union(enum) {
     /// This data structure is used by the Zig language code generation and
     /// therefore must be kept in sync with the compiler implementation.
     pub const Frame = struct {
-        function: anytype,
+        function: *const anyopaque,
     };
 
     /// This data structure is used by the Zig language code generation and
lib/std/enums.zig
@@ -16,7 +16,7 @@ pub fn EnumFieldStruct(comptime E: type, comptime Data: type, comptime field_def
         fields = fields ++ &[_]StructField{.{
             .name = field.name,
             .field_type = Data,
-            .default_value = field_default,
+            .default_value = if (field_default) |d| &d else null,
             .is_comptime = false,
             .alignment = if (@sizeOf(Data) > 0) @alignOf(Data) else 0,
         }};
lib/std/mem.zig
@@ -296,7 +296,8 @@ pub fn zeroes(comptime T: type) T {
             }
         },
         .Array => |info| {
-            if (info.sentinel) |sentinel| {
+            if (info.sentinel) |sentinel_ptr| {
+                const sentinel = @ptrCast(*const info.child, sentinel_ptr).*;
                 return [_:sentinel]info.child{zeroes(info.child)} ** info.len;
             }
             return [_]info.child{zeroes(info.child)} ** info.len;
@@ -453,7 +454,8 @@ pub fn zeroInit(comptime T: type, init: anytype) T {
                                     @field(value, field.name) = @field(init, field.name);
                                 },
                             }
-                        } else if (field.default_value) |default_value| {
+                        } else if (field.default_value) |default_value_ptr| {
+                            const default_value = @ptrCast(*const field.field_type, default_value_ptr).*;
                             @field(value, field.name) = default_value;
                         }
                     }
@@ -599,7 +601,7 @@ pub fn Span(comptime T: type) type {
                     else => @compileError("invalid type given to std.mem.Span"),
                 },
                 .C => {
-                    new_ptr_info.sentinel = 0;
+                    new_ptr_info.sentinel = &@as(ptr_info.child, 0);
                     new_ptr_info.is_allowzero = false;
                 },
                 .Many, .Slice => {},
@@ -651,7 +653,9 @@ pub fn span(ptr: anytype) Span(@TypeOf(ptr)) {
     }
     const Result = Span(@TypeOf(ptr));
     const l = len(ptr);
-    if (@typeInfo(Result).Pointer.sentinel) |s| {
+    const ptr_info = @typeInfo(Result).Pointer;
+    if (ptr_info.sentinel) |s_ptr| {
+        const s = @ptrCast(*const ptr_info.child, s_ptr).*;
         return ptr[0..l :s];
     } else {
         return ptr[0..l];
@@ -684,9 +688,10 @@ fn SliceTo(comptime T: type, comptime end: meta.Elem(T)) type {
                         // The return type must only be sentinel terminated if we are guaranteed
                         // to find the value searched for, which is only the case if it matches
                         // the sentinel of the type passed.
-                        if (array_info.sentinel) |sentinel| {
+                        if (array_info.sentinel) |sentinel_ptr| {
+                            const sentinel = @ptrCast(*const array_info.child, sentinel_ptr).*;
                             if (end == sentinel) {
-                                new_ptr_info.sentinel = end;
+                                new_ptr_info.sentinel = &end;
                             } else {
                                 new_ptr_info.sentinel = null;
                             }
@@ -698,16 +703,17 @@ fn SliceTo(comptime T: type, comptime end: meta.Elem(T)) type {
                     // The return type must only be sentinel terminated if we are guaranteed
                     // to find the value searched for, which is only the case if it matches
                     // the sentinel of the type passed.
-                    if (ptr_info.sentinel) |sentinel| {
+                    if (ptr_info.sentinel) |sentinel_ptr| {
+                        const sentinel = @ptrCast(*const ptr_info.child, sentinel_ptr).*;
                         if (end == sentinel) {
-                            new_ptr_info.sentinel = end;
+                            new_ptr_info.sentinel = &end;
                         } else {
                             new_ptr_info.sentinel = null;
                         }
                     }
                 },
                 .C => {
-                    new_ptr_info.sentinel = end;
+                    new_ptr_info.sentinel = &end;
                     // C pointers are always allowzero, but we don't want the return type to be.
                     assert(new_ptr_info.is_allowzero);
                     new_ptr_info.is_allowzero = false;
@@ -734,7 +740,9 @@ pub fn sliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) SliceTo(@Typ
     }
     const Result = SliceTo(@TypeOf(ptr), end);
     const length = lenSliceTo(ptr, end);
-    if (@typeInfo(Result).Pointer.sentinel) |s| {
+    const ptr_info = @typeInfo(Result).Pointer;
+    if (ptr_info.sentinel) |s_ptr| {
+        const s = @ptrCast(*const ptr_info.child, s_ptr).*;
         return ptr[0..length :s];
     } else {
         return ptr[0..length];
@@ -786,7 +794,8 @@ fn lenSliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) usize {
         .Pointer => |ptr_info| switch (ptr_info.size) {
             .One => switch (@typeInfo(ptr_info.child)) {
                 .Array => |array_info| {
-                    if (array_info.sentinel) |sentinel| {
+                    if (array_info.sentinel) |sentinel_ptr| {
+                        const sentinel = @ptrCast(*const array_info.child, sentinel_ptr).*;
                         if (sentinel == end) {
                             return indexOfSentinel(array_info.child, end, ptr);
                         }
@@ -795,7 +804,8 @@ fn lenSliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) usize {
                 },
                 else => {},
             },
-            .Many => if (ptr_info.sentinel) |sentinel| {
+            .Many => if (ptr_info.sentinel) |sentinel_ptr| {
+                const sentinel = @ptrCast(*const ptr_info.child, sentinel_ptr).*;
                 // We may be looking for something other than the sentinel,
                 // but iterating past the sentinel would be a bug so we need
                 // to check for both.
@@ -808,7 +818,8 @@ fn lenSliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) usize {
                 return indexOfSentinel(ptr_info.child, end, ptr);
             },
             .Slice => {
-                if (ptr_info.sentinel) |sentinel| {
+                if (ptr_info.sentinel) |sentinel_ptr| {
+                    const sentinel = @ptrCast(*const ptr_info.child, sentinel_ptr).*;
                     if (sentinel == end) {
                         return indexOfSentinel(ptr_info.child, sentinel, ptr);
                     }
@@ -867,10 +878,12 @@ pub fn len(value: anytype) usize {
                 .Array => value.len,
                 else => @compileError("invalid type given to std.mem.len"),
             },
-            .Many => if (info.sentinel) |sentinel|
-                indexOfSentinel(info.child, sentinel, value)
-            else
-                @compileError("length of pointer with no sentinel"),
+            .Many => {
+                const sentinel_ptr = info.sentinel orelse
+                    @compileError("length of pointer with no sentinel");
+                const sentinel = @ptrCast(*const info.child, sentinel_ptr).*;
+                return indexOfSentinel(info.child, sentinel, value);
+            },
             .C => {
                 assert(value != null);
                 return indexOfSentinel(info.child, 0, value);
@@ -2572,7 +2585,11 @@ test "alignPointer" {
     try S.checkAlign([*]u32, math.maxInt(usize) - 3, 8, 0);
 }
 
-fn CopyPtrAttrs(comptime source: type, comptime size: std.builtin.TypeInfo.Pointer.Size, comptime child: type) type {
+fn CopyPtrAttrs(
+    comptime source: type,
+    comptime size: std.builtin.TypeInfo.Pointer.Size,
+    comptime child: type,
+) type {
     const info = @typeInfo(source).Pointer;
     return @Type(.{
         .Pointer = .{
lib/std/meta.zig
@@ -190,12 +190,21 @@ test "std.meta.Elem" {
 /// Types which cannot possibly have a sentinel will be a compile error.
 pub fn sentinel(comptime T: type) ?Elem(T) {
     switch (@typeInfo(T)) {
-        .Array => |info| return info.sentinel,
+        .Array => |info| {
+            const sentinel_ptr = info.sentinel orelse return null;
+            return @ptrCast(*const info.child, sentinel_ptr).*;
+        },
         .Pointer => |info| {
             switch (info.size) {
-                .Many, .Slice => return info.sentinel,
+                .Many, .Slice => {
+                    const sentinel_ptr = info.sentinel orelse return null;
+                    return @ptrCast(*const info.child, sentinel_ptr).*;
+                },
                 .One => switch (@typeInfo(info.child)) {
-                    .Array => |array_info| return array_info.sentinel,
+                    .Array => |array_info| {
+                        const sentinel_ptr = array_info.sentinel orelse return null;
+                        return @ptrCast(*const array_info.child, sentinel_ptr).*;
+                    },
                     else => {},
                 },
                 else => {},
@@ -239,7 +248,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
                             .Array = .{
                                 .len = array_info.len,
                                 .child = array_info.child,
-                                .sentinel = sentinel_val,
+                                .sentinel = &sentinel_val,
                             },
                         }),
                         .is_allowzero = info.is_allowzero,
@@ -257,7 +266,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
                     .address_space = info.address_space,
                     .child = info.child,
                     .is_allowzero = info.is_allowzero,
-                    .sentinel = sentinel_val,
+                    .sentinel = &sentinel_val,
                 },
             }),
             else => {},
@@ -275,7 +284,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
                                 .address_space = ptr_info.address_space,
                                 .child = ptr_info.child,
                                 .is_allowzero = ptr_info.is_allowzero,
-                                .sentinel = sentinel_val,
+                                .sentinel = &sentinel_val,
                             },
                         }),
                     },
src/stage1/all_types.hpp
@@ -2108,6 +2108,7 @@ struct CodeGen {
         ZigType *entry_global_error_set;
         ZigType *entry_enum_literal;
         ZigType *entry_any_frame;
+        ZigType *entry_opt_ptr_const_anyopaque;
     } builtin_types;
 
     struct Intern {
src/stage1/codegen.cpp
@@ -9451,6 +9451,12 @@ static void define_builtin_types(CodeGen *g) {
         g->primitive_type_table.put(&g->builtin_types.entry_anyopaque->name, g->builtin_types.entry_anyopaque);
     }
 
+    {
+        ZigType *ptr_const_anyopaque = get_pointer_to_type(g,
+                g->builtin_types.entry_anyopaque, true);
+        g->builtin_types.entry_opt_ptr_const_anyopaque = get_optional_type(g, ptr_const_anyopaque);
+    }
+
     {
         ZigType *entry = new_type_table_entry(ZigTypeIdErrorSet);
         buf_init_from_str(&entry->name, "anyerror");
src/stage1/ir.cpp
@@ -18045,11 +18045,12 @@ static PtrLen size_enum_index_to_ptr_len(BuiltinPtrSize size_enum_index) {
 }
 
 static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *ptr_type_entry) {
+    CodeGen *g = ira->codegen;
     ZigType *attrs_type;
     BuiltinPtrSize size_enum_index;
     if (is_slice(ptr_type_entry)) {
         TypeStructField *ptr_field = ptr_type_entry->data.structure.fields[slice_ptr_index];
-        attrs_type = resolve_struct_field_type(ira->codegen, ptr_field);
+        attrs_type = resolve_struct_field_type(g, ptr_field);
         size_enum_index = BuiltinPtrSizeSlice;
     } else if (ptr_type_entry->id == ZigTypeIdPointer) {
         attrs_type = ptr_type_entry;
@@ -18059,19 +18060,19 @@ static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, Scope *scope, AstNode
     }
 
     ZigType *type_info_pointer_type = ir_type_info_get_type(ira, "Pointer", nullptr);
-    assertNoError(type_resolve(ira->codegen, type_info_pointer_type, ResolveStatusSizeKnown));
+    assertNoError(type_resolve(g, type_info_pointer_type, ResolveStatusSizeKnown));
 
-    ZigValue *result = ira->codegen->pass1_arena->create<ZigValue>();
+    ZigValue *result = g->pass1_arena->create<ZigValue>();
     result->special = ConstValSpecialStatic;
     result->type = type_info_pointer_type;
 
-    ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 8);
+    ZigValue **fields = alloc_const_vals_ptrs(g, 8);
     result->data.x_struct.fields = fields;
 
     // size: Size
     ensure_field_index(result->type, "size", 0);
     ZigType *type_info_pointer_size_type = ir_type_info_get_type(ira, "Size", type_info_pointer_type);
-    assertNoError(type_resolve(ira->codegen, type_info_pointer_size_type, ResolveStatusSizeKnown));
+    assertNoError(type_resolve(g, type_info_pointer_size_type, ResolveStatusSizeKnown));
     fields[0]->special = ConstValSpecialStatic;
     fields[0]->type = type_info_pointer_size_type;
     bigint_init_unsigned(&fields[0]->data.x_enum_tag, size_enum_index);
@@ -18079,16 +18080,16 @@ static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, Scope *scope, AstNode
     // is_const: bool
     ensure_field_index(result->type, "is_const", 1);
     fields[1]->special = ConstValSpecialStatic;
-    fields[1]->type = ira->codegen->builtin_types.entry_bool;
+    fields[1]->type = g->builtin_types.entry_bool;
     fields[1]->data.x_bool = attrs_type->data.pointer.is_const;
     // is_volatile: bool
     ensure_field_index(result->type, "is_volatile", 2);
     fields[2]->special = ConstValSpecialStatic;
-    fields[2]->type = ira->codegen->builtin_types.entry_bool;
+    fields[2]->type = g->builtin_types.entry_bool;
     fields[2]->data.x_bool = attrs_type->data.pointer.is_volatile;
     // alignment: comptime_int
     ensure_field_index(result->type, "alignment", 3);
-    fields[3]->type = ira->codegen->builtin_types.entry_num_lit_int;
+    fields[3]->type = g->builtin_types.entry_num_lit_int;
     if (attrs_type->data.pointer.explicit_alignment != 0) {
         fields[3]->special = ConstValSpecialStatic;
         bigint_init_unsigned(&fields[3]->data.x_bigint, attrs_type->data.pointer.explicit_alignment);
@@ -18103,27 +18104,25 @@ static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, Scope *scope, AstNode
     // address_space: AddressSpace,
     ensure_field_index(result->type, "address_space", 4);
     fields[4]->special = ConstValSpecialStatic;
-    fields[4]->type = get_builtin_type(ira->codegen, "AddressSpace");
+    fields[4]->type = get_builtin_type(g, "AddressSpace");
     bigint_init_unsigned(&fields[4]->data.x_enum_tag, AddressSpaceGeneric);
     // child: type
     ensure_field_index(result->type, "child", 5);
     fields[5]->special = ConstValSpecialStatic;
-    fields[5]->type = ira->codegen->builtin_types.entry_type;
+    fields[5]->type = g->builtin_types.entry_type;
     fields[5]->data.x_type = attrs_type->data.pointer.child_type;
     // is_allowzero: bool
     ensure_field_index(result->type, "is_allowzero", 6);
     fields[6]->special = ConstValSpecialStatic;
-    fields[6]->type = ira->codegen->builtin_types.entry_bool;
+    fields[6]->type = g->builtin_types.entry_bool;
     fields[6]->data.x_bool = attrs_type->data.pointer.allow_zero;
-    // sentinel: anytype
+    // sentinel: ?*const anyopaque
     ensure_field_index(result->type, "sentinel", 7);
     fields[7]->special = ConstValSpecialStatic;
-    if (attrs_type->data.pointer.sentinel != nullptr) {
-        fields[7]->type = get_optional_type(ira->codegen, attrs_type->data.pointer.child_type);
-        set_optional_payload(fields[7], attrs_type->data.pointer.sentinel);
-    } else {
-        fields[7]->type = ira->codegen->builtin_types.entry_null;
-    }
+    fields[7]->type = g->builtin_types.entry_opt_ptr_const_anyopaque;
+    ZigValue *ptr_to_sent = (attrs_type->data.pointer.sentinel == nullptr) ? nullptr :
+        create_const_ptr_ref(g, attrs_type->data.pointer.sentinel, true);
+    set_optional_payload(fields[7], ptr_to_sent);
 
     return result;
 };
@@ -18153,7 +18152,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
     assert(type_entry != nullptr);
     assert(!type_is_invalid(type_entry));
 
-    auto entry = ira->codegen->type_info_cache.maybe_get(type_entry);
+    CodeGen *g = ira->codegen;
+
+    auto entry = g->type_info_cache.maybe_get(type_entry);
     if (entry != nullptr) {
         *out = entry->value;
         return ErrorNone;
@@ -18172,43 +18173,43 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
         case ZigTypeIdEnumLiteral:
         case ZigTypeIdUndefined:
         case ZigTypeIdNull:
-            result = ira->codegen->intern.for_void();
+            result = g->intern.for_void();
             break;
         case ZigTypeIdInt:
             {
-                result = ira->codegen->pass1_arena->create<ZigValue>();
+                result = g->pass1_arena->create<ZigValue>();
                 result->special = ConstValSpecialStatic;
                 result->type = ir_type_info_get_type(ira, "Int", nullptr);
 
-                ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 2);
+                ZigValue **fields = alloc_const_vals_ptrs(g, 2);
                 result->data.x_struct.fields = fields;
 
                 // is_signed: Signedness
                 ensure_field_index(result->type, "signedness", 0);
                 fields[0]->special = ConstValSpecialStatic;
-                fields[0]->type = get_builtin_type(ira->codegen, "Signedness");
+                fields[0]->type = get_builtin_type(g, "Signedness");
                 bigint_init_unsigned(&fields[0]->data.x_enum_tag, !type_entry->data.integral.is_signed);
                 // bits: u8
                 ensure_field_index(result->type, "bits", 1);
                 fields[1]->special = ConstValSpecialStatic;
-                fields[1]->type = ira->codegen->builtin_types.entry_num_lit_int;
+                fields[1]->type = g->builtin_types.entry_num_lit_int;
                 bigint_init_unsigned(&fields[1]->data.x_bigint, type_entry->data.integral.bit_count);
 
                 break;
             }
         case ZigTypeIdFloat:
             {
-                result = ira->codegen->pass1_arena->create<ZigValue>();
+                result = g->pass1_arena->create<ZigValue>();
                 result->special = ConstValSpecialStatic;
                 result->type = ir_type_info_get_type(ira, "Float", nullptr);
 
-                ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 1);
+                ZigValue **fields = alloc_const_vals_ptrs(g, 1);
                 result->data.x_struct.fields = fields;
 
                 // bits: u8
                 ensure_field_index(result->type, "bits", 0);
                 fields[0]->special = ConstValSpecialStatic;
-                fields[0]->type = ira->codegen->builtin_types.entry_num_lit_int;
+                fields[0]->type = g->builtin_types.entry_num_lit_int;
                 bigint_init_unsigned(&fields[0]->data.x_bigint, type_entry->data.floating.bit_count);
 
                 break;
@@ -18222,97 +18223,96 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
             }
         case ZigTypeIdArray:
             {
-                result = ira->codegen->pass1_arena->create<ZigValue>();
+                result = g->pass1_arena->create<ZigValue>();
                 result->special = ConstValSpecialStatic;
                 result->type = ir_type_info_get_type(ira, "Array", nullptr);
 
-                ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 3);
+                ZigValue **fields = alloc_const_vals_ptrs(g, 3);
                 result->data.x_struct.fields = fields;
 
                 // len: usize
                 ensure_field_index(result->type, "len", 0);
                 fields[0]->special = ConstValSpecialStatic;
-                fields[0]->type = ira->codegen->builtin_types.entry_num_lit_int;
+                fields[0]->type = g->builtin_types.entry_num_lit_int;
                 bigint_init_unsigned(&fields[0]->data.x_bigint, type_entry->data.array.len);
                 // child: type
                 ensure_field_index(result->type, "child", 1);
                 fields[1]->special = ConstValSpecialStatic;
-                fields[1]->type = ira->codegen->builtin_types.entry_type;
+                fields[1]->type = g->builtin_types.entry_type;
                 fields[1]->data.x_type = type_entry->data.array.child_type;
-                // sentinel: anytype
+                src_assert(type_entry->data.array.child_type != nullptr, source_node);
+                // sentinel: ?*const anyopaque
                 fields[2]->special = ConstValSpecialStatic;
-                if (type_entry->data.array.child_type != nullptr) {
-                    fields[2]->type = get_optional_type(ira->codegen, type_entry->data.array.child_type);
-                    set_optional_payload(fields[2], type_entry->data.array.sentinel);
-                } else {
-                    fields[2]->type = ira->codegen->builtin_types.entry_null;
-                }
+                fields[2]->type = g->builtin_types.entry_opt_ptr_const_anyopaque;
+                ZigValue *ptr_to_sent = (type_entry->data.array.sentinel == nullptr) ? nullptr :
+                    create_const_ptr_ref(g, type_entry->data.array.sentinel, true);
+                set_optional_payload(fields[2], ptr_to_sent);
                 break;
             }
         case ZigTypeIdVector: {
-            result = ira->codegen->pass1_arena->create<ZigValue>();
+            result = g->pass1_arena->create<ZigValue>();
             result->special = ConstValSpecialStatic;
             result->type = ir_type_info_get_type(ira, "Vector", nullptr);
 
-            ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 2);
+            ZigValue **fields = alloc_const_vals_ptrs(g, 2);
             result->data.x_struct.fields = fields;
 
             // len: usize
             ensure_field_index(result->type, "len", 0);
             fields[0]->special = ConstValSpecialStatic;
-            fields[0]->type = ira->codegen->builtin_types.entry_num_lit_int;
+            fields[0]->type = g->builtin_types.entry_num_lit_int;
             bigint_init_unsigned(&fields[0]->data.x_bigint, type_entry->data.vector.len);
             // child: type
             ensure_field_index(result->type, "child", 1);
             fields[1]->special = ConstValSpecialStatic;
-            fields[1]->type = ira->codegen->builtin_types.entry_type;
+            fields[1]->type = g->builtin_types.entry_type;
             fields[1]->data.x_type = type_entry->data.vector.elem_type;
 
             break;
         }
         case ZigTypeIdOptional:
             {
-                result = ira->codegen->pass1_arena->create<ZigValue>();
+                result = g->pass1_arena->create<ZigValue>();
                 result->special = ConstValSpecialStatic;
                 result->type = ir_type_info_get_type(ira, "Optional", nullptr);
 
-                ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 1);
+                ZigValue **fields = alloc_const_vals_ptrs(g, 1);
                 result->data.x_struct.fields = fields;
 
                 // child: type
                 ensure_field_index(result->type, "child", 0);
                 fields[0]->special = ConstValSpecialStatic;
-                fields[0]->type = ira->codegen->builtin_types.entry_type;
+                fields[0]->type = g->builtin_types.entry_type;
                 fields[0]->data.x_type = type_entry->data.maybe.child_type;
 
                 break;
             }
         case ZigTypeIdAnyFrame: {
-            result = ira->codegen->pass1_arena->create<ZigValue>();
+            result = g->pass1_arena->create<ZigValue>();
             result->special = ConstValSpecialStatic;
             result->type = ir_type_info_get_type(ira, "AnyFrame", nullptr);
 
-            ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 1);
+            ZigValue **fields = alloc_const_vals_ptrs(g, 1);
             result->data.x_struct.fields = fields;
 
             // child: ?type
             ensure_field_index(result->type, "child", 0);
             fields[0]->special = ConstValSpecialStatic;
-            fields[0]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type);
+            fields[0]->type = get_optional_type(g, g->builtin_types.entry_type);
             fields[0]->data.x_optional = (type_entry->data.any_frame.result_type == nullptr) ? nullptr :
-                create_const_type(ira->codegen, type_entry->data.any_frame.result_type);
+                create_const_type(g, type_entry->data.any_frame.result_type);
             break;
         }
         case ZigTypeIdEnum:
             {
-                if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusSizeKnown)))
+                if ((err = type_resolve(g, type_entry, ResolveStatusSizeKnown)))
                     return err;
 
-                result = ira->codegen->pass1_arena->create<ZigValue>();
+                result = g->pass1_arena->create<ZigValue>();
                 result->special = ConstValSpecialStatic;
                 result->type = ir_type_info_get_type(ira, "Enum", nullptr);
 
-                ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 5);
+                ZigValue **fields = alloc_const_vals_ptrs(g, 5);
                 result->data.x_struct.fields = fields;
 
                 // layout: ContainerLayout
@@ -18323,24 +18323,24 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
                 // tag_type: type
                 ensure_field_index(result->type, "tag_type", 1);
                 fields[1]->special = ConstValSpecialStatic;
-                fields[1]->type = ira->codegen->builtin_types.entry_type;
+                fields[1]->type = g->builtin_types.entry_type;
                 fields[1]->data.x_type = type_entry->data.enumeration.tag_int_type;
                 // fields: []TypeInfo.EnumField
                 ensure_field_index(result->type, "fields", 2);
 
                 ZigType *type_info_enum_field_type = ir_type_info_get_type(ira, "EnumField", nullptr);
-                if ((err = type_resolve(ira->codegen, type_info_enum_field_type, ResolveStatusSizeKnown))) {
+                if ((err = type_resolve(g, type_info_enum_field_type, ResolveStatusSizeKnown))) {
                     zig_unreachable();
                 }
                 uint32_t enum_field_count = type_entry->data.enumeration.src_field_count;
 
-                ZigValue *enum_field_array = ira->codegen->pass1_arena->create<ZigValue>();
+                ZigValue *enum_field_array = g->pass1_arena->create<ZigValue>();
                 enum_field_array->special = ConstValSpecialStatic;
-                enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count, nullptr);
+                enum_field_array->type = get_array_type(g, type_info_enum_field_type, enum_field_count, nullptr);
                 enum_field_array->data.x_array.special = ConstArraySpecialNone;
-                enum_field_array->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(enum_field_count);
+                enum_field_array->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(enum_field_count);
 
-                init_const_slice(ira->codegen, fields[2], enum_field_array, 0, enum_field_count, false, nullptr);
+                init_const_slice(g, fields[2], enum_field_array, 0, enum_field_count, false, nullptr);
 
                 for (uint32_t enum_field_index = 0; enum_field_index < enum_field_count; enum_field_index++)
                 {
@@ -18361,39 +18361,39 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
                 // is_exhaustive: bool
                 ensure_field_index(result->type, "is_exhaustive", 4);
                 fields[4]->special = ConstValSpecialStatic;
-                fields[4]->type = ira->codegen->builtin_types.entry_bool;
+                fields[4]->type = g->builtin_types.entry_bool;
                 fields[4]->data.x_bool = !type_entry->data.enumeration.non_exhaustive;
 
                 break;
             }
         case ZigTypeIdErrorSet:
             {
-                result = ira->codegen->pass1_arena->create<ZigValue>();
+                result = g->pass1_arena->create<ZigValue>();
                 result->special = ConstValSpecialStatic;
                 result->type = ir_type_info_get_type(ira, "ErrorSet", nullptr);
 
                 ZigType *type_info_error_type = ir_type_info_get_type(ira, "Error", nullptr);
-                if (!resolve_inferred_error_set(ira->codegen, type_entry, source_node)) {
+                if (!resolve_inferred_error_set(g, type_entry, source_node)) {
                     return ErrorSemanticAnalyzeFail;
                 }
                 if (type_is_global_error_set(type_entry)) {
                     result->data.x_optional = nullptr;
                     break;
                 }
-                if ((err = type_resolve(ira->codegen, type_info_error_type, ResolveStatusSizeKnown))) {
+                if ((err = type_resolve(g, type_info_error_type, ResolveStatusSizeKnown))) {
                     zig_unreachable();
                 }
-                ZigValue *slice_val = ira->codegen->pass1_arena->create<ZigValue>();
+                ZigValue *slice_val = g->pass1_arena->create<ZigValue>();
                 result->data.x_optional = slice_val;
 
                 uint32_t error_count = type_entry->data.error_set.err_count;
-                ZigValue *error_array = ira->codegen->pass1_arena->create<ZigValue>();
+                ZigValue *error_array = g->pass1_arena->create<ZigValue>();
                 error_array->special = ConstValSpecialStatic;
-                error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count, nullptr);
+                error_array->type = get_array_type(g, type_info_error_type, error_count, nullptr);
                 error_array->data.x_array.special = ConstArraySpecialNone;
-                error_array->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(error_count);
+                error_array->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(error_count);
 
-                init_const_slice(ira->codegen, slice_val, error_array, 0, error_count, false, nullptr);
+                init_const_slice(g, slice_val, error_array, 0, error_count, false, nullptr);
                 for (uint32_t error_index = 0; error_index < error_count; error_index++) {
                     ErrorTableEntry *error = type_entry->data.error_set.errors[error_index];
                     ZigValue *error_val = &error_array->data.x_array.data.s_none.elements[error_index];
@@ -18401,14 +18401,14 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
                     error_val->special = ConstValSpecialStatic;
                     error_val->type = type_info_error_type;
 
-                    ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 1);
+                    ZigValue **inner_fields = alloc_const_vals_ptrs(g, 1);
 
                     ZigValue *name = nullptr;
                     if (error->cached_error_name_val != nullptr)
                         name = error->cached_error_name_val;
                     if (name == nullptr)
-                        name = create_const_str_lit(ira->codegen, &error->name)->data.x_ptr.data.ref.pointee;
-                    init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(&error->name), true, nullptr);
+                        name = create_const_str_lit(g, &error->name)->data.x_ptr.data.ref.pointee;
+                    init_const_slice(g, inner_fields[0], name, 0, buf_len(&error->name), true, nullptr);
 
                     error_val->data.x_struct.fields = inner_fields;
                     error_val->parent.id = ConstParentIdArray;
@@ -18420,37 +18420,37 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
             }
         case ZigTypeIdErrorUnion:
             {
-                result = ira->codegen->pass1_arena->create<ZigValue>();
+                result = g->pass1_arena->create<ZigValue>();
                 result->special = ConstValSpecialStatic;
                 result->type = ir_type_info_get_type(ira, "ErrorUnion", nullptr);
 
-                ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 2);
+                ZigValue **fields = alloc_const_vals_ptrs(g, 2);
                 result->data.x_struct.fields = fields;
 
                 // error_set: type
                 ensure_field_index(result->type, "error_set", 0);
                 fields[0]->special = ConstValSpecialStatic;
-                fields[0]->type = ira->codegen->builtin_types.entry_type;
+                fields[0]->type = g->builtin_types.entry_type;
                 fields[0]->data.x_type = type_entry->data.error_union.err_set_type;
 
                 // payload: type
                 ensure_field_index(result->type, "payload", 1);
                 fields[1]->special = ConstValSpecialStatic;
-                fields[1]->type = ira->codegen->builtin_types.entry_type;
+                fields[1]->type = g->builtin_types.entry_type;
                 fields[1]->data.x_type = type_entry->data.error_union.payload_type;
 
                 break;
             }
         case ZigTypeIdUnion:
             {
-                if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusSizeKnown)))
+                if ((err = type_resolve(g, type_entry, ResolveStatusSizeKnown)))
                     return err;
 
-                result = ira->codegen->pass1_arena->create<ZigValue>();
+                result = g->pass1_arena->create<ZigValue>();
                 result->special = ConstValSpecialStatic;
                 result->type = ir_type_info_get_type(ira, "Union", nullptr);
 
-                ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 4);
+                ZigValue **fields = alloc_const_vals_ptrs(g, 4);
                 result->data.x_struct.fields = fields;
 
                 // layout: ContainerLayout
@@ -18461,15 +18461,15 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
                 // tag_type: ?type
                 ensure_field_index(result->type, "tag_type", 1);
                 fields[1]->special = ConstValSpecialStatic;
-                fields[1]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type);
+                fields[1]->type = get_optional_type(g, g->builtin_types.entry_type);
 
                 AstNode *union_decl_node = type_entry->data.unionation.decl_node;
                 if (union_decl_node->data.container_decl.auto_enum ||
                     union_decl_node->data.container_decl.init_arg_expr != nullptr)
                 {
-                    ZigValue *tag_type = ira->codegen->pass1_arena->create<ZigValue>();
+                    ZigValue *tag_type = g->pass1_arena->create<ZigValue>();
                     tag_type->special = ConstValSpecialStatic;
-                    tag_type->type = ira->codegen->builtin_types.entry_type;
+                    tag_type->type = g->builtin_types.entry_type;
                     tag_type->data.x_type = type_entry->data.unionation.tag_type;
                     fields[1]->data.x_optional = tag_type;
                 } else {
@@ -18479,17 +18479,17 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
                 ensure_field_index(result->type, "fields", 2);
 
                 ZigType *type_info_union_field_type = ir_type_info_get_type(ira, "UnionField", nullptr);
-                if ((err = type_resolve(ira->codegen, type_info_union_field_type, ResolveStatusSizeKnown)))
+                if ((err = type_resolve(g, type_info_union_field_type, ResolveStatusSizeKnown)))
                     zig_unreachable();
                 uint32_t union_field_count = type_entry->data.unionation.src_field_count;
 
-                ZigValue *union_field_array = ira->codegen->pass1_arena->create<ZigValue>();
+                ZigValue *union_field_array = g->pass1_arena->create<ZigValue>();
                 union_field_array->special = ConstValSpecialStatic;
-                union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count, nullptr);
+                union_field_array->type = get_array_type(g, type_info_union_field_type, union_field_count, nullptr);
                 union_field_array->data.x_array.special = ConstArraySpecialNone;
-                union_field_array->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(union_field_count);
+                union_field_array->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(union_field_count);
 
-                init_const_slice(ira->codegen, fields[2], union_field_array, 0, union_field_count, false, nullptr);
+                init_const_slice(g, fields[2], union_field_array, 0, union_field_count, false, nullptr);
 
                 for (uint32_t union_field_index = 0; union_field_index < union_field_count; union_field_index++) {
                     TypeUnionField *union_field = &type_entry->data.unionation.fields[union_field_index];
@@ -18498,19 +18498,19 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
                     union_field_val->special = ConstValSpecialStatic;
                     union_field_val->type = type_info_union_field_type;
 
-                    ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 3);
+                    ZigValue **inner_fields = alloc_const_vals_ptrs(g, 3);
                     // field_type: type
                     inner_fields[1]->special = ConstValSpecialStatic;
-                    inner_fields[1]->type = ira->codegen->builtin_types.entry_type;
+                    inner_fields[1]->type = g->builtin_types.entry_type;
                     inner_fields[1]->data.x_type = union_field->type_entry;
 
                     // alignment: comptime_int
                     inner_fields[2]->special = ConstValSpecialStatic;
-                    inner_fields[2]->type = ira->codegen->builtin_types.entry_num_lit_int;
+                    inner_fields[2]->type = g->builtin_types.entry_num_lit_int;
                     bigint_init_unsigned(&inner_fields[2]->data.x_bigint, union_field->align);
 
-                    ZigValue *name = create_const_str_lit(ira->codegen, union_field->name)->data.x_ptr.data.ref.pointee;
-                    init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(union_field->name), true, nullptr);
+                    ZigValue *name = create_const_str_lit(g, union_field->name)->data.x_ptr.data.ref.pointee;
+                    init_const_slice(g, inner_fields[0], name, 0, buf_len(union_field->name), true, nullptr);
 
                     union_field_val->data.x_struct.fields = inner_fields;
                     union_field_val->parent.id = ConstParentIdArray;
@@ -18536,14 +18536,14 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
                     break;
                 }
 
-                if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusSizeKnown)))
+                if ((err = type_resolve(g, type_entry, ResolveStatusSizeKnown)))
                     return err;
 
-                result = ira->codegen->pass1_arena->create<ZigValue>();
+                result = g->pass1_arena->create<ZigValue>();
                 result->special = ConstValSpecialStatic;
                 result->type = ir_type_info_get_type(ira, "Struct", nullptr);
 
-                ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 4);
+                ZigValue **fields = alloc_const_vals_ptrs(g, 4);
                 result->data.x_struct.fields = fields;
 
                 // layout: ContainerLayout
@@ -18555,18 +18555,18 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
                 ensure_field_index(result->type, "fields", 1);
 
                 ZigType *type_info_struct_field_type = ir_type_info_get_type(ira, "StructField", nullptr);
-                if ((err = type_resolve(ira->codegen, type_info_struct_field_type, ResolveStatusSizeKnown))) {
+                if ((err = type_resolve(g, type_info_struct_field_type, ResolveStatusSizeKnown))) {
                     zig_unreachable();
                 }
                 uint32_t struct_field_count = type_entry->data.structure.src_field_count;
 
-                ZigValue *struct_field_array = ira->codegen->pass1_arena->create<ZigValue>();
+                ZigValue *struct_field_array = g->pass1_arena->create<ZigValue>();
                 struct_field_array->special = ConstValSpecialStatic;
-                struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count, nullptr);
+                struct_field_array->type = get_array_type(g, type_info_struct_field_type, struct_field_count, nullptr);
                 struct_field_array->data.x_array.special = ConstArraySpecialNone;
-                struct_field_array->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(struct_field_count);
+                struct_field_array->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(struct_field_count);
 
-                init_const_slice(ira->codegen, fields[1], struct_field_array, 0, struct_field_count, false, nullptr);
+                init_const_slice(g, fields[1], struct_field_array, 0, struct_field_count, false, nullptr);
 
                 for (uint32_t struct_field_index = 0; struct_field_index < struct_field_count; struct_field_index++) {
                     TypeStructField *struct_field = type_entry->data.structure.fields[struct_field_index];
@@ -18575,34 +18575,37 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
                     struct_field_val->special = ConstValSpecialStatic;
                     struct_field_val->type = type_info_struct_field_type;
 
-                    ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 5);
+                    ZigValue **inner_fields = alloc_const_vals_ptrs(g, 5);
 
                     inner_fields[1]->special = ConstValSpecialStatic;
-                    inner_fields[1]->type = ira->codegen->builtin_types.entry_type;
+                    inner_fields[1]->type = g->builtin_types.entry_type;
                     inner_fields[1]->data.x_type = struct_field->type_entry;
 
-                    // default_value: anytype
+                    // default_value: ?*const anyopaque
                     inner_fields[2]->special = ConstValSpecialStatic;
-                    inner_fields[2]->type = get_optional_type2(ira->codegen, struct_field->type_entry);
-                    if (inner_fields[2]->type == nullptr) return ErrorSemanticAnalyzeFail;
-                    memoize_field_init_val(ira->codegen, type_entry, struct_field);
-                    if(struct_field->init_val != nullptr && type_is_invalid(struct_field->init_val->type)){
+                    inner_fields[2]->type = g->builtin_types.entry_opt_ptr_const_anyopaque;
+                    memoize_field_init_val(g, type_entry, struct_field);
+                    if (struct_field->init_val != nullptr &&
+                        type_is_invalid(struct_field->init_val->type))
+                    {
                         return ErrorSemanticAnalyzeFail;
                     }
-                    set_optional_payload(inner_fields[2], struct_field->init_val);
+                    ZigValue *ptr_to_sent = (struct_field->init_val == nullptr) ? nullptr :
+                        create_const_ptr_ref(g, struct_field->init_val, true);
+                    set_optional_payload(inner_fields[2], ptr_to_sent);
 
                     // is_comptime: bool
                     inner_fields[3]->special = ConstValSpecialStatic;
-                    inner_fields[3]->type = ira->codegen->builtin_types.entry_bool;
+                    inner_fields[3]->type = g->builtin_types.entry_bool;
                     inner_fields[3]->data.x_bool = struct_field->is_comptime;
 
                     // alignment: comptime_int
                     inner_fields[4]->special = ConstValSpecialStatic;
-                    inner_fields[4]->type = ira->codegen->builtin_types.entry_num_lit_int;
+                    inner_fields[4]->type = g->builtin_types.entry_num_lit_int;
                     bigint_init_unsigned(&inner_fields[4]->data.x_bigint, struct_field->align);
 
-                    ZigValue *name = create_const_str_lit(ira->codegen, struct_field->name)->data.x_ptr.data.ref.pointee;
-                    init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(struct_field->name), true, nullptr);
+                    ZigValue *name = create_const_str_lit(g, struct_field->name)->data.x_ptr.data.ref.pointee;
+                    init_const_slice(g, inner_fields[0], name, 0, buf_len(struct_field->name), true, nullptr);
 
                     struct_field_val->data.x_struct.fields = inner_fields;
                     struct_field_val->parent.id = ConstParentIdArray;
@@ -18620,69 +18623,69 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
                 // is_tuple: bool
                 ensure_field_index(result->type, "is_tuple", 3);
                 fields[3]->special = ConstValSpecialStatic;
-                fields[3]->type = ira->codegen->builtin_types.entry_bool;
+                fields[3]->type = g->builtin_types.entry_bool;
                 fields[3]->data.x_bool = is_tuple(type_entry);
 
                 break;
             }
         case ZigTypeIdFn:
             {
-                result = ira->codegen->pass1_arena->create<ZigValue>();
+                result = g->pass1_arena->create<ZigValue>();
                 result->special = ConstValSpecialStatic;
                 result->type = ir_type_info_get_type(ira, "Fn", nullptr);
 
-                ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 7);
+                ZigValue **fields = alloc_const_vals_ptrs(g, 7);
                 result->data.x_struct.fields = fields;
 
                 // calling_convention: TypeInfo.CallingConvention
                 ensure_field_index(result->type, "calling_convention", 0);
                 fields[0]->special = ConstValSpecialStatic;
-                fields[0]->type = get_builtin_type(ira->codegen, "CallingConvention");
+                fields[0]->type = get_builtin_type(g, "CallingConvention");
                 bigint_init_unsigned(&fields[0]->data.x_enum_tag, type_entry->data.fn.fn_type_id.cc);
                 // alignment: comptime_int
                 ensure_field_index(result->type, "alignment", 1);
                 fields[1]->special = ConstValSpecialStatic;
-                fields[1]->type = ira->codegen->builtin_types.entry_num_lit_int;
-                bigint_init_unsigned(&fields[1]->data.x_bigint, get_ptr_align(ira->codegen, type_entry));
+                fields[1]->type = g->builtin_types.entry_num_lit_int;
+                bigint_init_unsigned(&fields[1]->data.x_bigint, get_ptr_align(g, type_entry));
                 // is_generic: bool
                 ensure_field_index(result->type, "is_generic", 2);
                 bool is_generic = type_entry->data.fn.is_generic;
                 fields[2]->special = ConstValSpecialStatic;
-                fields[2]->type = ira->codegen->builtin_types.entry_bool;
+                fields[2]->type = g->builtin_types.entry_bool;
                 fields[2]->data.x_bool = is_generic;
                 // is_varargs: bool
                 ensure_field_index(result->type, "is_var_args", 3);
                 bool is_varargs = type_entry->data.fn.fn_type_id.is_var_args;
                 fields[3]->special = ConstValSpecialStatic;
-                fields[3]->type = ira->codegen->builtin_types.entry_bool;
+                fields[3]->type = g->builtin_types.entry_bool;
                 fields[3]->data.x_bool = is_varargs;
                 // return_type: ?type
                 ensure_field_index(result->type, "return_type", 4);
                 fields[4]->special = ConstValSpecialStatic;
-                fields[4]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type);
+                fields[4]->type = get_optional_type(g, g->builtin_types.entry_type);
                 if (type_entry->data.fn.fn_type_id.return_type == nullptr)
                     fields[4]->data.x_optional = nullptr;
                 else {
-                    ZigValue *return_type = ira->codegen->pass1_arena->create<ZigValue>();
+                    ZigValue *return_type = g->pass1_arena->create<ZigValue>();
                     return_type->special = ConstValSpecialStatic;
-                    return_type->type = ira->codegen->builtin_types.entry_type;
+                    return_type->type = g->builtin_types.entry_type;
                     return_type->data.x_type = type_entry->data.fn.fn_type_id.return_type;
                     fields[4]->data.x_optional = return_type;
                 }
                 // args: []TypeInfo.FnArg
                 ZigType *type_info_fn_arg_type = ir_type_info_get_type(ira, "FnArg", nullptr);
-                if ((err = type_resolve(ira->codegen, type_info_fn_arg_type, ResolveStatusSizeKnown))) {
+                if ((err = type_resolve(g, type_info_fn_arg_type, ResolveStatusSizeKnown))) {
                     zig_unreachable();
                 }
                 size_t fn_arg_count = type_entry->data.fn.fn_type_id.param_count;
 
-                ZigValue *fn_arg_array = ira->codegen->pass1_arena->create<ZigValue>();
+                ZigValue *fn_arg_array = g->pass1_arena->create<ZigValue>();
                 fn_arg_array->special = ConstValSpecialStatic;
-                fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count, nullptr);
+                fn_arg_array->type = get_array_type(g, type_info_fn_arg_type, fn_arg_count, nullptr);
                 fn_arg_array->data.x_array.special = ConstArraySpecialNone;
-                fn_arg_array->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(fn_arg_count);
+                fn_arg_array->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(fn_arg_count);
 
-                init_const_slice(ira->codegen, fields[5], fn_arg_array, 0, fn_arg_count, false, nullptr);
+                init_const_slice(g, fields[5], fn_arg_array, 0, fn_arg_count, false, nullptr);
 
                 for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) {
                     FnTypeParamInfo *fn_param_info = &type_entry->data.fn.fn_type_id.param_info[fn_arg_index];
@@ -18694,22 +18697,22 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
                     bool arg_is_generic = fn_param_info->type == nullptr;
                     if (arg_is_generic) assert(is_generic);
 
-                    ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 3);
+                    ZigValue **inner_fields = alloc_const_vals_ptrs(g, 3);
                     inner_fields[0]->special = ConstValSpecialStatic;
-                    inner_fields[0]->type = ira->codegen->builtin_types.entry_bool;
+                    inner_fields[0]->type = g->builtin_types.entry_bool;
                     inner_fields[0]->data.x_bool = arg_is_generic;
                     inner_fields[1]->special = ConstValSpecialStatic;
-                    inner_fields[1]->type = ira->codegen->builtin_types.entry_bool;
+                    inner_fields[1]->type = g->builtin_types.entry_bool;
                     inner_fields[1]->data.x_bool = fn_param_info->is_noalias;
                     inner_fields[2]->special = ConstValSpecialStatic;
-                    inner_fields[2]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type);
+                    inner_fields[2]->type = get_optional_type(g, g->builtin_types.entry_type);
 
                     if (arg_is_generic)
                         inner_fields[2]->data.x_optional = nullptr;
                     else {
-                        ZigValue *arg_type = ira->codegen->pass1_arena->create<ZigValue>();
+                        ZigValue *arg_type = g->pass1_arena->create<ZigValue>();
                         arg_type->special = ConstValSpecialStatic;
-                        arg_type->type = ira->codegen->builtin_types.entry_type;
+                        arg_type->type = g->builtin_types.entry_type;
                         arg_type->data.x_type = fn_param_info->type;
                         inner_fields[2]->data.x_optional = arg_type;
                     }
@@ -18733,11 +18736,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
             }
         case ZigTypeIdOpaque:
             {
-                result = ira->codegen->pass1_arena->create<ZigValue>();
+                result = g->pass1_arena->create<ZigValue>();
                 result->special = ConstValSpecialStatic;
                 result->type = ir_type_info_get_type(ira, "Opaque", nullptr);
 
-                ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 1);
+                ZigValue **fields = alloc_const_vals_ptrs(g, 1);
                 result->data.x_struct.fields = fields;
 
                 // decls: []TypeInfo.Declaration
@@ -18752,21 +18755,24 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
             }
         case ZigTypeIdFnFrame:
             {
-                result = ira->codegen->pass1_arena->create<ZigValue>();
+                result = g->pass1_arena->create<ZigValue>();
                 result->special = ConstValSpecialStatic;
                 result->type = ir_type_info_get_type(ira, "Frame", nullptr);
-                ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 1);
+                ZigValue **fields = alloc_const_vals_ptrs(g, 1);
                 result->data.x_struct.fields = fields;
                 ZigFn *fn = type_entry->data.frame.fn;
-                // function: anytype
+                // function: ?*const anyopaque
                 ensure_field_index(result->type, "function", 0);
-                fields[0] = create_const_fn(ira->codegen, fn);
+                fields[0]->special = ConstValSpecialStatic;
+                fields[0]->type = get_pointer_to_type(g, g->builtin_types.entry_anyopaque, true);
+                fields[0]->data.x_ptr.special = ConstPtrSpecialFunction;
+                fields[0]->data.x_ptr.data.fn.fn_entry = fn;
                 break;
             }
     }
 
     assert(result != nullptr);
-    ira->codegen->type_info_cache.put(type_entry, result);
+    g->type_info_cache.put(type_entry, result);
     *out = result;
     return ErrorNone;
 }
@@ -18810,26 +18816,25 @@ static ZigValue *get_const_field(IrAnalyze *ira, AstNode *source_node, ZigValue
     return val;
 }
 
-static Error get_const_field_sentinel(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigValue *struct_value,
-        const char *name, size_t field_index, ZigType *elem_type, ZigValue **result)
+static Error get_const_field_sentinel(IrAnalyze *ira, Scope *scope, AstNode *source_node,
+    ZigValue *struct_value, const char *name, size_t field_index, ZigType *elem_type,
+    ZigValue **result)
 {
     ZigValue *field_val = get_const_field(ira, source_node, struct_value, name, field_index);
     if (field_val == nullptr)
         return ErrorSemanticAnalyzeFail;
 
-    Stage1AirInst *field_inst = ir_const_move(ira, scope, source_node, field_val);
-    Stage1AirInst *casted_field_inst = ir_implicit_cast(ira, field_inst,
-            get_optional_type(ira->codegen, elem_type));
-    if (type_is_invalid(casted_field_inst->value->type))
-        return ErrorSemanticAnalyzeFail;
-
-    if (optional_value_is_null(casted_field_inst->value)) {
+    // type of `field_val` is `?*const anyopaque`.
+    if (field_val->data.x_ptr.special == ConstPtrSpecialNull) {
         *result = nullptr;
-    } else {
-        assert(type_has_optional_repr(casted_field_inst->value->type));
-        *result = casted_field_inst->value->data.x_optional;
+        return ErrorNone;
     }
 
+    ZigValue *pointee = const_ptr_pointee_unchecked_no_isf(ira->codegen, field_val);
+    if (pointee == nullptr)
+        return ErrorSemanticAnalyzeFail;
+
+    *result = pointee;
     return ErrorNone;
 }
 
@@ -19140,15 +19145,9 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
             return get_any_frame_type(ira->codegen, child_type);
         }
         case ZigTypeIdFnFrame: {
-            assert(payload->special == ConstValSpecialStatic);
-            assert(payload->type == ir_type_info_get_type(ira, "Frame", nullptr));
-            ZigValue *function = get_const_field(ira, source_node, payload, "function", 0);
-            if (function == nullptr)
-                return ira->codegen->invalid_inst_gen->value->type;
-
-            assert(function->type->id == ZigTypeIdFn);
-            ZigFn *fn = function->data.x_ptr.data.fn.fn_entry;
-            return get_fn_frame_type(ira->codegen, fn);
+            ir_add_error_node(ira, source_node,
+                buf_sprintf("use the @Frame builtin instead of @Type"));
+            return ira->codegen->invalid_inst_gen->value->type;
         }
         case ZigTypeIdErrorSet: {
             assert(payload->special == ConstValSpecialStatic);
@@ -19276,19 +19275,17 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
                 ZigValue *default_value = get_const_field(ira, source_node, field_value, "default_value", 2);
                 if (default_value == nullptr)
                     return ira->codegen->invalid_inst_gen->value->type;
-                if (default_value->type->id == ZigTypeIdNull) {
+
+                // type of `default_value` is `?*const anyopaque`.
+                if (default_value->data.x_ptr.special == ConstPtrSpecialNull) {
                     field->init_val = nullptr;
-                } else if (default_value->type->id == ZigTypeIdOptional && default_value->type->data.maybe.child_type == field->type_entry) {
-                    field->init_val = default_value->data.x_optional;
-                } else if (default_value->type == field->type_entry) {
-                    field->init_val = default_value;
                 } else {
-                    ir_add_error_node(ira, source_node,
-                        buf_sprintf("default_value of field '%s' is of type '%s', expected '%s' or '?%s'",
-                            buf_ptr(field->name), buf_ptr(&default_value->type->name),
-                            buf_ptr(&field->type_entry->name), buf_ptr(&field->type_entry->name)));
-                    return ira->codegen->invalid_inst_gen->value->type;
+                    ZigValue *pointee = const_ptr_pointee_unchecked_no_isf(ira->codegen, default_value);
+                    if (pointee == nullptr)
+                        return ira->codegen->invalid_inst_gen->value->type;
+                    field->init_val = pointee;
                 }
+
                 if ((err = get_const_field_bool(ira, source_node, field_value, "is_comptime", 3, &field->is_comptime)))
                     return ira->codegen->invalid_inst_gen->value->type;
                 BigInt *alignment = get_const_field_lit_int(ira, source_node, field_value, "alignment", 4);
test/behavior/type_info.zig
@@ -119,7 +119,7 @@ fn testNullTerminatedPtr() !void {
     try expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
     try expect(ptr_info.Pointer.is_const == false);
     try expect(ptr_info.Pointer.is_volatile == false);
-    try expect(ptr_info.Pointer.sentinel.? == 0);
+    try expect(@ptrCast(*const u8, ptr_info.Pointer.sentinel.?).* == 0);
 
     try expect(@typeInfo([:0]u8).Pointer.sentinel != null);
 }
@@ -161,7 +161,7 @@ fn testArray() !void {
         const info = @typeInfo([10:0]u8);
         try expect(info.Array.len == 10);
         try expect(info.Array.child == u8);
-        try expect(info.Array.sentinel.? == @as(u8, 0));
+        try expect(@ptrCast(*const u8, info.Array.sentinel.?).* == @as(u8, 0));
         try expect(@sizeOf([10:0]u8) == info.Array.len + 1);
     }
 }
@@ -271,8 +271,8 @@ fn testStruct() !void {
     const unpacked_struct_info = @typeInfo(TestUnpackedStruct);
     try expect(unpacked_struct_info.Struct.is_tuple == false);
     try expect(unpacked_struct_info.Struct.fields[0].alignment == @alignOf(u32));
-    try expect(unpacked_struct_info.Struct.fields[0].default_value.? == 4);
-    try expectEqualStrings("foobar", unpacked_struct_info.Struct.fields[1].default_value.?);
+    try expect(@ptrCast(*const u32, unpacked_struct_info.Struct.fields[0].default_value.?).* == 4);
+    try expectEqualStrings("foobar", @ptrCast(*const *const [6:0]u8, unpacked_struct_info.Struct.fields[1].default_value.?).*);
 
     const struct_info = @typeInfo(TestStruct);
     try expect(struct_info == .Struct);
@@ -282,7 +282,7 @@ fn testStruct() !void {
     try expect(struct_info.Struct.fields[0].alignment == 2 * @alignOf(usize));
     try expect(struct_info.Struct.fields[2].field_type == *TestStruct);
     try expect(struct_info.Struct.fields[2].default_value == null);
-    try expect(struct_info.Struct.fields[3].default_value.? == 4);
+    try expect(@ptrCast(*const u32, struct_info.Struct.fields[3].default_value.?).* == 4);
     try expect(struct_info.Struct.fields[3].alignment == 1);
     try expect(struct_info.Struct.decls.len == 2);
     try expect(struct_info.Struct.decls[0].is_pub);
@@ -452,7 +452,7 @@ test "type info for async frames" {
 
     switch (@typeInfo(@Frame(add))) {
         .Frame => |frame| {
-            try expect(frame.function == add);
+            try expect(@ptrCast(@TypeOf(add), frame.function) == add);
         },
         else => unreachable,
     }
test/behavior/type_stage1.zig
@@ -37,7 +37,7 @@ test "Type.Array" {
         .Array = TypeInfo.Array{
             .len = 2,
             .child = u32,
-            .sentinel = 0,
+            .sentinel = &@as(u32, 0),
         },
     }));
     try testTypes(&[_]type{ [1]u8, [30]usize, [7]bool });
@@ -141,12 +141,6 @@ fn add(a: i32, b: i32) i32 {
     return a + b;
 }
 
-test "Type.Frame" {
-    try testTypes(&[_]type{
-        @Frame(add),
-    });
-}
-
 test "Type.ErrorSet" {
     // error sets don't compare equal so just check if they compile
     _ = @Type(@typeInfo(error{}));
@@ -160,10 +154,10 @@ test "Type.Struct" {
     try testing.expectEqual(TypeInfo.ContainerLayout.Auto, infoA.layout);
     try testing.expectEqualSlices(u8, "x", infoA.fields[0].name);
     try testing.expectEqual(u8, infoA.fields[0].field_type);
-    try testing.expectEqual(@as(?u8, null), infoA.fields[0].default_value);
+    try testing.expectEqual(@as(?*const anyopaque, null), infoA.fields[0].default_value);
     try testing.expectEqualSlices(u8, "y", infoA.fields[1].name);
     try testing.expectEqual(u32, infoA.fields[1].field_type);
-    try testing.expectEqual(@as(?u32, null), infoA.fields[1].default_value);
+    try testing.expectEqual(@as(?*const anyopaque, null), infoA.fields[1].default_value);
     try testing.expectEqualSlices(TypeInfo.Declaration, &[_]TypeInfo.Declaration{}, infoA.decls);
     try testing.expectEqual(@as(bool, false), infoA.is_tuple);
 
@@ -178,10 +172,10 @@ test "Type.Struct" {
     try testing.expectEqual(TypeInfo.ContainerLayout.Extern, infoB.layout);
     try testing.expectEqualSlices(u8, "x", infoB.fields[0].name);
     try testing.expectEqual(u8, infoB.fields[0].field_type);
-    try testing.expectEqual(@as(?u8, null), infoB.fields[0].default_value);
+    try testing.expectEqual(@as(?*const anyopaque, null), infoB.fields[0].default_value);
     try testing.expectEqualSlices(u8, "y", infoB.fields[1].name);
     try testing.expectEqual(u32, infoB.fields[1].field_type);
-    try testing.expectEqual(@as(?u32, 5), infoB.fields[1].default_value);
+    try testing.expectEqual(@as(u32, 5), @ptrCast(*const u32, infoB.fields[1].default_value.?).*);
     try testing.expectEqual(@as(usize, 0), infoB.decls.len);
     try testing.expectEqual(@as(bool, false), infoB.is_tuple);
 
@@ -190,10 +184,10 @@ test "Type.Struct" {
     try testing.expectEqual(TypeInfo.ContainerLayout.Packed, infoC.layout);
     try testing.expectEqualSlices(u8, "x", infoC.fields[0].name);
     try testing.expectEqual(u8, infoC.fields[0].field_type);
-    try testing.expectEqual(@as(?u8, 3), infoC.fields[0].default_value);
+    try testing.expectEqual(@as(u8, 3), @ptrCast(*const u8, infoC.fields[0].default_value.?).*);
     try testing.expectEqualSlices(u8, "y", infoC.fields[1].name);
     try testing.expectEqual(u32, infoC.fields[1].field_type);
-    try testing.expectEqual(@as(?u32, 5), infoC.fields[1].default_value);
+    try testing.expectEqual(@as(u32, 5), @ptrCast(*const u32, infoC.fields[1].default_value.?).*);
     try testing.expectEqual(@as(usize, 0), infoC.decls.len);
     try testing.expectEqual(@as(bool, false), infoC.is_tuple);
 }
test/compile_errors.zig
@@ -744,7 +744,7 @@ pub fn addCases(ctx: *TestContext) !void {
         \\        .address_space = .generic,
         \\        .child = u8,
         \\        .is_allowzero = false,
-        \\        .sentinel = 0,
+        \\        .sentinel = &@as(u8, 0),
         \\    }});
         \\}
     , &[_][]const u8{