Commit 1dc01f1140

Jacob Young <jacobly0@users.noreply.github.com>
2023-05-27 00:56:31
InternPool: fix build-exe and compiler-rt crashes
1 parent 9cd0ca9
src/arch/x86_64/CodeGen.zig
@@ -4895,7 +4895,7 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
     });
 
     const sign_val = switch (tag) {
-        .neg => try vec_ty.minInt(mod),
+        .neg => try vec_ty.minInt(mod, vec_ty),
         .fabs => try vec_ty.maxInt(mod, vec_ty),
         else => unreachable,
     };
src/codegen/c.zig
@@ -6723,7 +6723,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
         },
         .Max => switch (scalar_ty.zigTypeTag(mod)) {
             .Bool => try mod.intValue(scalar_ty, 0),
-            .Int => try scalar_ty.minInt(mod),
+            .Int => try scalar_ty.minInt(mod, scalar_ty),
             .Float => try mod.floatValue(scalar_ty, std.math.nan_f128),
             else => unreachable,
         },
src/InternPool.zig
@@ -2817,6 +2817,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
         },
         .ptr_type => |ptr_type| {
             assert(ptr_type.elem_type != .none);
+            assert(ptr_type.sentinel == .none or ip.typeOf(ptr_type.sentinel) == ptr_type.elem_type);
 
             if (ptr_type.size == .Slice) {
                 _ = ip.map.pop();
@@ -4780,7 +4781,88 @@ pub fn stringToSliceUnwrap(ip: InternPool, s: OptionalNullTerminatedString) ?[:0
 }
 
 pub fn typeOf(ip: InternPool, index: Index) Index {
-    return ip.indexToKey(index).typeOf();
+    // This optimization of static keys is required so that typeOf can be called
+    // on static keys that haven't been added yet during static key initialization.
+    // An alternative would be to topological sort the static keys, but this would
+    // mean that the range of type indices would not be dense.
+    return switch (index) {
+        .u1_type,
+        .u8_type,
+        .i8_type,
+        .u16_type,
+        .i16_type,
+        .u29_type,
+        .u32_type,
+        .i32_type,
+        .u64_type,
+        .i64_type,
+        .u80_type,
+        .u128_type,
+        .i128_type,
+        .usize_type,
+        .isize_type,
+        .c_char_type,
+        .c_short_type,
+        .c_ushort_type,
+        .c_int_type,
+        .c_uint_type,
+        .c_long_type,
+        .c_ulong_type,
+        .c_longlong_type,
+        .c_ulonglong_type,
+        .c_longdouble_type,
+        .f16_type,
+        .f32_type,
+        .f64_type,
+        .f80_type,
+        .f128_type,
+        .anyopaque_type,
+        .bool_type,
+        .void_type,
+        .type_type,
+        .anyerror_type,
+        .comptime_int_type,
+        .comptime_float_type,
+        .noreturn_type,
+        .anyframe_type,
+        .null_type,
+        .undefined_type,
+        .enum_literal_type,
+        .atomic_order_type,
+        .atomic_rmw_op_type,
+        .calling_convention_type,
+        .address_space_type,
+        .float_mode_type,
+        .reduce_op_type,
+        .call_modifier_type,
+        .prefetch_options_type,
+        .export_options_type,
+        .extern_options_type,
+        .type_info_type,
+        .manyptr_u8_type,
+        .manyptr_const_u8_type,
+        .manyptr_const_u8_sentinel_0_type,
+        .single_const_pointer_to_comptime_int_type,
+        .slice_const_u8_type,
+        .slice_const_u8_sentinel_0_type,
+        .anyerror_void_error_union_type,
+        .generic_poison_type,
+        .empty_struct_type,
+        => .type_type,
+        .undef => .undefined_type,
+        .zero, .one, .negative_one => .comptime_int_type,
+        .zero_usize, .one_usize => .usize_type,
+        .zero_u8, .one_u8, .four_u8 => .u8_type,
+        .calling_convention_c, .calling_convention_inline => .calling_convention_type,
+        .void_value => .void_type,
+        .unreachable_value => .noreturn_type,
+        .null_value => .null_type,
+        .bool_true, .bool_false => .bool_type,
+        .empty_struct => .empty_struct_type,
+        .generic_poison => .generic_poison_type,
+        .var_args_param_type, .none => unreachable,
+        _ => ip.indexToKey(index).typeOf(),
+    };
 }
 
 /// Assumes that the enum's field indexes equal its value tags.
src/Module.zig
@@ -6898,10 +6898,6 @@ pub fn enumValueFieldIndex(mod: *Module, ty: Type, field_index: u32) Allocator.E
 }
 
 pub fn intValue(mod: *Module, ty: Type, x: anytype) Allocator.Error!Value {
-    if (std.debug.runtime_safety) {
-        const tag = ty.zigTypeTag(mod);
-        assert(tag == .Int or tag == .ComptimeInt);
-    }
     if (std.math.cast(u64, x)) |casted| return intValue_u64(mod, ty, casted);
     if (std.math.cast(i64, x)) |casted| return intValue_i64(mod, ty, casted);
     var limbs_buffer: [4]usize = undefined;
src/Sema.zig
@@ -848,13 +848,12 @@ pub fn analyzeBodyBreak(
     block: *Block,
     body: []const Zir.Inst.Index,
 ) CompileError!?BreakData {
-    const mod = sema.mod;
     const break_inst = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
         error.ComptimeBreak => sema.comptime_break_inst,
         else => |e| return e,
     };
     if (block.instructions.items.len != 0 and
-        sema.typeOf(Air.indexToRef(block.instructions.items[block.instructions.items.len - 1])).isNoReturn(mod))
+        sema.isNoReturn(Air.indexToRef(block.instructions.items[block.instructions.items.len - 1])))
         return null;
     const break_data = sema.code.instructions.items(.data)[break_inst].@"break";
     const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data;
@@ -9671,9 +9670,9 @@ fn intCast(
                 // range to account for negative values.
                 const dest_range_val = if (wanted_info.signedness == .signed) range_val: {
                     const one = try mod.intValue(unsigned_operand_ty, 1);
-                    const range_minus_one = try dest_max_val.shl(one, unsigned_operand_ty, sema.arena, sema.mod);
+                    const range_minus_one = try dest_max_val.shl(one, unsigned_operand_ty, sema.arena, mod);
                     break :range_val try sema.intAdd(range_minus_one, one, unsigned_operand_ty);
-                } else dest_max_val;
+                } else try mod.getCoerced(dest_max_val, unsigned_operand_ty);
                 const dest_range = try sema.addConstant(unsigned_operand_ty, dest_range_val);
 
                 const ok = if (is_vector) ok: {
@@ -10791,7 +10790,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
 
             check_range: {
                 if (operand_ty.zigTypeTag(mod) == .Int) {
-                    const min_int = try operand_ty.minInt(mod);
+                    const min_int = try operand_ty.minInt(mod, operand_ty);
                     const max_int = try operand_ty.maxInt(mod, operand_ty);
                     if (try range_set.spans(min_int, max_int, operand_ty)) {
                         if (special_prong == .@"else") {
@@ -11647,7 +11646,7 @@ const RangeSetUnhandledIterator = struct {
 
     fn init(sema: *Sema, ty: Type, range_set: RangeSet) !RangeSetUnhandledIterator {
         const mod = sema.mod;
-        const min = try ty.minInt(mod);
+        const min = try ty.minInt(mod, ty);
         const max = try ty.maxInt(mod, ty);
 
         return RangeSetUnhandledIterator{
@@ -12452,7 +12451,7 @@ fn zirShr(
     if (block.wantSafety()) {
         const bit_count = scalar_ty.intInfo(mod).bits;
         if (!std.math.isPowerOfTwo(bit_count)) {
-            const bit_count_val = try mod.intValue(scalar_ty, bit_count);
+            const bit_count_val = try mod.intValue(rhs_ty.scalarType(mod), bit_count);
 
             const ok = if (rhs_ty.zigTypeTag(mod) == .Vector) ok: {
                 const bit_count_inst = try sema.addConstant(rhs_ty, try sema.splat(rhs_ty, bit_count_val));
@@ -13297,7 +13296,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
                 if (!lhs_val.isUndef(mod)) {
                     if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
                         const scalar_zero = switch (scalar_tag) {
-                            .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0),
+                            .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
                             .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
                             else => unreachable,
                         };
@@ -13437,7 +13436,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
             } else {
                 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
                     const scalar_zero = switch (scalar_tag) {
-                        .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0),
+                        .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
                         .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
                         else => unreachable,
                     };
@@ -13520,7 +13519,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
             const remainder = try block.addBinOp(.rem, casted_lhs, casted_rhs);
 
             const scalar_zero = switch (scalar_tag) {
-                .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0),
+                .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
                 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
                 else => unreachable,
             };
@@ -13608,7 +13607,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
             if (!lhs_val.isUndef(mod)) {
                 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
                     const scalar_zero = switch (scalar_tag) {
-                        .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0),
+                        .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
                         .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
                         else => unreachable,
                     };
@@ -13725,7 +13724,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
             if (!lhs_val.isUndef(mod)) {
                 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
                     const scalar_zero = switch (scalar_tag) {
-                        .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0),
+                        .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
                         .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
                         else => unreachable,
                     };
@@ -13805,7 +13804,7 @@ fn addDivIntOverflowSafety(
         return;
     }
 
-    const min_int = try resolved_type.minInt(mod);
+    const min_int = try resolved_type.minInt(mod, resolved_type);
     const neg_one_scalar = try mod.intValue(lhs_scalar_ty, -1);
     const neg_one = try sema.splat(resolved_type, neg_one_scalar);
 
@@ -13881,7 +13880,7 @@ fn addDivByZeroSafety(
     const scalar_zero = if (is_int)
         try mod.intValue(resolved_type.scalarType(mod), 0)
     else
-        try mod.floatValue(resolved_type.scalarType(mod), 0);
+        try mod.floatValue(resolved_type.scalarType(mod), 0.0);
     const ok = if (resolved_type.zigTypeTag(mod) == .Vector) ok: {
         const zero_val = try sema.splat(resolved_type, scalar_zero);
         const zero = try sema.addConstant(resolved_type, zero_val);
@@ -13967,7 +13966,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
                 }
                 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
                     const scalar_zero = switch (scalar_tag) {
-                        .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0),
+                        .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
                         .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
                         else => unreachable,
                     };
@@ -14575,7 +14574,8 @@ fn analyzeArithmetic(
     const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
     const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
 
-    const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod);
+    const scalar_type = resolved_type.scalarType(mod);
+    const scalar_tag = scalar_type.zigTypeTag(mod);
 
     const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
 
@@ -14797,8 +14797,13 @@ fn analyzeArithmetic(
                 // the result is nan.
                 // If either of the operands are nan, the result is nan.
                 const scalar_zero = switch (scalar_tag) {
-                    .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0),
-                    .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
+                    .ComptimeFloat, .Float => try mod.floatValue(scalar_type, 0.0),
+                    .ComptimeInt, .Int => try mod.intValue(scalar_type, 0),
+                    else => unreachable,
+                };
+                const scalar_one = switch (scalar_tag) {
+                    .ComptimeFloat, .Float => try mod.floatValue(scalar_type, 1.0),
+                    .ComptimeInt, .Int => try mod.intValue(scalar_type, 1),
                     else => unreachable,
                 };
                 if (maybe_lhs_val) |lhs_val| {
@@ -14823,7 +14828,7 @@ fn analyzeArithmetic(
                             const zero_val = try sema.splat(resolved_type, scalar_zero);
                             return sema.addConstant(resolved_type, zero_val);
                         }
-                        if (try sema.compareAll(lhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
+                        if (try sema.compareAll(lhs_val, .eq, try sema.splat(resolved_type, scalar_one), resolved_type)) {
                             return casted_rhs;
                         }
                     }
@@ -14854,7 +14859,7 @@ fn analyzeArithmetic(
                         const zero_val = try sema.splat(resolved_type, scalar_zero);
                         return sema.addConstant(resolved_type, zero_val);
                     }
-                    if (try sema.compareAll(rhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
+                    if (try sema.compareAll(rhs_val, .eq, try sema.splat(resolved_type, scalar_one), resolved_type)) {
                         return casted_lhs;
                     }
                     if (maybe_lhs_val) |lhs_val| {
@@ -14887,8 +14892,8 @@ fn analyzeArithmetic(
                 // If either of the operands are one, result is the other operand.
                 // If either of the operands are undefined, result is undefined.
                 const scalar_zero = switch (scalar_tag) {
-                    .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0),
-                    .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
+                    .ComptimeFloat, .Float => try mod.floatValue(scalar_type, 0.0),
+                    .ComptimeInt, .Int => try mod.intValue(scalar_type, 0),
                     else => unreachable,
                 };
                 if (maybe_lhs_val) |lhs_val| {
@@ -14931,8 +14936,8 @@ fn analyzeArithmetic(
                 // If either of the operands are one, result is the other operand.
                 // If either of the operands are undefined, result is undefined.
                 const scalar_zero = switch (scalar_tag) {
-                    .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0),
-                    .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
+                    .ComptimeFloat, .Float => try mod.floatValue(scalar_type, 0.0),
+                    .ComptimeInt, .Int => try mod.intValue(scalar_type, 0),
                     else => unreachable,
                 };
                 if (maybe_lhs_val) |lhs_val| {
@@ -18817,7 +18822,10 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
     {
         return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);
     }
-    return sema.addConstant(opt_ptr_stack_trace_ty, Value.null);
+    return sema.addConstant(opt_ptr_stack_trace_ty, (try mod.intern(.{ .opt = .{
+        .ty = opt_ptr_stack_trace_ty.toIntern(),
+        .val = .none,
+    } })).toValue());
 }
 
 fn zirFrame(
@@ -20103,8 +20111,8 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
     if (block.wantSafety()) {
         const back = try block.addTyOp(.int_to_float, operand_ty, result);
         const diff = try block.addBinOp(.sub, operand, back);
-        const ok_pos = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_lt_optimized else .cmp_lt, diff, try sema.addConstant(operand_ty, try mod.intValue(operand_ty, 1)));
-        const ok_neg = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_gt_optimized else .cmp_gt, diff, try sema.addConstant(operand_ty, try mod.intValue(operand_ty, -1)));
+        const ok_pos = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_lt_optimized else .cmp_lt, diff, try sema.addConstant(operand_ty, try mod.floatValue(operand_ty, 1.0)));
+        const ok_neg = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_gt_optimized else .cmp_gt, diff, try sema.addConstant(operand_ty, try mod.floatValue(operand_ty, -1.0)));
         const ok = try block.addBinOp(.bool_and, ok_pos, ok_neg);
         try sema.addSafetyCheck(block, ok, .integer_part_out_of_bounds);
     }
@@ -22448,8 +22456,8 @@ fn analyzeMinMax(
 
         // Compute the final bounds based on the runtime type and the comptime-known bound type
         const min_val = switch (air_tag) {
-            .min => try unrefined_elem_ty.minInt(mod),
-            .max => try comptime_elem_ty.minInt(mod), // @max(ct, rt) >= ct
+            .min => try unrefined_elem_ty.minInt(mod, unrefined_elem_ty),
+            .max => try comptime_elem_ty.minInt(mod, comptime_elem_ty), // @max(ct, rt) >= ct
             else => unreachable,
         };
         const max_val = switch (air_tag) {
@@ -25996,7 +26004,7 @@ fn coerceExtra(
 
                 if (dest_info.sentinel) |dest_sent| {
                     if (array_ty.sentinel(mod)) |inst_sent| {
-                        if (!dest_sent.eql(inst_sent, dst_elem_type, sema.mod)) {
+                        if (!dest_sent.eql(inst_sent, dst_elem_type, mod)) {
                             in_memory_result = .{ .ptr_sentinel = .{
                                 .actual = inst_sent,
                                 .wanted = dest_sent,
@@ -26115,7 +26123,7 @@ fn coerceExtra(
                         if (inst_info.size == .Slice) {
                             assert(dest_info.sentinel == null);
                             if (inst_info.sentinel == null or
-                                !inst_info.sentinel.?.eql(try mod.intValue(dest_info.pointee_type, 0), dest_info.pointee_type, sema.mod))
+                                !inst_info.sentinel.?.eql(try mod.intValue(dest_info.pointee_type, 0), dest_info.pointee_type, mod))
                                 break :p;
 
                             const slice_ptr = try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty);
@@ -26164,7 +26172,7 @@ fn coerceExtra(
                             block,
                             inst_src,
                             "array literal requires address-of operator (&) to coerce to slice type '{}'",
-                            .{dest_ty.fmt(sema.mod)},
+                            .{dest_ty.fmt(mod)},
                         );
                     }
 
@@ -26190,7 +26198,7 @@ fn coerceExtra(
                     // pointer to tuple to slice
                     if (dest_info.mutable) {
                         const err_msg = err_msg: {
-                            const err_msg = try sema.errMsg(block, inst_src, "cannot cast pointer to tuple to '{}'", .{dest_ty.fmt(sema.mod)});
+                            const err_msg = try sema.errMsg(block, inst_src, "cannot cast pointer to tuple to '{}'", .{dest_ty.fmt(mod)});
                             errdefer err_msg.deinit(sema.gpa);
                             try sema.errNote(block, dest_ty_src, err_msg, "pointers to tuples can only coerce to constant pointers", .{});
                             break :err_msg err_msg;
@@ -26218,7 +26226,7 @@ fn coerceExtra(
                     }
 
                     if (dest_info.sentinel == null or inst_info.sentinel == null or
-                        !dest_info.sentinel.?.eql(inst_info.sentinel.?, dest_info.pointee_type, sema.mod))
+                        !dest_info.sentinel.?.eql(inst_info.sentinel.?, dest_info.pointee_type, mod))
                         break :p;
 
                     const slice_ptr = try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty);
@@ -26244,7 +26252,7 @@ fn coerceExtra(
                         block,
                         inst_src,
                         "fractional component prevents float value '{}' from coercion to type '{}'",
-                        .{ val.fmtValue(inst_ty, sema.mod), dest_ty.fmt(sema.mod) },
+                        .{ val.fmtValue(inst_ty, mod), dest_ty.fmt(mod) },
                     );
                 }
                 const result_val = try sema.floatToInt(block, inst_src, val, inst_ty, dest_ty);
@@ -26258,7 +26266,7 @@ fn coerceExtra(
                     // comptime-known integer to other number
                     if (!(try sema.intFitsInType(val, dest_ty, null))) {
                         if (!opts.report_err) return error.NotCoercible;
-                        return sema.fail(block, inst_src, "type '{}' cannot represent integer value '{}'", .{ dest_ty.fmt(sema.mod), val.fmtValue(inst_ty, sema.mod) });
+                        return sema.fail(block, inst_src, "type '{}' cannot represent integer value '{}'", .{ dest_ty.fmt(mod), val.fmtValue(inst_ty, mod) });
                     }
                     return try sema.addConstant(dest_ty, try mod.getCoerced(val, dest_ty));
                 }
@@ -26296,12 +26304,12 @@ fn coerceExtra(
                 }
                 if (try sema.resolveMaybeUndefVal(inst)) |val| {
                     const result_val = try val.floatCast(dest_ty, mod);
-                    if (!val.eql(result_val, inst_ty, sema.mod)) {
+                    if (!val.eql(try result_val.floatCast(inst_ty, mod), inst_ty, mod)) {
                         return sema.fail(
                             block,
                             inst_src,
                             "type '{}' cannot represent float value '{}'",
-                            .{ dest_ty.fmt(sema.mod), val.fmtValue(inst_ty, sema.mod) },
+                            .{ dest_ty.fmt(mod), val.fmtValue(inst_ty, mod) },
                         );
                     }
                     return try sema.addConstant(dest_ty, result_val);
@@ -26329,7 +26337,7 @@ fn coerceExtra(
                     }
                     break :int;
                 };
-                const result_val = try val.intToFloatAdvanced(sema.arena, inst_ty, dest_ty, sema.mod, sema);
+                const result_val = try val.intToFloatAdvanced(sema.arena, inst_ty, dest_ty, mod, sema);
                 // TODO implement this compile error
                 //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty);
                 //if (!int_again_val.eql(val, inst_ty, mod)) {
@@ -26337,7 +26345,7 @@ fn coerceExtra(
                 //        block,
                 //        inst_src,
                 //        "type '{}' cannot represent integer value '{}'",
-                //        .{ dest_ty.fmt(sema.mod), val },
+                //        .{ dest_ty.fmt(mod), val },
                 //    );
                 //}
                 return try sema.addConstant(dest_ty, result_val);
@@ -26359,7 +26367,7 @@ fn coerceExtra(
                             block,
                             inst_src,
                             "no field named '{s}' in enum '{}'",
-                            .{ bytes, dest_ty.fmt(sema.mod) },
+                            .{ bytes, dest_ty.fmt(mod) },
                         );
                         errdefer msg.destroy(sema.gpa);
                         try sema.addDeclaredHereNote(msg, dest_ty);
@@ -26375,7 +26383,7 @@ fn coerceExtra(
             .Union => blk: {
                 // union to its own tag type
                 const union_tag_ty = inst_ty.unionTagType(mod) orelse break :blk;
-                if (union_tag_ty.eql(dest_ty, sema.mod)) {
+                if (union_tag_ty.eql(dest_ty, mod)) {
                     return sema.unionToTag(block, dest_ty, inst, inst_src);
                 }
             },
@@ -26498,15 +26506,15 @@ fn coerceExtra(
             errdefer msg.destroy(sema.gpa);
 
             const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
-            const src_decl = sema.mod.declPtr(sema.func.?.owner_decl);
-            try sema.mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "'noreturn' declared here", .{});
+            const src_decl = mod.declPtr(sema.func.?.owner_decl);
+            try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "'noreturn' declared here", .{});
             break :msg msg;
         };
         return sema.failWithOwnedErrorMsg(msg);
     }
 
     const msg = msg: {
-        const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(sema.mod), inst_ty.fmt(sema.mod) });
+        const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(mod), inst_ty.fmt(mod) });
         errdefer msg.destroy(sema.gpa);
 
         // E!T to T
@@ -26528,18 +26536,18 @@ fn coerceExtra(
         try in_memory_result.report(sema, block, inst_src, msg);
 
         // Add notes about function return type
-        if (opts.is_ret and sema.mod.test_functions.get(sema.func.?.owner_decl) == null) {
+        if (opts.is_ret and mod.test_functions.get(sema.func.?.owner_decl) == null) {
             const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
-            const src_decl = sema.mod.declPtr(sema.func.?.owner_decl);
+            const src_decl = mod.declPtr(sema.func.?.owner_decl);
             if (inst_ty.isError(mod) and !dest_ty.isError(mod)) {
-                try sema.mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "function cannot return an error", .{});
+                try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "function cannot return an error", .{});
             } else {
-                try sema.mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "function return type declared here", .{});
+                try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "function return type declared here", .{});
             }
         }
 
         if (try opts.param_src.get(sema)) |param_src| {
-            try sema.mod.errNoteNonLazy(param_src, msg, "parameter type declared here", .{});
+            try mod.errNoteNonLazy(param_src, msg, "parameter type declared here", .{});
         }
 
         // TODO maybe add "cannot store an error in type '{}'" note
@@ -26679,7 +26687,7 @@ const InMemoryCoercionResult = union(enum) {
             },
             .error_union_payload => |pair| {
                 try sema.errNote(block, src, msg, "error union payload '{}' cannot cast into error union payload '{}'", .{
-                    pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
+                    pair.actual.fmt(mod), pair.wanted.fmt(mod),
                 });
                 cur = pair.child;
             },
@@ -26692,18 +26700,18 @@ const InMemoryCoercionResult = union(enum) {
             .array_sentinel => |sentinel| {
                 if (sentinel.actual.toIntern() != .unreachable_value) {
                     try sema.errNote(block, src, msg, "array sentinel '{}' cannot cast into array sentinel '{}'", .{
-                        sentinel.actual.fmtValue(sentinel.ty, sema.mod), sentinel.wanted.fmtValue(sentinel.ty, sema.mod),
+                        sentinel.actual.fmtValue(sentinel.ty, mod), sentinel.wanted.fmtValue(sentinel.ty, mod),
                     });
                 } else {
                     try sema.errNote(block, src, msg, "destination array requires '{}' sentinel", .{
-                        sentinel.wanted.fmtValue(sentinel.ty, sema.mod),
+                        sentinel.wanted.fmtValue(sentinel.ty, mod),
                     });
                 }
                 break;
             },
             .array_elem => |pair| {
                 try sema.errNote(block, src, msg, "array element type '{}' cannot cast into array element type '{}'", .{
-                    pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
+                    pair.actual.fmt(mod), pair.wanted.fmt(mod),
                 });
                 cur = pair.child;
             },
@@ -26715,19 +26723,19 @@ const InMemoryCoercionResult = union(enum) {
             },
             .vector_elem => |pair| {
                 try sema.errNote(block, src, msg, "vector element type '{}' cannot cast into vector element type '{}'", .{
-                    pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
+                    pair.actual.fmt(mod), pair.wanted.fmt(mod),
                 });
                 cur = pair.child;
             },
             .optional_shape => |pair| {
                 try sema.errNote(block, src, msg, "optional type child '{}' cannot cast into optional type child '{}'", .{
-                    pair.actual.optionalChild(mod).fmt(sema.mod), pair.wanted.optionalChild(mod).fmt(sema.mod),
+                    pair.actual.optionalChild(mod).fmt(mod), pair.wanted.optionalChild(mod).fmt(mod),
                 });
                 break;
             },
             .optional_child => |pair| {
                 try sema.errNote(block, src, msg, "optional type child '{}' cannot cast into optional type child '{}'", .{
-                    pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
+                    pair.actual.fmt(mod), pair.wanted.fmt(mod),
                 });
                 cur = pair.child;
             },
@@ -26792,7 +26800,7 @@ const InMemoryCoercionResult = union(enum) {
             },
             .fn_param => |param| {
                 try sema.errNote(block, src, msg, "parameter {d} '{}' cannot cast into '{}'", .{
-                    param.index, param.actual.fmt(sema.mod), param.wanted.fmt(sema.mod),
+                    param.index, param.actual.fmt(mod), param.wanted.fmt(mod),
                 });
                 cur = param.child;
             },
@@ -26802,13 +26810,13 @@ const InMemoryCoercionResult = union(enum) {
             },
             .fn_return_type => |pair| {
                 try sema.errNote(block, src, msg, "return type '{}' cannot cast into return type '{}'", .{
-                    pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
+                    pair.actual.fmt(mod), pair.wanted.fmt(mod),
                 });
                 cur = pair.child;
             },
             .ptr_child => |pair| {
                 try sema.errNote(block, src, msg, "pointer type child '{}' cannot cast into pointer type child '{}'", .{
-                    pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
+                    pair.actual.fmt(mod), pair.wanted.fmt(mod),
                 });
                 cur = pair.child;
             },
@@ -26819,11 +26827,11 @@ const InMemoryCoercionResult = union(enum) {
             .ptr_sentinel => |sentinel| {
                 if (sentinel.actual.toIntern() != .unreachable_value) {
                     try sema.errNote(block, src, msg, "pointer sentinel '{}' cannot cast into pointer sentinel '{}'", .{
-                        sentinel.actual.fmtValue(sentinel.ty, sema.mod), sentinel.wanted.fmtValue(sentinel.ty, sema.mod),
+                        sentinel.actual.fmtValue(sentinel.ty, mod), sentinel.wanted.fmtValue(sentinel.ty, mod),
                     });
                 } else {
                     try sema.errNote(block, src, msg, "destination pointer requires '{}' sentinel", .{
-                        sentinel.wanted.fmtValue(sentinel.ty, sema.mod),
+                        sentinel.wanted.fmtValue(sentinel.ty, mod),
                     });
                 }
                 break;
@@ -26847,11 +26855,11 @@ const InMemoryCoercionResult = union(enum) {
                 const actual_allow_zero = pair.actual.ptrAllowsZero(mod);
                 if (actual_allow_zero and !wanted_allow_zero) {
                     try sema.errNote(block, src, msg, "'{}' could have null values which are illegal in type '{}'", .{
-                        pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
+                        pair.actual.fmt(mod), pair.wanted.fmt(mod),
                     });
                 } else {
                     try sema.errNote(block, src, msg, "mutable '{}' allows illegal null values stored to type '{}'", .{
-                        pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
+                        pair.actual.fmt(mod), pair.wanted.fmt(mod),
                     });
                 }
                 break;
@@ -26877,13 +26885,13 @@ const InMemoryCoercionResult = union(enum) {
             },
             .double_ptr_to_anyopaque => |pair| {
                 try sema.errNote(block, src, msg, "cannot implicitly cast double pointer '{}' to anyopaque pointer '{}'", .{
-                    pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
+                    pair.actual.fmt(mod), pair.wanted.fmt(mod),
                 });
                 break;
             },
             .slice_to_anyopaque => |pair| {
                 try sema.errNote(block, src, msg, "cannot implicitly cast slice '{}' to anyopaque pointer '{}'", .{
-                    pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
+                    pair.actual.fmt(mod), pair.wanted.fmt(mod),
                 });
                 try sema.errNote(block, src, msg, "consider using '.ptr'", .{});
                 break;
@@ -27616,25 +27624,24 @@ fn obtainBitCastedVectorPtr(sema: *Sema, ptr: Air.Inst.Ref) ?Air.Inst.Ref {
     const mod = sema.mod;
     const array_ty = sema.typeOf(ptr).childType(mod);
     if (array_ty.zigTypeTag(mod) != .Array) return null;
-    var ptr_inst = Air.refToIndex(ptr) orelse return null;
+    var ptr_ref = ptr;
+    var ptr_inst = Air.refToIndex(ptr_ref) orelse return null;
     const air_datas = sema.air_instructions.items(.data);
     const air_tags = sema.air_instructions.items(.tag);
-    const prev_ptr = while (air_tags[ptr_inst] == .bitcast) {
-        const prev_ptr = air_datas[ptr_inst].ty_op.operand;
-        const prev_ptr_ty = sema.typeOf(prev_ptr);
-        if (prev_ptr_ty.zigTypeTag(mod) != .Pointer) return null;
-        const prev_ptr_child_ty = prev_ptr_ty.childType(mod);
-        if (prev_ptr_child_ty.zigTypeTag(mod) == .Vector) break prev_ptr;
-        ptr_inst = Air.refToIndex(prev_ptr) orelse return null;
+    const vector_ty = while (air_tags[ptr_inst] == .bitcast) {
+        ptr_ref = air_datas[ptr_inst].ty_op.operand;
+        if (!sema.isKnownZigType(ptr_ref, .Pointer)) return null;
+        const child_ty = sema.typeOf(ptr_ref).childType(mod);
+        if (child_ty.zigTypeTag(mod) == .Vector) break child_ty;
+        ptr_inst = Air.refToIndex(ptr_ref) orelse return null;
     } else return null;
 
     // We have a pointer-to-array and a pointer-to-vector. If the elements and
     // lengths match, return the result.
-    const vector_ty = sema.typeOf(prev_ptr).childType(mod);
     if (array_ty.childType(mod).eql(vector_ty.childType(mod), sema.mod) and
         array_ty.arrayLen(mod) == vector_ty.vectorLen(mod))
     {
-        return prev_ptr;
+        return ptr_ref;
     } else {
         return null;
     }
@@ -34474,3 +34481,12 @@ fn isNoReturn(sema: *Sema, ref: Air.Inst.Ref) bool {
     };
     return sema.typeOf(ref).isNoReturn(sema.mod);
 }
+
+/// Avoids crashing the compiler when asking if inferred allocations are known to be a certain type.
+fn isKnownZigType(sema: *Sema, ref: Air.Inst.Ref, tag: std.builtin.TypeId) bool {
+    if (Air.refToIndex(ref)) |inst| switch (sema.air_instructions.items(.tag)[inst]) {
+        .inferred_alloc, .inferred_alloc_comptime => return false,
+        else => {},
+    };
+    return sema.typeOf(ref).zigTypeTag(sema.mod) == tag;
+}
src/type.zig
@@ -2865,23 +2865,23 @@ pub const Type = struct {
     }
 
     // Works for vectors and vectors of integers.
-    pub fn minInt(ty: Type, mod: *Module) !Value {
-        const scalar = try minIntScalar(ty.scalarType(mod), mod);
+    pub fn minInt(ty: Type, mod: *Module, dest_ty: Type) !Value {
+        const scalar = try minIntScalar(ty.scalarType(mod), mod, dest_ty);
         return if (ty.zigTypeTag(mod) == .Vector) (try mod.intern(.{ .aggregate = .{
-            .ty = ty.toIntern(),
+            .ty = dest_ty.toIntern(),
             .storage = .{ .repeated_elem = scalar.toIntern() },
         } })).toValue() else scalar;
     }
 
     /// Asserts that the type is an integer.
-    pub fn minIntScalar(ty: Type, mod: *Module) !Value {
+    pub fn minIntScalar(ty: Type, mod: *Module, dest_ty: Type) !Value {
         const info = ty.intInfo(mod);
-        if (info.signedness == .unsigned) return mod.intValue(ty, 0);
-        if (info.bits == 0) return mod.intValue(ty, -1);
+        if (info.signedness == .unsigned) return mod.intValue(dest_ty, 0);
+        if (info.bits == 0) return mod.intValue(dest_ty, -1);
 
         if (std.math.cast(u6, info.bits - 1)) |shift| {
             const n = @as(i64, std.math.minInt(i64)) >> (63 - shift);
-            return mod.intValue(Type.comptime_int, n);
+            return mod.intValue(dest_ty, n);
         }
 
         var res = try std.math.big.int.Managed.init(mod.gpa);
@@ -2889,7 +2889,7 @@ pub const Type = struct {
 
         try res.setTwosCompIntLimit(.min, info.signedness, info.bits);
 
-        return mod.intValue_big(Type.comptime_int, res.toConst());
+        return mod.intValue_big(dest_ty, res.toConst());
     }
 
     // Works for vectors and vectors of integers.
@@ -2897,7 +2897,7 @@ pub const Type = struct {
     pub fn maxInt(ty: Type, mod: *Module, dest_ty: Type) !Value {
         const scalar = try maxIntScalar(ty.scalarType(mod), mod, dest_ty);
         return if (ty.zigTypeTag(mod) == .Vector) (try mod.intern(.{ .aggregate = .{
-            .ty = ty.toIntern(),
+            .ty = dest_ty.toIntern(),
             .storage = .{ .repeated_elem = scalar.toIntern() },
         } })).toValue() else scalar;
     }
src/value.zig
@@ -3166,6 +3166,11 @@ pub const Value = struct {
             .len = undefined,
         };
         result_bigint.shiftLeft(lhs_bigint, shift);
+        if (ty.toIntern() != .comptime_int_type) {
+            const int_info = ty.intInfo(mod);
+            result_bigint.truncate(result_bigint.toConst(), int_info.signedness, int_info.bits);
+        }
+
         return mod.intValue_big(ty, result_bigint.toConst());
     }