about summary refs log tree commit diff
diff options
context:
space:
mode:
authoroli <github35764891676564198441@oli-obk.de>2020-11-04 13:41:58 +0000
committeroli <github35764891676564198441@oli-obk.de>2020-11-04 13:41:58 +0000
commitabacaf2aef26043ce09e3aee176a9587bb87eaf6 (patch)
tree71dd864eabe7c9078a135beddbdf8853090f021e
parente67c768110f2cd55d6823defcbfca5651fe1f9f5 (diff)
downloadrust-abacaf2aef26043ce09e3aee176a9587bb87eaf6.tar.gz
rust-abacaf2aef26043ce09e3aee176a9587bb87eaf6.zip
`u128` truncation and sign extension are not just interpreter related
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs5
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs3
-rw-r--r--compiler/rustc_lint/src/types.rs5
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs35
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs6
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs12
-rw-r--r--compiler/rustc_middle/src/ty/util.rs11
-rw-r--r--compiler/rustc_mir/src/interpret/cast.rs5
-rw-r--r--compiler/rustc_mir/src/interpret/eval_context.rs8
-rw-r--r--compiler/rustc_mir/src/interpret/place.rs8
-rw-r--r--compiler/rustc_mir/src/transform/const_prop.rs9
-rw-r--r--compiler/rustc_mir_build/src/build/matches/simplify.rs5
-rw-r--r--compiler/rustc_mir_build/src/thir/constant.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/_match.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs6
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs3
-rw-r--r--compiler/rustc_target/src/abi/mod.rs29
-rw-r--r--src/librustdoc/clean/utils.rs4
18 files changed, 73 insertions, 89 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 2097f9d2887..bfe5514b6d3 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -585,10 +585,7 @@ fn codegen_stmt<'tcx>(
                                     .discriminant_for_variant(fx.tcx, *index)
                                     .unwrap();
                                 let discr = if discr.ty.is_signed() {
-                                    rustc_middle::mir::interpret::sign_extend(
-                                        discr.val,
-                                        fx.layout_of(discr.ty).size,
-                                    )
+                                    fx.layout_of(discr.ty).size.sign_extend(discr.val)
                                 } else {
                                     discr.val
                                 };
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index ef1ae807453..454d43fd4e7 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -29,7 +29,6 @@ use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::ich::NodeIdHashingMode;
-use rustc_middle::mir::interpret::truncate;
 use rustc_middle::mir::{self, Field, GeneratorLayout};
 use rustc_middle::ty::layout::{self, IntegerExt, PrimitiveExt, TyAndLayout};
 use rustc_middle::ty::subst::GenericArgKind;
@@ -1693,7 +1692,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                                 let value = (i.as_u32() as u128)
                                     .wrapping_sub(niche_variants.start().as_u32() as u128)
                                     .wrapping_add(niche_start);
-                                let value = truncate(value, tag.value.size(cx));
+                                let value = tag.value.size(cx).truncate(value);
                                 // NOTE(eddyb) do *NOT* remove this assert, until
                                 // we pass the full 128-bit value to LLVM, otherwise
                                 // truncation will be silent and remain undetected.
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 428cd453dd5..467a3a42590 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -6,7 +6,6 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::{is_range_literal, ExprKind, Node};
 use rustc_index::vec::Idx;
-use rustc_middle::mir::interpret::{sign_extend, truncate};
 use rustc_middle::ty::layout::{IntegerExt, SizeSkeleton};
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable};
@@ -218,11 +217,11 @@ fn report_bin_hex_error(
     cx.struct_span_lint(OVERFLOWING_LITERALS, expr.span, |lint| {
         let (t, actually) = match ty {
             attr::IntType::SignedInt(t) => {
-                let actually = sign_extend(val, size) as i128;
+                let actually = size.sign_extend(val) as i128;
                 (t.name_str(), actually.to_string())
             }
             attr::IntType::UnsignedInt(t) => {
-                let actually = truncate(val, size);
+                let actually = size.truncate(val);
                 (t.name_str(), actually.to_string())
             }
         };
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index b5beb3babe2..bcf85797313 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -110,7 +110,7 @@ use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_serialize::{Decodable, Encodable};
-use rustc_target::abi::{Endian, Size};
+use rustc_target::abi::Endian;
 
 use crate::mir;
 use crate::ty::codec::{TyDecoder, TyEncoder};
@@ -590,39 +590,6 @@ pub fn read_target_uint(endianness: Endian, mut source: &[u8]) -> Result<u128, i
     uint
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// Methods to facilitate working with signed integers stored in a u128
-////////////////////////////////////////////////////////////////////////////////
-
-/// Truncates `value` to `size` bits and then sign-extend it to 128 bits
-/// (i.e., if it is negative, fill with 1's on the left).
-#[inline]
-pub fn sign_extend(value: u128, size: Size) -> u128 {
-    let size = size.bits();
-    if size == 0 {
-        // Truncated until nothing is left.
-        return 0;
-    }
-    // Sign-extend it.
-    let shift = 128 - size;
-    // Shift the unsigned value to the left, then shift back to the right as signed
-    // (essentially fills with FF on the left).
-    (((value << shift) as i128) >> shift) as u128
-}
-
-/// Truncates `value` to `size` bits.
-#[inline]
-pub fn truncate(value: u128, size: Size) -> u128 {
-    let size = size.bits();
-    if size == 0 {
-        // Truncated until nothing is left.
-        return 0;
-    }
-    let shift = 128 - size;
-    // Truncate (shift left to drop out leftover values, shift right to fill with zeroes).
-    (value << shift) >> shift
-}
-
 /// Computes the unsigned absolute value without wrapping or panicking.
 #[inline]
 pub fn uabs(value: i64) -> u64 {
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index a191dd1d705..5e97862ecf2 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -10,7 +10,7 @@ use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout};
 
 use crate::ty::{ParamEnv, ScalarInt, Ty, TyCtxt};
 
-use super::{sign_extend, AllocId, Allocation, InterpResult, Pointer, PointerArithmetic};
+use super::{AllocId, Allocation, InterpResult, Pointer, PointerArithmetic};
 
 /// Represents the result of const evaluation via the `eval_to_allocation` query.
 #[derive(Clone, HashStable, TyEncodable, TyDecodable)]
@@ -448,7 +448,7 @@ impl<'tcx, Tag> Scalar<Tag> {
     fn to_signed_with_bit_width(self, bits: u64) -> InterpResult<'static, i128> {
         let sz = Size::from_bits(bits);
         let b = self.to_bits(sz)?;
-        Ok(sign_extend(b, sz) as i128)
+        Ok(sz.sign_extend(b) as i128)
     }
 
     /// Converts the scalar to produce an `i8`. Fails if the scalar is a pointer.
@@ -479,7 +479,7 @@ impl<'tcx, Tag> Scalar<Tag> {
     pub fn to_machine_isize(self, cx: &impl HasDataLayout) -> InterpResult<'static, i64> {
         let sz = cx.data_layout().pointer_size;
         let b = self.to_bits(sz)?;
-        let b = sign_extend(b, sz) as i128;
+        let b = sz.sign_extend(b) as i128;
         Ok(i64::try_from(b).unwrap())
     }
 
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index 8308cfddb43..4ff88d1adaf 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -1,4 +1,4 @@
-use crate::mir::interpret::{sign_extend, truncate, InterpResult};
+use crate::mir::interpret::InterpResult;
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
@@ -75,7 +75,7 @@ impl std::fmt::Debug for ConstInt {
                 Ok(())
             }
         } else {
-            let max = truncate(u128::MAX, Size::from_bytes(size));
+            let max = Size::from_bytes(size).truncate(u128::MAX);
             if raw == max {
                 match (size, is_ptr_sized_integral) {
                     (_, true) => write!(fmt, "usize::MAX"),
@@ -174,7 +174,7 @@ impl ScalarInt {
         // is a packed struct, that would create a possibly unaligned reference, which
         // is UB.
         debug_assert_eq!(
-            truncate(self.data, self.size()),
+            self.size().truncate(self.data),
             { self.data },
             "Scalar value {:#x} exceeds size of {} bytes",
             { self.data },
@@ -204,7 +204,7 @@ impl ScalarInt {
     #[inline]
     pub fn try_from_uint(i: impl Into<u128>, size: Size) -> Option<Self> {
         let data = i.into();
-        if truncate(data, size) == data {
+        if size.truncate(data) == data {
             Some(Self { data, size: size.bytes() as u8 })
         } else {
             None
@@ -215,8 +215,8 @@ impl ScalarInt {
     pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
         let i = i.into();
         // `into` performed sign extension, we have to truncate
-        let truncated = truncate(i as u128, size);
-        if sign_extend(truncated, size) as i128 == i {
+        let truncated = size.truncate(i as u128);
+        if size.sign_extend(truncated) as i128 == i {
             Some(Self { data: truncated, size: size.bytes() as u8 })
         } else {
             None
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 4a20e1c32f9..5f117e19eca 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -2,7 +2,6 @@
 
 use crate::ich::NodeIdHashingMode;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use crate::mir::interpret::{sign_extend, truncate};
 use crate::ty::fold::TypeFolder;
 use crate::ty::layout::IntegerExt;
 use crate::ty::query::TyCtxtAt;
@@ -38,7 +37,7 @@ impl<'tcx> fmt::Display for Discr<'tcx> {
                 let size = ty::tls::with(|tcx| Integer::from_attr(&tcx, SignedInt(ity)).size());
                 let x = self.val;
                 // sign extend the raw representation to be an i128
-                let x = sign_extend(x, size) as i128;
+                let x = size.sign_extend(x) as i128;
                 write!(fmt, "{}", x)
             }
             _ => write!(fmt, "{}", self.val),
@@ -47,7 +46,7 @@ impl<'tcx> fmt::Display for Discr<'tcx> {
 }
 
 fn signed_min(size: Size) -> i128 {
-    sign_extend(1_u128 << (size.bits() - 1), size) as i128
+    size.sign_extend(1_u128 << (size.bits() - 1)) as i128
 }
 
 fn signed_max(size: Size) -> i128 {
@@ -77,14 +76,14 @@ impl<'tcx> Discr<'tcx> {
         let (val, oflo) = if signed {
             let min = signed_min(size);
             let max = signed_max(size);
-            let val = sign_extend(self.val, size) as i128;
+            let val = size.sign_extend(self.val) as i128;
             assert!(n < (i128::MAX as u128));
             let n = n as i128;
             let oflo = val > max - n;
             let val = if oflo { min + (n - (max - val) - 1) } else { val + n };
             // zero the upper bits
             let val = val as u128;
-            let val = truncate(val, size);
+            let val = size.truncate(val);
             (val, oflo)
         } else {
             let max = unsigned_max(size);
@@ -650,7 +649,7 @@ impl<'tcx> ty::TyS<'tcx> {
         let val = match self.kind() {
             ty::Int(_) | ty::Uint(_) => {
                 let (size, signed) = int_size_and_signed(tcx, self);
-                let val = if signed { truncate(signed_min(size) as u128, size) } else { 0 };
+                let val = if signed { size.truncate(signed_min(size) as u128) } else { 0 };
                 Some(val)
             }
             ty::Char => Some(0),
diff --git a/compiler/rustc_mir/src/interpret/cast.rs b/compiler/rustc_mir/src/interpret/cast.rs
index affeae546b2..6d224bcc50b 100644
--- a/compiler/rustc_mir/src/interpret/cast.rs
+++ b/compiler/rustc_mir/src/interpret/cast.rs
@@ -13,8 +13,7 @@ use rustc_span::symbol::sym;
 use rustc_target::abi::{Integer, LayoutOf, Variants};
 
 use super::{
-    truncate, util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy,
-    PlaceTy,
+    util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy,
 };
 
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
@@ -209,7 +208,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     RawPtr(_) => self.pointer_size(),
                     _ => bug!(),
                 };
-                let v = truncate(v, size);
+                let v = size.truncate(v);
                 Scalar::from_uint(v, size)
             }
 
diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs
index ec1195d3703..08d8904ae1a 100644
--- a/compiler/rustc_mir/src/interpret/eval_context.rs
+++ b/compiler/rustc_mir/src/interpret/eval_context.rs
@@ -9,9 +9,7 @@ use rustc_index::vec::IndexVec;
 use rustc_macros::HashStable;
 use rustc_middle::ich::StableHashingContext;
 use rustc_middle::mir;
-use rustc_middle::mir::interpret::{
-    sign_extend, truncate, GlobalId, InterpResult, Pointer, Scalar,
-};
+use rustc_middle::mir::interpret::{GlobalId, InterpResult, Pointer, Scalar};
 use rustc_middle::ty::layout::{self, TyAndLayout};
 use rustc_middle::ty::{
     self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
@@ -443,12 +441,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     #[inline(always)]
     pub fn sign_extend(&self, value: u128, ty: TyAndLayout<'_>) -> u128 {
         assert!(ty.abi.is_signed());
-        sign_extend(value, ty.size)
+        ty.size.sign_extend(value)
     }
 
     #[inline(always)]
     pub fn truncate(&self, value: u128, ty: TyAndLayout<'_>) -> u128 {
-        truncate(value, ty.size)
+        ty.size.truncate(value)
     }
 
     #[inline]
diff --git a/compiler/rustc_mir/src/interpret/place.rs b/compiler/rustc_mir/src/interpret/place.rs
index 3e10d0960a8..a003380dda7 100644
--- a/compiler/rustc_mir/src/interpret/place.rs
+++ b/compiler/rustc_mir/src/interpret/place.rs
@@ -14,9 +14,9 @@ use rustc_target::abi::{Abi, Align, FieldsShape, TagEncoding};
 use rustc_target::abi::{HasDataLayout, LayoutOf, Size, VariantIdx, Variants};
 
 use super::{
-    mir_assign_valid_types, truncate, AllocId, AllocMap, Allocation, AllocationExtra, ConstAlloc,
-    ImmTy, Immediate, InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy, Operand,
-    Pointer, PointerArithmetic, Scalar, ScalarMaybeUninit,
+    mir_assign_valid_types, AllocId, AllocMap, Allocation, AllocationExtra, ConstAlloc, ImmTy,
+    Immediate, InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy, Operand, Pointer,
+    PointerArithmetic, Scalar, ScalarMaybeUninit,
 };
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
@@ -1073,7 +1073,7 @@ where
                 // their computation, but the in-memory tag is the smallest possible
                 // representation
                 let size = tag_layout.value.size(self);
-                let tag_val = truncate(discr_val, size);
+                let tag_val = size.truncate(discr_val);
 
                 let tag_dest = self.place_field(dest, tag_field)?;
                 self.write_scalar(Scalar::from_uint(tag_val, size), tag_dest)?;
diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs
index 620b9ac673a..aeb9920c0e3 100644
--- a/compiler/rustc_mir/src/transform/const_prop.rs
+++ b/compiler/rustc_mir/src/transform/const_prop.rs
@@ -29,10 +29,9 @@ use rustc_trait_selection::traits;
 
 use crate::const_eval::ConstEvalErr;
 use crate::interpret::{
-    self, compile_time_machine, truncate, AllocId, Allocation, ConstValue, CtfeValidationMode,
-    Frame, ImmTy, Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemPlace, Memory,
-    MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Pointer, Scalar, ScalarMaybeUninit,
-    StackPopCleanup,
+    self, compile_time_machine, AllocId, Allocation, ConstValue, CtfeValidationMode, Frame, ImmTy,
+    Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemPlace, Memory, MemoryKind, OpTy,
+    Operand as InterpOperand, PlaceTy, Pointer, Scalar, ScalarMaybeUninit, StackPopCleanup,
 };
 use crate::transform::MirPass;
 
@@ -746,7 +745,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                             }
                         }
                         BinOp::BitOr => {
-                            if arg_value == truncate(u128::MAX, const_arg.layout.size)
+                            if arg_value == const_arg.layout.size.truncate(u128::MAX)
                                 || (const_arg.layout.ty.is_bool() && arg_value == 1)
                             {
                                 this.ecx.write_immediate(*const_arg, dest)?;
diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs
index e46274770be..375f19f8755 100644
--- a/compiler/rustc_mir_build/src/build/matches/simplify.rs
+++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs
@@ -17,7 +17,6 @@ use crate::build::Builder;
 use crate::thir::{self, *};
 use rustc_attr::{SignedInt, UnsignedInt};
 use rustc_hir::RangeEnd;
-use rustc_middle::mir::interpret::truncate;
 use rustc_middle::mir::Place;
 use rustc_middle::ty;
 use rustc_middle::ty::layout::IntegerExt;
@@ -161,13 +160,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     }
                     ty::Int(ity) => {
                         let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
-                        let max = truncate(u128::MAX, size);
+                        let max = size.truncate(u128::MAX);
                         let bias = 1u128 << (size.bits() - 1);
                         (Some((0, max, size)), bias)
                     }
                     ty::Uint(uty) => {
                         let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size();
-                        let max = truncate(u128::MAX, size);
+                        let max = size.truncate(u128::MAX);
                         (Some((0, max, size)), 0)
                     }
                     _ => (None, 0),
diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs
index b71ff6e7557..dfe82317f48 100644
--- a/compiler/rustc_mir_build/src/thir/constant.rs
+++ b/compiler/rustc_mir_build/src/thir/constant.rs
@@ -1,6 +1,6 @@
 use rustc_ast as ast;
 use rustc_middle::mir::interpret::{
-    truncate, Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
+    Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
 };
 use rustc_middle::ty::{self, ParamEnv, TyCtxt};
 use rustc_span::symbol::Symbol;
@@ -16,7 +16,7 @@ crate fn lit_to_const<'tcx>(
         let param_ty = ParamEnv::reveal_all().and(ty);
         let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
         trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
-        let result = truncate(n, width);
+        let result = width.truncate(n);
         trace!("trunc result: {}", result);
         Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
     };
diff --git a/compiler/rustc_mir_build/src/thir/pattern/_match.rs b/compiler/rustc_mir_build/src/thir/pattern/_match.rs
index e0de1351ac3..9e096f9ad68 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/_match.rs
@@ -304,7 +304,7 @@ use rustc_arena::TypedArena;
 use rustc_attr::{SignedInt, UnsignedInt};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{HirId, RangeEnd};
-use rustc_middle::mir::interpret::{truncate, ConstValue};
+use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::mir::Field;
 use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::{self, Const, Ty, TyCtxt};
@@ -1608,7 +1608,7 @@ fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Vec<Constructor<'tc
         }
         &ty::Uint(uty) => {
             let size = Integer::from_attr(&cx.tcx, UnsignedInt(uty)).size();
-            let max = truncate(u128::MAX, size);
+            let max = size.truncate(u128::MAX);
             vec![make_range(0, max)]
         }
         _ if cx.is_uninhabited(pcx.ty) => vec![],
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 3c746ac5153..db0ecd701bc 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -15,7 +15,7 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
 use rustc_hir::RangeEnd;
 use rustc_index::vec::Idx;
-use rustc_middle::mir::interpret::{get_slice_bytes, sign_extend, ConstValue};
+use rustc_middle::mir::interpret::{get_slice_bytes, ConstValue};
 use rustc_middle::mir::interpret::{ErrorHandled, LitToConstError, LitToConstInput};
 use rustc_middle::mir::UserTypeProjection;
 use rustc_middle::mir::{BorrowKind, Field, Mutability};
@@ -1082,8 +1082,8 @@ crate fn compare_const_vals<'tcx>(
                 use rustc_attr::SignedInt;
                 use rustc_middle::ty::layout::IntegerExt;
                 let size = rustc_target::abi::Integer::from_attr(&tcx, SignedInt(ity)).size();
-                let a = sign_extend(a, size);
-                let b = sign_extend(b, size);
+                let a = size.sign_extend(a);
+                let b = size.sign_extend(b);
                 Some((a as i128).cmp(&(b as i128)))
             }
             _ => Some(a.cmp(&b)),
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 1ff043ae91f..c28c2fecfbb 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -4,7 +4,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
-use rustc_middle::mir::interpret::sign_extend;
 use rustc_middle::ty::print::{Print, Printer};
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable};
@@ -527,7 +526,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
                 let param_env = ty::ParamEnv::reveal_all();
                 ct.try_eval_bits(self.tcx, param_env, ct.ty).and_then(|b| {
                     let sz = self.tcx.layout_of(param_env.and(ct.ty)).ok()?.size;
-                    let val = sign_extend(b, sz) as i128;
+                    let val = sz.sign_extend(b) as i128;
                     if val < 0 {
                         neg = true;
                     }
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index 5c87a8f6b3d..12cdd5c169a 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -306,6 +306,35 @@ impl Size {
         let bytes = self.bytes().checked_mul(count)?;
         if bytes < dl.obj_size_bound() { Some(Size::from_bytes(bytes)) } else { None }
     }
+
+    /// Truncates `value` to `self` bits and then sign-extend it to 128 bits
+    /// (i.e., if it is negative, fill with 1's on the left).
+    #[inline]
+    pub fn sign_extend(self, value: u128) -> u128 {
+        let size = self.bits();
+        if size == 0 {
+            // Truncated until nothing is left.
+            return 0;
+        }
+        // Sign-extend it.
+        let shift = 128 - size;
+        // Shift the unsigned value to the left, then shift back to the right as signed
+        // (essentially fills with FF on the left).
+        (((value << shift) as i128) >> shift) as u128
+    }
+
+    /// Truncates `value` to `self` bits.
+    #[inline]
+    pub fn truncate(self, value: u128) -> u128 {
+        let size = self.bits();
+        if size == 0 {
+            // Truncated until nothing is left.
+            return 0;
+        }
+        let shift = 128 - size;
+        // Truncate (shift left to drop out leftover values, shift right to fill with zeroes).
+        (value << shift) >> shift
+    }
 }
 
 // Panicking addition, subtraction and multiplication for convenience.
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 167b06428e5..f6258221e32 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -14,7 +14,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_middle::mir::interpret::{sign_extend, ConstValue};
+use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
 use rustc_middle::ty::{self, DefIdTree, Ty};
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -506,7 +506,7 @@ fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &'tcx ty::Const
             let ty = cx.tcx.lift(ct.ty).unwrap();
             let size = cx.tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
             let data = int.assert_bits(size);
-            let sign_extended_data = sign_extend(data, size) as i128;
+            let sign_extended_data = size.sign_extend(data) as i128;
 
             format!(
                 "{}{}",