Commit 85c69c5194

Andrew Kelley <andrew@ziglang.org>
2023-05-04 05:04:47
Type.isSlice: make it InternPool aware
1 parent fb16ad3
src/arch/aarch64/abi.zig
@@ -52,7 +52,7 @@ pub fn classifyType(ty: Type, mod: *const Module) Class {
             return .byval;
         },
         .Pointer => {
-            std.debug.assert(!ty.isSlice());
+            std.debug.assert(!ty.isSlice(mod));
             return .byval;
         },
         .ErrorUnion,
src/arch/arm/abi.zig
@@ -94,7 +94,7 @@ pub fn classifyType(ty: Type, mod: *const Module, ctx: Context) Class {
             return .byval;
         },
         .Pointer => {
-            assert(!ty.isSlice());
+            assert(!ty.isSlice(mod));
             return .byval;
         },
         .ErrorUnion,
src/arch/riscv64/abi.zig
@@ -52,7 +52,7 @@ pub fn classifyType(ty: Type, mod: *const Module) Class {
             return .byval;
         },
         .Pointer => {
-            std.debug.assert(!ty.isSlice());
+            std.debug.assert(!ty.isSlice(mod));
             return .byval;
         },
         .ErrorUnion,
src/arch/wasm/abi.zig
@@ -60,7 +60,7 @@ pub fn classifyType(ty: Type, mod: *const Module) [2]Class {
             return direct;
         },
         .Pointer => {
-            std.debug.assert(!ty.isSlice());
+            std.debug.assert(!ty.isSlice(mod));
             return direct;
         },
         .Union => {
src/arch/wasm/CodeGen.zig
@@ -1773,7 +1773,7 @@ fn isByRef(ty: Type, mod: *const Module) bool {
         },
         .Pointer => {
             // Slices act like struct and will be passed by reference
-            if (ty.isSlice()) return true;
+            if (ty.isSlice(mod)) return true;
             return false;
         },
     }
@@ -2396,7 +2396,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE
             },
         },
         .Pointer => {
-            if (ty.isSlice()) {
+            if (ty.isSlice(mod)) {
                 // store pointer first
                 // lower it to the stack so we do not have to store rhs into a local first
                 try func.emitWValue(lhs);
@@ -3010,11 +3010,11 @@ fn lowerParentPtrDecl(func: *CodeGen, ptr_val: Value, decl_index: Module.Decl.In
 }
 
 fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: Module.Decl.Index, offset: u32) InnerError!WValue {
-    if (tv.ty.isSlice()) {
+    const mod = func.bin_file.base.options.module.?;
+    if (tv.ty.isSlice(mod)) {
         return WValue{ .memory = try func.bin_file.lowerUnnamedConst(tv, decl_index) };
     }
 
-    const mod = func.bin_file.base.options.module.?;
     const decl = mod.declPtr(decl_index);
     if (decl.ty.zigTypeTag(mod) != .Fn and !decl.ty.hasRuntimeBitsIgnoreComptime(mod)) {
         return WValue{ .imm32 = 0xaaaaaaaa };
@@ -4182,7 +4182,7 @@ fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcod
             };
             try func.addMemArg(.i32_load8_u, .{ .offset = operand.offset() + offset, .alignment = 1 });
         }
-    } else if (payload_ty.isSlice()) {
+    } else if (payload_ty.isSlice(mod)) {
         switch (func.arch()) {
             .wasm32 => try func.addMemArg(.i32_load, .{ .offset = operand.offset(), .alignment = 4 }),
             .wasm64 => try func.addMemArg(.i64_load, .{ .offset = operand.offset(), .alignment = 8 }),
@@ -4455,10 +4455,11 @@ fn airArrayToSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
 }
 
 fn airPtrToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
+    const mod = func.bin_file.base.options.module.?;
     const un_op = func.air.instructions.items(.data)[inst].un_op;
     const operand = try func.resolveInst(un_op);
     const ptr_ty = func.typeOf(un_op);
-    const result = if (ptr_ty.isSlice())
+    const result = if (ptr_ty.isSlice(mod))
         try func.slicePtr(operand)
     else switch (operand) {
         // for stack offset, return a pointer to this offset.
@@ -4479,7 +4480,7 @@ fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
     const elem_size = elem_ty.abiSize(mod);
 
     // load pointer onto the stack
-    if (ptr_ty.isSlice()) {
+    if (ptr_ty.isSlice(mod)) {
         _ = try func.load(ptr, Type.usize, 0);
     } else {
         try func.lowerToStack(ptr);
@@ -4518,7 +4519,7 @@ fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
     const index = try func.resolveInst(bin_op.rhs);
 
     // load pointer onto the stack
-    if (ptr_ty.isSlice()) {
+    if (ptr_ty.isSlice(mod)) {
         _ = try func.load(ptr, Type.usize, 0);
     } else {
         try func.lowerToStack(ptr);
@@ -5441,7 +5442,8 @@ fn airFieldParentPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
 }
 
 fn sliceOrArrayPtr(func: *CodeGen, ptr: WValue, ptr_ty: Type) InnerError!WValue {
-    if (ptr_ty.isSlice()) {
+    const mod = func.bin_file.base.options.module.?;
+    if (ptr_ty.isSlice(mod)) {
         return func.slicePtr(ptr);
     } else {
         return ptr;
src/arch/x86_64/CodeGen.zig
@@ -8688,7 +8688,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
 
     var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined;
     const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(mod))
-        .{ .off = 0, .ty = if (pl_ty.isSlice()) pl_ty.slicePtrFieldType(&ptr_buf) else pl_ty }
+        .{ .off = 0, .ty = if (pl_ty.isSlice(mod)) pl_ty.slicePtrFieldType(&ptr_buf) else pl_ty }
     else
         .{ .off = @intCast(i32, pl_ty.abiSize(mod)), .ty = Type.bool };
 
@@ -8781,7 +8781,7 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue)
 
     var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined;
     const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(mod))
-        .{ .off = 0, .ty = if (pl_ty.isSlice()) pl_ty.slicePtrFieldType(&ptr_buf) else pl_ty }
+        .{ .off = 0, .ty = if (pl_ty.isSlice(mod)) pl_ty.slicePtrFieldType(&ptr_buf) else pl_ty }
     else
         .{ .off = @intCast(i32, pl_ty.abiSize(mod)), .ty = Type.bool };
 
src/codegen/c.zig
@@ -556,7 +556,7 @@ pub const DeclGen = struct {
         if (decl.val.castTag(.variable)) |var_payload|
             try dg.renderFwdDecl(decl_index, var_payload.data);
 
-        if (ty.isSlice()) {
+        if (ty.isSlice(mod)) {
             if (location == .StaticInitializer) {
                 try writer.writeByte('{');
             } else {
@@ -603,7 +603,7 @@ pub const DeclGen = struct {
     fn renderParentPtr(dg: *DeclGen, writer: anytype, ptr_val: Value, ptr_ty: Type, location: ValueRenderLocation) error{ OutOfMemory, AnalysisFail }!void {
         const mod = dg.module;
 
-        if (!ptr_ty.isSlice()) {
+        if (!ptr_ty.isSlice(mod)) {
             try writer.writeByte('(');
             try dg.renderType(writer, ptr_ty);
             try writer.writeByte(')');
@@ -776,7 +776,7 @@ pub const DeclGen = struct {
                     try dg.renderValue(writer, repr_ty, Value.undef, .FunctionArgument);
                     return writer.writeByte(')');
                 },
-                .Pointer => if (ty.isSlice()) {
+                .Pointer => if (ty.isSlice(mod)) {
                     if (!location.isInitializer()) {
                         try writer.writeByte('(');
                         try dg.renderType(writer, ty);
@@ -1045,7 +1045,7 @@ pub const DeclGen = struct {
                 return;
             },
             .Pointer => switch (val.tag()) {
-                .null_value, .zero => if (ty.isSlice()) {
+                .null_value, .zero => if (ty.isSlice(mod)) {
                     var slice_pl = Value.Payload.Slice{
                         .base = .{ .tag = .slice },
                         .data = .{ .ptr = val, .len = Value.undef },
@@ -5073,7 +5073,7 @@ fn airIsNull(
         TypedValue{ .ty = optional_ty, .val = Value.null }
     else if (payload_ty.zigTypeTag(mod) == .ErrorSet)
         TypedValue{ .ty = payload_ty, .val = Value.zero }
-    else if (payload_ty.isSlice() and optional_ty.optionalReprIsPayload(mod)) rhs: {
+    else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: {
         try writer.writeAll(".ptr");
         const slice_ptr_ty = payload_ty.slicePtrFieldType(&slice_ptr_buf);
         break :rhs TypedValue{ .ty = slice_ptr_ty, .val = Value.null };
@@ -5864,6 +5864,7 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue {
+    const mod = f.object.dg.module;
     const un_op = f.air.instructions.items(.data)[inst].un_op;
 
     const operand = try f.resolveInst(un_op);
@@ -5877,7 +5878,7 @@ fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue {
     try writer.writeAll(" = (");
     try f.renderType(writer, inst_ty);
     try writer.writeByte(')');
-    if (operand_ty.isSlice()) {
+    if (operand_ty.isSlice(mod)) {
         try f.writeCValueMember(writer, operand, .{ .identifier = "len" });
     } else {
         try f.writeCValue(writer, operand, .Other);
@@ -6272,7 +6273,8 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
 }
 
 fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !void {
-    if (ptr_ty.isSlice()) {
+    const mod = f.object.dg.module;
+    if (ptr_ty.isSlice(mod)) {
         try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" });
     } else {
         try f.writeCValue(writer, ptr, .FunctionArgument);
src/codegen/llvm.zig
@@ -1636,7 +1636,7 @@ pub const Object = struct {
                     return ptr_di_ty;
                 }
 
-                if (ty.isSlice()) {
+                if (ty.isSlice(mod)) {
                     var buf: Type.SlicePtrFieldTypeBuffer = undefined;
                     const ptr_ty = ty.slicePtrFieldType(&buf);
                     const len_ty = Type.usize;
@@ -2833,7 +2833,7 @@ pub const DeclGen = struct {
             },
             .Bool => return dg.context.intType(1),
             .Pointer => {
-                if (t.isSlice()) {
+                if (t.isSlice(mod)) {
                     var buf: Type.SlicePtrFieldTypeBuffer = undefined;
                     const ptr_type = t.slicePtrFieldType(&buf);
 
@@ -4110,7 +4110,7 @@ pub const DeclGen = struct {
                         }
                     },
                     .Pointer => {
-                        assert(parent_ty.isSlice());
+                        assert(parent_ty.isSlice(mod));
                         const indices: [2]*llvm.Value = .{
                             llvm_u32.constInt(0, .False),
                             llvm_u32.constInt(field_index, .False),
@@ -4184,7 +4184,7 @@ pub const DeclGen = struct {
         decl_index: Module.Decl.Index,
     ) Error!*llvm.Value {
         const mod = self.module;
-        if (tv.ty.isSlice()) {
+        if (tv.ty.isSlice(mod)) {
             var buf: Type.SlicePtrFieldTypeBuffer = undefined;
             const ptr_ty = tv.ty.slicePtrFieldType(&buf);
             var slice_len: Value.Payload.U64 = .{
@@ -5794,7 +5794,8 @@ pub const FuncGen = struct {
     }
 
     fn sliceOrArrayPtr(fg: *FuncGen, ptr: *llvm.Value, ty: Type) *llvm.Value {
-        if (ty.isSlice()) {
+        const mod = fg.dg.module;
+        if (ty.isSlice(mod)) {
             return fg.builder.buildExtractValue(ptr, 0, "");
         } else {
             return ptr;
@@ -6669,7 +6670,7 @@ pub const FuncGen = struct {
                 self.builder.buildLoad(optional_llvm_ty, operand, "")
             else
                 operand;
-            if (payload_ty.isSlice()) {
+            if (payload_ty.isSlice(mod)) {
                 const slice_ptr = self.builder.buildExtractValue(loaded, 0, "");
                 var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined;
                 const ptr_ty = try self.dg.lowerType(payload_ty.slicePtrFieldType(&slice_buf));
@@ -10864,7 +10865,7 @@ const ParamTypeIterator = struct {
                 it.zig_index += 1;
                 it.llvm_index += 1;
                 var buf: Type.Payload.ElemType = undefined;
-                if (ty.isSlice() or (ty.zigTypeTag(mod) == .Optional and ty.optionalChild(&buf).isSlice())) {
+                if (ty.isSlice(mod) or (ty.zigTypeTag(mod) == .Optional and ty.optionalChild(&buf).isSlice(mod))) {
                     it.llvm_index += 1;
                     return .slice;
                 } else if (isByRef(ty, mod)) {
src/codegen/spirv.zig
@@ -2980,12 +2980,12 @@ pub const DeclGen = struct {
             // Pointer payload represents nullability: pointer or slice.
 
             var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined;
-            const ptr_ty = if (payload_ty.isSlice())
+            const ptr_ty = if (payload_ty.isSlice(mod))
                 payload_ty.slicePtrFieldType(&ptr_buf)
             else
                 payload_ty;
 
-            const ptr_id = if (payload_ty.isSlice())
+            const ptr_id = if (payload_ty.isSlice(mod))
                 try self.extractField(Type.bool, operand_id, 0)
             else
                 operand_id;
src/link/Dwarf.zig
@@ -258,7 +258,7 @@ pub const DeclState = struct {
                 }
             },
             .Pointer => {
-                if (ty.isSlice()) {
+                if (ty.isSlice(mod)) {
                     // Slices are structs: struct { .ptr = *, .len = N }
                     const ptr_bits = target.ptrBitWidth();
                     const ptr_bytes = @intCast(u8, @divExact(ptr_bits, 8));
src/codegen.zig
@@ -317,11 +317,11 @@ pub fn generateSymbol(
                 switch (target.ptrBitWidth()) {
                     32 => {
                         mem.writeInt(u32, try code.addManyAsArray(4), 0, endian);
-                        if (typed_value.ty.isSlice()) try code.appendNTimes(0xaa, 4);
+                        if (typed_value.ty.isSlice(mod)) try code.appendNTimes(0xaa, 4);
                     },
                     64 => {
                         mem.writeInt(u64, try code.addManyAsArray(8), 0, endian);
-                        if (typed_value.ty.isSlice()) try code.appendNTimes(0xaa, 8);
+                        if (typed_value.ty.isSlice(mod)) try code.appendNTimes(0xaa, 8);
                     },
                     else => unreachable,
                 }
@@ -845,7 +845,7 @@ fn lowerParentPtr(
                 debug_output,
                 reloc_info.offset(@intCast(u32, switch (field_ptr.container_ty.zigTypeTag(mod)) {
                     .Pointer => offset: {
-                        assert(field_ptr.container_ty.isSlice());
+                        assert(field_ptr.container_ty.isSlice(mod));
                         var buf: Type.SlicePtrFieldTypeBuffer = undefined;
                         break :offset switch (field_ptr.field_index) {
                             0 => 0,
@@ -946,7 +946,7 @@ fn lowerDeclRef(
 ) CodeGenError!Result {
     const target = bin_file.options.target;
     const mod = bin_file.options.module.?;
-    if (typed_value.ty.isSlice()) {
+    if (typed_value.ty.isSlice(mod)) {
         // generate ptr
         var buf: Type.SlicePtrFieldTypeBuffer = undefined;
         const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf);
@@ -1174,7 +1174,7 @@ pub fn genTypedValue(
     const target = bin_file.options.target;
     const ptr_bits = target.ptrBitWidth();
 
-    if (!typed_value.ty.isSlice()) {
+    if (!typed_value.ty.isSlice(mod)) {
         if (typed_value.val.castTag(.variable)) |payload| {
             return genDeclRef(bin_file, src_loc, typed_value, payload.data.owner_decl);
         }
src/InternPool.zig
@@ -629,7 +629,7 @@ pub const Tag = enum(u8) {
     /// A vector type.
     /// data is payload to Vector.
     type_vector,
-    /// A pointer type along with all its bells and whistles.
+    /// A fully explicitly specified pointer type.
     /// data is payload to Pointer.
     type_pointer,
     /// An optional type.
@@ -682,13 +682,13 @@ pub const Tag = enum(u8) {
     /// An enum tag identified by a negative integer value.
     /// data is a limbs index to Int.
     enum_tag_negative,
-    /// A float value that can be represented by f32.
+    /// An f32 value.
     /// data is float value bitcasted to u32.
     float_f32,
-    /// A float value that can be represented by f64.
+    /// An f64 value.
     /// data is payload index to Float64.
     float_f64,
-    /// A float value that can be represented by f128.
+    /// An f128 value.
     /// data is payload index to Float128.
     float_f128,
     /// An extern function.
@@ -871,7 +871,47 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
         .simple_type => .{ .simple_type = @intToEnum(SimpleType, data) },
         .simple_value => .{ .simple_value = @intToEnum(SimpleValue, data) },
 
-        else => @panic("TODO"),
+        .type_vector => {
+            const vector_info = ip.extraData(Vector, data);
+            return .{ .vector_type = .{
+                .len = vector_info.len,
+                .child = vector_info.child,
+            } };
+        },
+
+        .type_pointer => {
+            const ptr_info = ip.extraData(Pointer, data);
+            return .{ .ptr_type = .{
+                .elem_type = ptr_info.child,
+                .sentinel = ptr_info.sentinel,
+                .alignment = ptr_info.flags.alignment,
+                .size = ptr_info.flags.size,
+                .is_const = ptr_info.flags.is_const,
+                .is_volatile = ptr_info.flags.is_volatile,
+                .is_allowzero = ptr_info.flags.is_allowzero,
+                .address_space = ptr_info.flags.address_space,
+            } };
+        },
+
+        .type_optional => .{ .optional_type = .{ .payload_type = @intToEnum(Index, data) } },
+
+        .type_error_union => @panic("TODO"),
+        .type_enum_simple => @panic("TODO"),
+        .simple_internal => @panic("TODO"),
+        .int_small_u32 => @panic("TODO"),
+        .int_small_i32 => @panic("TODO"),
+        .int_small_usize => @panic("TODO"),
+        .int_small_comptime_unsigned => @panic("TODO"),
+        .int_small_comptime_signed => @panic("TODO"),
+        .int_positive => @panic("TODO"),
+        .int_negative => @panic("TODO"),
+        .enum_tag_positive => @panic("TODO"),
+        .enum_tag_negative => @panic("TODO"),
+        .float_f32 => @panic("TODO"),
+        .float_f64 => @panic("TODO"),
+        .float_f128 => @panic("TODO"),
+        .extern_func => @panic("TODO"),
+        .func => @panic("TODO"),
     };
 }
 
src/Sema.zig
@@ -2030,7 +2030,7 @@ fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty
             ty.fmt(mod),
         });
         errdefer msg.destroy(sema.gpa);
-        if (ty.isSlice()) {
+        if (ty.isSlice(mod)) {
             try sema.errNote(block, src, msg, "inferred array length is specified with an underscore: '[_]{}'", .{ty.elemType2(mod).fmt(mod)});
         }
         break :msg msg;
@@ -10359,7 +10359,7 @@ fn zirSwitchCond(
         .ErrorSet,
         .Enum,
         => {
-            if (operand_ty.isSlice()) {
+            if (operand_ty.isSlice(mod)) {
                 return sema.fail(block, src, "switch on type '{}'", .{operand_ty.fmt(sema.mod)});
             }
             if ((try sema.typeHasOnePossibleValue(operand_ty))) |opv| {
@@ -12017,7 +12017,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
     const ty = try sema.resolveTypeFields(unresolved_ty);
 
     const has_field = hf: {
-        if (ty.isSlice()) {
+        if (ty.isSlice(mod)) {
             if (mem.eql(u8, field_name, "ptr")) break :hf true;
             if (mem.eql(u8, field_name, "len")) break :hf true;
             break :hf false;
@@ -20020,8 +20020,8 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
         return sema.failWithOwnedErrorMsg(msg);
     }
 
-    const dest_is_slice = dest_ty.isSlice();
-    const operand_is_slice = operand_ty.isSlice();
+    const dest_is_slice = dest_ty.isSlice(mod);
+    const operand_is_slice = operand_ty.isSlice(mod);
     if (dest_is_slice and !operand_is_slice) {
         return sema.fail(block, dest_ty_src, "illegal pointer cast to slice", .{});
     }
@@ -20274,14 +20274,14 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
             Type.usize,
             Value.initPayload(&val_payload.base),
         );
-        const actual_ptr = if (ptr_ty.isSlice())
+        const actual_ptr = if (ptr_ty.isSlice(mod))
             try sema.analyzeSlicePtr(block, ptr_src, ptr, ptr_ty)
         else
             ptr;
         const ptr_int = try block.addUnOp(.ptrtoint, actual_ptr);
         const remainder = try block.addBinOp(.bit_and, ptr_int, align_minus_1);
         const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize);
-        const ok = if (ptr_ty.isSlice()) ok: {
+        const ok = if (ptr_ty.isSlice(mod)) ok: {
             const len = try sema.analyzeSliceLen(block, ptr_src, ptr);
             const len_zero = try block.addBinOp(.cmp_eq, len, .zero_usize);
             break :ok try block.addBinOp(.bit_or, len_zero, is_aligned);
@@ -22336,7 +22336,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
         // Change the src from slice to a many pointer, to avoid multiple ptr
         // slice extractions in AIR instructions.
         const new_src_ptr_ty = sema.typeOf(new_src_ptr);
-        if (new_src_ptr_ty.isSlice()) {
+        if (new_src_ptr_ty.isSlice(mod)) {
             new_src_ptr = try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty);
         }
     } else if (dest_len == .none and len_val == null) {
@@ -22344,7 +22344,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
         const dest_ptr_ptr = try sema.analyzeRef(block, dest_src, new_dest_ptr);
         new_dest_ptr = try sema.analyzeSlice(block, dest_src, dest_ptr_ptr, .zero, src_len, .none, .unneeded, dest_src, dest_src, dest_src, false);
         const new_src_ptr_ty = sema.typeOf(new_src_ptr);
-        if (new_src_ptr_ty.isSlice()) {
+        if (new_src_ptr_ty.isSlice(mod)) {
             new_src_ptr = try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty);
         }
     }
@@ -22363,7 +22363,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
         // Extract raw pointer from dest slice. The AIR instructions could support them, but
         // it would cause redundant machine code instructions.
         const new_dest_ptr_ty = sema.typeOf(new_dest_ptr);
-        const raw_dest_ptr = if (new_dest_ptr_ty.isSlice())
+        const raw_dest_ptr = if (new_dest_ptr_ty.isSlice(mod))
             try sema.analyzeSlicePtr(block, dest_src, new_dest_ptr, new_dest_ptr_ty)
         else
             new_dest_ptr;
@@ -23383,7 +23383,7 @@ fn validateExternType(
         .Float,
         .AnyFrame,
         => return true,
-        .Pointer => return !(ty.isSlice() or try sema.typeRequiresComptime(ty)),
+        .Pointer => return !(ty.isSlice(mod) or try sema.typeRequiresComptime(ty)),
         .Int => switch (ty.intInfo(mod).bits) {
             8, 16, 32, 64, 128 => return true,
             else => return false,
@@ -23448,7 +23448,7 @@ fn explainWhyTypeIsNotExtern(
         => return,
 
         .Pointer => {
-            if (ty.isSlice()) {
+            if (ty.isSlice(mod)) {
                 try mod.errNoteNonLazy(src_loc, msg, "slices have no guaranteed in-memory representation", .{});
             } else {
                 const pointee_ty = ty.childType();
@@ -23523,7 +23523,7 @@ fn validatePackedType(ty: Type, mod: *const Module) bool {
         .Vector,
         .Enum,
         => return true,
-        .Pointer => return !ty.isSlice(),
+        .Pointer => return !ty.isSlice(mod),
         .Struct, .Union => return ty.containerLayout() == .Packed,
     }
 }
@@ -23803,7 +23803,7 @@ fn panicSentinelMismatch(
     const expected_sentinel = try sema.addConstant(sentinel_ty, expected_sentinel_val);
 
     const ptr_ty = sema.typeOf(ptr);
-    const actual_sentinel = if (ptr_ty.isSlice())
+    const actual_sentinel = if (ptr_ty.isSlice(mod))
         try parent_block.addBinOp(.slice_elem_val, ptr, sentinel_index)
     else blk: {
         const elem_ptr_ty = try sema.elemPtrType(ptr_ty, null);
@@ -24064,7 +24064,7 @@ fn fieldVal(
                     const msg = msg: {
                         const msg = try sema.errMsg(block, src, "type '{}' has no members", .{child_type.fmt(sema.mod)});
                         errdefer msg.destroy(sema.gpa);
-                        if (child_type.isSlice()) try sema.errNote(block, src, msg, "slice values have 'len' and 'ptr' members", .{});
+                        if (child_type.isSlice(mod)) try sema.errNote(block, src, msg, "slice values have 'len' and 'ptr' members", .{});
                         if (child_type.zigTypeTag(mod) == .Array) try sema.errNote(block, src, msg, "array values have 'len' member", .{});
                         break :msg msg;
                     };
@@ -24140,7 +24140,7 @@ fn fieldPtr(
                 );
             }
         },
-        .Pointer => if (inner_ty.isSlice()) {
+        .Pointer => if (inner_ty.isSlice(mod)) {
             const inner_ptr = if (is_pointer_to)
                 try sema.analyzeLoad(block, src, object_ptr, object_ptr_src)
             else
@@ -25743,8 +25743,8 @@ fn coerceExtra(
                     } };
                     break :pointer;
                 }
-                if (dest_ty.isSlice()) break :to_anyopaque;
-                if (inst_ty.isSlice()) {
+                if (dest_ty.isSlice(mod)) break :to_anyopaque;
+                if (inst_ty.isSlice(mod)) {
                     in_memory_result = .{ .slice_to_anyopaque = .{
                         .actual = inst_ty,
                         .wanted = dest_ty,
@@ -25885,7 +25885,7 @@ fn coerceExtra(
                     return sema.coerceTupleToSlicePtrs(block, dest_ty, dest_ty_src, inst, inst_src);
                 },
                 .Many => p: {
-                    if (!inst_ty.isSlice()) break :p;
+                    if (!inst_ty.isSlice(mod)) break :p;
                     if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :p;
                     const inst_info = inst_ty.ptrInfo().data;
 
@@ -26651,7 +26651,7 @@ fn coerceInMemoryAllowed(
     }
 
     // Slices
-    if (dest_ty.isSlice() and src_ty.isSlice()) {
+    if (dest_ty.isSlice(mod) and src_ty.isSlice(mod)) {
         return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_ty, src_ty, dest_is_mut, target, dest_src, src_src);
     }
 
@@ -27744,7 +27744,7 @@ fn beginComptimePtrMutation(
                                 );
                             },
                             .Pointer => {
-                                assert(parent.ty.isSlice());
+                                assert(parent.ty.isSlice(mod));
                                 val_ptr.* = try Value.Tag.slice.create(arena, .{
                                     .ptr = Value.undef,
                                     .len = Value.undef,
@@ -28187,7 +28187,7 @@ fn beginComptimePtrLoad(
                 break :blk deref;
             }
 
-            if (field_ptr.container_ty.isSlice()) {
+            if (field_ptr.container_ty.isSlice(mod)) {
                 const slice_val = tv.val.castTag(.slice).?.data;
                 deref.pointee = switch (field_index) {
                     Value.Payload.Slice.ptr_index => TypedValue{
@@ -28442,13 +28442,13 @@ fn coerceCompatiblePtrs(
     if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero(mod) and
         (try sema.typeHasRuntimeBits(dest_ty.elemType2(mod)) or dest_ty.elemType2(mod).zigTypeTag(mod) == .Fn))
     {
-        const actual_ptr = if (inst_ty.isSlice())
+        const actual_ptr = if (inst_ty.isSlice(mod))
             try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty)
         else
             inst;
         const ptr_int = try block.addUnOp(.ptrtoint, actual_ptr);
         const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize);
-        const ok = if (inst_ty.isSlice()) ok: {
+        const ok = if (inst_ty.isSlice(mod)) ok: {
             const len = try sema.analyzeSliceLen(block, inst_src, inst);
             const len_zero = try block.addBinOp(.cmp_eq, len, .zero_usize);
             break :ok try block.addBinOp(.bit_or, len_zero, is_non_zero);
@@ -29548,7 +29548,7 @@ fn analyzeSlice(
         else => return sema.fail(block, src, "slice of non-array type '{}'", .{ptr_ptr_child_ty.fmt(mod)}),
     }
 
-    const ptr = if (slice_ty.isSlice())
+    const ptr = if (slice_ty.isSlice(mod))
         try sema.analyzeSlicePtr(block, ptr_src, ptr_or_slice, slice_ty)
     else
         ptr_or_slice;
@@ -29605,7 +29605,7 @@ fn analyzeSlice(
             }
 
             break :e try sema.addConstant(Type.usize, len_val);
-        } else if (slice_ty.isSlice()) {
+        } else if (slice_ty.isSlice(mod)) {
             if (!end_is_len) {
                 const end = if (by_length) end: {
                     const len = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
@@ -29778,7 +29778,7 @@ fn analyzeSlice(
                     try sema.addSafetyCheck(block, is_non_null, .unwrap_null);
                 }
 
-                if (slice_ty.isSlice()) {
+                if (slice_ty.isSlice(mod)) {
                     const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice);
                     const actual_len = if (slice_ty.sentinel() == null)
                         slice_len_inst
@@ -29840,7 +29840,7 @@ fn analyzeSlice(
         // requirement: end <= len
         const opt_len_inst = if (array_ty.zigTypeTag(mod) == .Array)
             try sema.addIntUnsigned(Type.usize, array_ty.arrayLenIncludingSentinel())
-        else if (slice_ty.isSlice()) blk: {
+        else if (slice_ty.isSlice(mod)) blk: {
             if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| {
                 // we don't need to add one for sentinels because the
                 // underlying value data includes the sentinel
src/type.zig
@@ -229,7 +229,7 @@ pub const Type = struct {
             .Frame,
             => false,
 
-            .Pointer => !ty.isSlice() and (is_equality_cmp or ty.isCPtr()),
+            .Pointer => !ty.isSlice(mod) and (is_equality_cmp or ty.isCPtr()),
             .Optional => {
                 if (!is_equality_cmp) return false;
                 var buf: Payload.ElemType = undefined;
@@ -369,209 +369,212 @@ pub const Type = struct {
     }
 
     pub fn ptrInfo(self: Type) Payload.Pointer {
-        switch (self.tag()) {
-            .single_const_pointer_to_comptime_int => return .{ .data = .{
-                .pointee_type = Type.comptime_int,
-                .sentinel = null,
-                .@"align" = 0,
-                .@"addrspace" = .generic,
-                .bit_offset = 0,
-                .host_size = 0,
-                .@"allowzero" = false,
-                .mutable = false,
-                .@"volatile" = false,
-                .size = .One,
-            } },
-            .const_slice_u8 => return .{ .data = .{
-                .pointee_type = Type.u8,
-                .sentinel = null,
-                .@"align" = 0,
-                .@"addrspace" = .generic,
-                .bit_offset = 0,
-                .host_size = 0,
-                .@"allowzero" = false,
-                .mutable = false,
-                .@"volatile" = false,
-                .size = .Slice,
-            } },
-            .const_slice_u8_sentinel_0 => return .{ .data = .{
-                .pointee_type = Type.u8,
-                .sentinel = Value.zero,
-                .@"align" = 0,
-                .@"addrspace" = .generic,
-                .bit_offset = 0,
-                .host_size = 0,
-                .@"allowzero" = false,
-                .mutable = false,
-                .@"volatile" = false,
-                .size = .Slice,
-            } },
-            .single_const_pointer => return .{ .data = .{
-                .pointee_type = self.castPointer().?.data,
-                .sentinel = null,
-                .@"align" = 0,
-                .@"addrspace" = .generic,
-                .bit_offset = 0,
-                .host_size = 0,
-                .@"allowzero" = false,
-                .mutable = false,
-                .@"volatile" = false,
-                .size = .One,
-            } },
-            .single_mut_pointer => return .{ .data = .{
-                .pointee_type = self.castPointer().?.data,
-                .sentinel = null,
-                .@"align" = 0,
-                .@"addrspace" = .generic,
-                .bit_offset = 0,
-                .host_size = 0,
-                .@"allowzero" = false,
-                .mutable = true,
-                .@"volatile" = false,
-                .size = .One,
-            } },
-            .many_const_pointer => return .{ .data = .{
-                .pointee_type = self.castPointer().?.data,
-                .sentinel = null,
-                .@"align" = 0,
-                .@"addrspace" = .generic,
-                .bit_offset = 0,
-                .host_size = 0,
-                .@"allowzero" = false,
-                .mutable = false,
-                .@"volatile" = false,
-                .size = .Many,
-            } },
-            .manyptr_const_u8 => return .{ .data = .{
-                .pointee_type = Type.u8,
-                .sentinel = null,
-                .@"align" = 0,
-                .@"addrspace" = .generic,
-                .bit_offset = 0,
-                .host_size = 0,
-                .@"allowzero" = false,
-                .mutable = false,
-                .@"volatile" = false,
-                .size = .Many,
-            } },
-            .manyptr_const_u8_sentinel_0 => return .{ .data = .{
-                .pointee_type = Type.u8,
-                .sentinel = Value.zero,
-                .@"align" = 0,
-                .@"addrspace" = .generic,
-                .bit_offset = 0,
-                .host_size = 0,
-                .@"allowzero" = false,
-                .mutable = false,
-                .@"volatile" = false,
-                .size = .Many,
-            } },
-            .many_mut_pointer => return .{ .data = .{
-                .pointee_type = self.castPointer().?.data,
-                .sentinel = null,
-                .@"align" = 0,
-                .@"addrspace" = .generic,
-                .bit_offset = 0,
-                .host_size = 0,
-                .@"allowzero" = false,
-                .mutable = true,
-                .@"volatile" = false,
-                .size = .Many,
-            } },
-            .manyptr_u8 => return .{ .data = .{
-                .pointee_type = Type.u8,
-                .sentinel = null,
-                .@"align" = 0,
-                .@"addrspace" = .generic,
-                .bit_offset = 0,
-                .host_size = 0,
-                .@"allowzero" = false,
-                .mutable = true,
-                .@"volatile" = false,
-                .size = .Many,
-            } },
-            .c_const_pointer => return .{ .data = .{
-                .pointee_type = self.castPointer().?.data,
-                .sentinel = null,
-                .@"align" = 0,
-                .@"addrspace" = .generic,
-                .bit_offset = 0,
-                .host_size = 0,
-                .@"allowzero" = true,
-                .mutable = false,
-                .@"volatile" = false,
-                .size = .C,
-            } },
-            .c_mut_pointer => return .{ .data = .{
-                .pointee_type = self.castPointer().?.data,
-                .sentinel = null,
-                .@"align" = 0,
-                .@"addrspace" = .generic,
-                .bit_offset = 0,
-                .host_size = 0,
-                .@"allowzero" = true,
-                .mutable = true,
-                .@"volatile" = false,
-                .size = .C,
-            } },
-            .const_slice => return .{ .data = .{
-                .pointee_type = self.castPointer().?.data,
-                .sentinel = null,
-                .@"align" = 0,
-                .@"addrspace" = .generic,
-                .bit_offset = 0,
-                .host_size = 0,
-                .@"allowzero" = false,
-                .mutable = false,
-                .@"volatile" = false,
-                .size = .Slice,
-            } },
-            .mut_slice => return .{ .data = .{
-                .pointee_type = self.castPointer().?.data,
-                .sentinel = null,
-                .@"align" = 0,
-                .@"addrspace" = .generic,
-                .bit_offset = 0,
-                .host_size = 0,
-                .@"allowzero" = false,
-                .mutable = true,
-                .@"volatile" = false,
-                .size = .Slice,
-            } },
-
-            .pointer => return self.castTag(.pointer).?.*,
-
-            .optional_single_mut_pointer => return .{ .data = .{
-                .pointee_type = self.castPointer().?.data,
-                .sentinel = null,
-                .@"align" = 0,
-                .@"addrspace" = .generic,
-                .bit_offset = 0,
-                .host_size = 0,
-                .@"allowzero" = false,
-                .mutable = true,
-                .@"volatile" = false,
-                .size = .One,
-            } },
-            .optional_single_const_pointer => return .{ .data = .{
-                .pointee_type = self.castPointer().?.data,
-                .sentinel = null,
-                .@"align" = 0,
-                .@"addrspace" = .generic,
-                .bit_offset = 0,
-                .host_size = 0,
-                .@"allowzero" = false,
-                .mutable = false,
-                .@"volatile" = false,
-                .size = .One,
-            } },
-            .optional => {
-                var buf: Payload.ElemType = undefined;
-                const child_type = self.optionalChild(&buf);
-                return child_type.ptrInfo();
-            },
+        switch (self.ip_index) {
+            .none => switch (self.tag()) {
+                .single_const_pointer_to_comptime_int => return .{ .data = .{
+                    .pointee_type = Type.comptime_int,
+                    .sentinel = null,
+                    .@"align" = 0,
+                    .@"addrspace" = .generic,
+                    .bit_offset = 0,
+                    .host_size = 0,
+                    .@"allowzero" = false,
+                    .mutable = false,
+                    .@"volatile" = false,
+                    .size = .One,
+                } },
+                .const_slice_u8 => return .{ .data = .{
+                    .pointee_type = Type.u8,
+                    .sentinel = null,
+                    .@"align" = 0,
+                    .@"addrspace" = .generic,
+                    .bit_offset = 0,
+                    .host_size = 0,
+                    .@"allowzero" = false,
+                    .mutable = false,
+                    .@"volatile" = false,
+                    .size = .Slice,
+                } },
+                .const_slice_u8_sentinel_0 => return .{ .data = .{
+                    .pointee_type = Type.u8,
+                    .sentinel = Value.zero,
+                    .@"align" = 0,
+                    .@"addrspace" = .generic,
+                    .bit_offset = 0,
+                    .host_size = 0,
+                    .@"allowzero" = false,
+                    .mutable = false,
+                    .@"volatile" = false,
+                    .size = .Slice,
+                } },
+                .single_const_pointer => return .{ .data = .{
+                    .pointee_type = self.castPointer().?.data,
+                    .sentinel = null,
+                    .@"align" = 0,
+                    .@"addrspace" = .generic,
+                    .bit_offset = 0,
+                    .host_size = 0,
+                    .@"allowzero" = false,
+                    .mutable = false,
+                    .@"volatile" = false,
+                    .size = .One,
+                } },
+                .single_mut_pointer => return .{ .data = .{
+                    .pointee_type = self.castPointer().?.data,
+                    .sentinel = null,
+                    .@"align" = 0,
+                    .@"addrspace" = .generic,
+                    .bit_offset = 0,
+                    .host_size = 0,
+                    .@"allowzero" = false,
+                    .mutable = true,
+                    .@"volatile" = false,
+                    .size = .One,
+                } },
+                .many_const_pointer => return .{ .data = .{
+                    .pointee_type = self.castPointer().?.data,
+                    .sentinel = null,
+                    .@"align" = 0,
+                    .@"addrspace" = .generic,
+                    .bit_offset = 0,
+                    .host_size = 0,
+                    .@"allowzero" = false,
+                    .mutable = false,
+                    .@"volatile" = false,
+                    .size = .Many,
+                } },
+                .manyptr_const_u8 => return .{ .data = .{
+                    .pointee_type = Type.u8,
+                    .sentinel = null,
+                    .@"align" = 0,
+                    .@"addrspace" = .generic,
+                    .bit_offset = 0,
+                    .host_size = 0,
+                    .@"allowzero" = false,
+                    .mutable = false,
+                    .@"volatile" = false,
+                    .size = .Many,
+                } },
+                .manyptr_const_u8_sentinel_0 => return .{ .data = .{
+                    .pointee_type = Type.u8,
+                    .sentinel = Value.zero,
+                    .@"align" = 0,
+                    .@"addrspace" = .generic,
+                    .bit_offset = 0,
+                    .host_size = 0,
+                    .@"allowzero" = false,
+                    .mutable = false,
+                    .@"volatile" = false,
+                    .size = .Many,
+                } },
+                .many_mut_pointer => return .{ .data = .{
+                    .pointee_type = self.castPointer().?.data,
+                    .sentinel = null,
+                    .@"align" = 0,
+                    .@"addrspace" = .generic,
+                    .bit_offset = 0,
+                    .host_size = 0,
+                    .@"allowzero" = false,
+                    .mutable = true,
+                    .@"volatile" = false,
+                    .size = .Many,
+                } },
+                .manyptr_u8 => return .{ .data = .{
+                    .pointee_type = Type.u8,
+                    .sentinel = null,
+                    .@"align" = 0,
+                    .@"addrspace" = .generic,
+                    .bit_offset = 0,
+                    .host_size = 0,
+                    .@"allowzero" = false,
+                    .mutable = true,
+                    .@"volatile" = false,
+                    .size = .Many,
+                } },
+                .c_const_pointer => return .{ .data = .{
+                    .pointee_type = self.castPointer().?.data,
+                    .sentinel = null,
+                    .@"align" = 0,
+                    .@"addrspace" = .generic,
+                    .bit_offset = 0,
+                    .host_size = 0,
+                    .@"allowzero" = true,
+                    .mutable = false,
+                    .@"volatile" = false,
+                    .size = .C,
+                } },
+                .c_mut_pointer => return .{ .data = .{
+                    .pointee_type = self.castPointer().?.data,
+                    .sentinel = null,
+                    .@"align" = 0,
+                    .@"addrspace" = .generic,
+                    .bit_offset = 0,
+                    .host_size = 0,
+                    .@"allowzero" = true,
+                    .mutable = true,
+                    .@"volatile" = false,
+                    .size = .C,
+                } },
+                .const_slice => return .{ .data = .{
+                    .pointee_type = self.castPointer().?.data,
+                    .sentinel = null,
+                    .@"align" = 0,
+                    .@"addrspace" = .generic,
+                    .bit_offset = 0,
+                    .host_size = 0,
+                    .@"allowzero" = false,
+                    .mutable = false,
+                    .@"volatile" = false,
+                    .size = .Slice,
+                } },
+                .mut_slice => return .{ .data = .{
+                    .pointee_type = self.castPointer().?.data,
+                    .sentinel = null,
+                    .@"align" = 0,
+                    .@"addrspace" = .generic,
+                    .bit_offset = 0,
+                    .host_size = 0,
+                    .@"allowzero" = false,
+                    .mutable = true,
+                    .@"volatile" = false,
+                    .size = .Slice,
+                } },
+
+                .pointer => return self.castTag(.pointer).?.*,
+
+                .optional_single_mut_pointer => return .{ .data = .{
+                    .pointee_type = self.castPointer().?.data,
+                    .sentinel = null,
+                    .@"align" = 0,
+                    .@"addrspace" = .generic,
+                    .bit_offset = 0,
+                    .host_size = 0,
+                    .@"allowzero" = false,
+                    .mutable = true,
+                    .@"volatile" = false,
+                    .size = .One,
+                } },
+                .optional_single_const_pointer => return .{ .data = .{
+                    .pointee_type = self.castPointer().?.data,
+                    .sentinel = null,
+                    .@"align" = 0,
+                    .@"addrspace" = .generic,
+                    .bit_offset = 0,
+                    .host_size = 0,
+                    .@"allowzero" = false,
+                    .mutable = false,
+                    .@"volatile" = false,
+                    .size = .One,
+                } },
+                .optional => {
+                    var buf: Payload.ElemType = undefined;
+                    const child_type = self.optionalChild(&buf);
+                    return child_type.ptrInfo();
+                },
 
-            else => unreachable,
+                else => unreachable,
+            },
+            else => @panic("TODO"),
         }
     }
 
@@ -3712,17 +3715,23 @@ pub const Type = struct {
         };
     }
 
-    pub fn isSlice(self: Type) bool {
-        return switch (self.tag()) {
-            .const_slice,
-            .mut_slice,
-            .const_slice_u8,
-            .const_slice_u8_sentinel_0,
-            => true,
+    pub fn isSlice(ty: Type, mod: *const Module) bool {
+        return switch (ty.ip_index) {
+            .none => switch (ty.tag()) {
+                .const_slice,
+                .mut_slice,
+                .const_slice_u8,
+                .const_slice_u8_sentinel_0,
+                => true,
 
-            .pointer => self.castTag(.pointer).?.data.size == .Slice,
+                .pointer => ty.castTag(.pointer).?.data.size == .Slice,
 
-            else => false,
+                else => false,
+            },
+            else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
+                .ptr_type => |ptr_type| ptr_type.size == .Slice,
+                else => false,
+            },
         };
     }
 
src/TypedValue.zig
@@ -259,7 +259,7 @@ pub fn print(
             } else if (field_ptr.container_ty.zigTypeTag(mod) == .Union) {
                 const field_name = field_ptr.container_ty.unionFields().keys()[field_ptr.field_index];
                 return writer.print(".{s}", .{field_name});
-            } else if (field_ptr.container_ty.isSlice()) {
+            } else if (field_ptr.container_ty.isSlice(mod)) {
                 switch (field_ptr.field_index) {
                     Value.Payload.Slice.ptr_index => return writer.writeAll(".ptr"),
                     Value.Payload.Slice.len_index => return writer.writeAll(".len"),
src/value.zig
@@ -1144,7 +1144,7 @@ pub const Value = struct {
                 },
             },
             .Pointer => {
-                if (ty.isSlice()) return error.IllDefinedMemoryLayout;
+                if (ty.isSlice(mod)) return error.IllDefinedMemoryLayout;
                 if (val.isDeclRef()) return error.ReinterpretDeclRef;
                 return val.writeToMemory(Type.usize, mod, buffer);
             },
@@ -1261,7 +1261,7 @@ pub const Value = struct {
                 },
             },
             .Pointer => {
-                assert(!ty.isSlice()); // No well defined layout.
+                assert(!ty.isSlice(mod)); // No well defined layout.
                 if (val.isDeclRef()) return error.ReinterpretDeclRef;
                 return val.writeToPackedMemory(Type.usize, mod, buffer, bit_offset);
             },
@@ -1381,7 +1381,7 @@ pub const Value = struct {
                 return Value.initPayload(&payload.base);
             },
             .Pointer => {
-                assert(!ty.isSlice()); // No well defined layout.
+                assert(!ty.isSlice(mod)); // No well defined layout.
                 return readFromMemory(Type.usize, mod, buffer, arena);
             },
             .Optional => {
@@ -1478,7 +1478,7 @@ pub const Value = struct {
                 },
             },
             .Pointer => {
-                assert(!ty.isSlice()); // No well defined layout.
+                assert(!ty.isSlice(mod)); // No well defined layout.
                 return readFromPackedMemory(Type.usize, mod, buffer, bit_offset, arena);
             },
             .Optional => {