about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOli Scherer <github35764891676564198441@oli-obk.de>2021-03-08 16:18:03 +0000
committerOli Scherer <github35764891676564198441@oli-obk.de>2021-03-12 12:43:54 +0000
commit3127a9c60f267c862d2b0f1250c28f38891b94aa (patch)
tree2985fdcfe65cc2360239543f4b0c4f6730e0f9f3
parent3ecde6f5db72c0a99824ec91f57411442026141d (diff)
downloadrust-3127a9c60f267c862d2b0f1250c28f38891b94aa.tar.gz
rust-3127a9c60f267c862d2b0f1250c28f38891b94aa.zip
Prepare mir::Constant for ty::Const only supporting valtrees
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs30
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/constant.rs7
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs18
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs133
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs2
-rw-r--r--compiler/rustc_middle/src/mir/type_foldable.rs17
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs5
-rw-r--r--compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs4
-rw-r--r--compiler/rustc_mir/src/borrow_check/type_check/mod.rs23
-rw-r--r--compiler/rustc_mir/src/interpret/eval_context.rs2
-rw-r--r--compiler/rustc_mir/src/interpret/operand.rs46
-rw-r--r--compiler/rustc_mir/src/monomorphize/collector.rs2
-rw-r--r--compiler/rustc_mir/src/shim.rs8
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/qualifs.rs36
-rw-r--r--compiler/rustc_mir/src/transform/const_prop.rs52
-rw-r--r--compiler/rustc_mir/src/transform/elaborate_drops.rs2
-rw-r--r--compiler/rustc_mir/src/transform/generator.rs2
-rw-r--r--compiler/rustc_mir/src/transform/inline.rs9
-rw-r--r--compiler/rustc_mir/src/transform/instcombine.rs7
-rw-r--r--compiler/rustc_mir/src/transform/lower_intrinsics.rs2
-rw-r--r--compiler/rustc_mir/src/transform/match_branches.rs4
-rw-r--r--compiler/rustc_mir/src/transform/promote_consts.rs36
-rw-r--r--compiler/rustc_mir/src/transform/required_consts.rs8
-rw-r--r--compiler/rustc_mir/src/transform/rustc_peek.rs2
-rw-r--r--compiler/rustc_mir/src/transform/simplify_comparison_integral.rs4
-rw-r--r--compiler/rustc_mir/src/util/elaborate_drops.rs2
-rw-r--r--compiler/rustc_mir/src/util/find_self_call.rs4
-rw-r--r--compiler/rustc_mir/src/util/pretty.rs9
-rw-r--r--compiler/rustc_mir_build/src/build/cfg.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs8
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/misc.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs5
38 files changed, 367 insertions, 151 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index b0639cf9e15..23ad5267c56 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -8,7 +8,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::interpret::{
     read_target_uint, AllocId, Allocation, ConstValue, ErrorHandled, GlobalAlloc, Pointer, Scalar,
 };
-use rustc_middle::ty::{Const, ConstKind};
+use rustc_middle::ty::ConstKind;
 
 use cranelift_codegen::ir::GlobalValueData;
 use cranelift_module::*;
@@ -39,7 +39,10 @@ impl ConstantCx {
 pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
     let mut all_constants_ok = true;
     for constant in &fx.mir.required_consts {
-        let const_ = fx.monomorphize(constant.literal);
+        let const_ = match fx.monomorphize(constant.literal) {
+            ConstantSource::Ty(ct) => ct,
+            ConstantSource::Val(..) => continue,
+        };
         match const_.val {
             ConstKind::Value(_) => {}
             ConstKind::Unevaluated(def, ref substs, promoted) => {
@@ -113,19 +116,17 @@ pub(crate) fn codegen_constant<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     constant: &Constant<'tcx>,
 ) -> CValue<'tcx> {
-    let const_ = fx.monomorphize(constant.literal);
+    let const_ = match fx.monomorphize(constant.literal) {
+        ConstantSource::Ty(ct) => ct,
+        ConstantSource::Val(val, ty) => return codegen_const_value(fx, val, ty),
+    };
     let const_val = match const_.val {
         ConstKind::Value(const_val) => const_val,
         ConstKind::Unevaluated(def, ref substs, promoted) if fx.tcx.is_static(def.did) => {
             assert!(substs.is_empty());
             assert!(promoted.is_none());
 
-            return codegen_static_ref(
-                fx,
-                def.did,
-                fx.layout_of(fx.monomorphize(&constant.literal.ty)),
-            )
-            .to_cvalue(fx);
+            return codegen_static_ref(fx, def.did, fx.layout_of(const_.ty)).to_cvalue(fx);
         }
         ConstKind::Unevaluated(def, ref substs, promoted) => {
             match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), def, substs, promoted, None) {
@@ -422,11 +423,14 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
 pub(crate) fn mir_operand_get_const_val<'tcx>(
     fx: &FunctionCx<'_, '_, 'tcx>,
     operand: &Operand<'tcx>,
-) -> Option<&'tcx Const<'tcx>> {
+) -> Option<ConstValue<'tcx>> {
     match operand {
         Operand::Copy(_) | Operand::Move(_) => None,
-        Operand::Constant(const_) => {
-            Some(fx.monomorphize(const_.literal).eval(fx.tcx, ParamEnv::reveal_all()))
-        }
+        Operand::Constant(const_) => match const_.literal {
+            ConstantSource::Ty(const_) => {
+                fx.monomorphize(const_).eval(fx.tcx, ParamEnv::reveal_all()).val.try_to_value()
+            }
+            ConstantSource::Val(val, _) => Some(val),
+        },
     }
 }
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
index 0692da397eb..83c91f789cd 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
@@ -53,7 +53,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
         };
         llvm.x86.sse2.cmp.ps | llvm.x86.sse2.cmp.pd, (c x, c y, o kind) {
             let kind_const = crate::constant::mir_operand_get_const_val(fx, kind).expect("llvm.x86.sse2.cmp.* kind not const");
-            let flt_cc = match kind_const.val.try_to_bits(Size::from_bytes(1)).unwrap_or_else(|| panic!("kind not scalar: {:?}", kind_const)) {
+            let flt_cc = match kind_const.try_to_bits(Size::from_bytes(1)).unwrap_or_else(|| panic!("kind not scalar: {:?}", kind_const)) {
                 0 => FloatCC::Equal,
                 1 => FloatCC::LessThan,
                 2 => FloatCC::LessThanOrEqual,
@@ -84,7 +84,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
         llvm.x86.sse2.psrli.d, (c a, o imm8) {
             let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8).expect("llvm.x86.sse2.psrli.d imm8 not const");
             simd_for_each_lane(fx, a, ret, |fx, _lane_layout, res_lane_layout, lane| {
-                let res_lane = match imm8.val.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) {
+                let res_lane = match imm8.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) {
                     imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)),
                     _ => fx.bcx.ins().iconst(types::I32, 0),
                 };
@@ -94,7 +94,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
         llvm.x86.sse2.pslli.d, (c a, o imm8) {
             let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8).expect("llvm.x86.sse2.psrli.d imm8 not const");
             simd_for_each_lane(fx, a, ret, |fx, _lane_layout, res_lane_layout, lane| {
-                let res_lane = match imm8.val.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) {
+                let res_lane = match imm8.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) {
                     imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)),
                     _ => fx.bcx.ins().iconst(types::I32, 0),
                 };
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
index 1f8eeb1e714..d17136080fe 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
@@ -85,8 +85,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                 use rustc_middle::mir::interpret::*;
                 let idx_const = crate::constant::mir_operand_get_const_val(fx, idx).expect("simd_shuffle* idx not const");
 
-                let idx_bytes = match idx_const.val {
-                    ty::ConstKind::Value(ConstValue::ByRef { alloc, offset }) => {
+                let idx_bytes = match idx_const {
+                    ConstValue::ByRef { alloc, offset } => {
                         let ptr = Pointer::new(AllocId(0 /* dummy */), offset);
                         let size = Size::from_bytes(4 * u64::from(ret_lane_count) /* size_of([u32; ret_lane_count]) */);
                         alloc.get_bytes(fx, ptr, size).unwrap()
@@ -130,7 +130,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                 );
             };
 
-            let idx = idx_const.val.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const));
+            let idx = idx_const.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const));
             let (lane_count, _lane_ty) = base.layout().ty.simd_size_and_type(fx.tcx);
             if idx >= lane_count.into() {
                 fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_insert] idx {} >= lane_count {}", idx, lane_count));
@@ -159,7 +159,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                 return;
             };
 
-            let idx = idx_const.val.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const));
+            let idx = idx_const.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const));
             let (lane_count, _lane_ty) = v.layout().ty.simd_size_and_type(fx.tcx);
             if idx >= lane_count.into() {
                 fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_extract] idx {} >= lane_count {}", idx, lane_count));
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index fc4fc08bb0a..04225ddd36f 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -860,7 +860,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 }
                 mir::InlineAsmOperand::SymFn { ref value } => {
                     let literal = self.monomorphize(value.literal);
-                    if let ty::FnDef(def_id, substs) = *literal.ty.kind() {
+                    if let ty::FnDef(def_id, substs) = *literal.ty().kind() {
                         let instance = ty::Instance::resolve_for_fn_ptr(
                             bx.tcx(),
                             ty::ParamEnv::reveal_all(),
diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs
index 114f6a4032a..d73e2325a8b 100644
--- a/compiler/rustc_codegen_ssa/src/mir/constant.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs
@@ -24,7 +24,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         &self,
         constant: &mir::Constant<'tcx>,
     ) -> Result<ConstValue<'tcx>, ErrorHandled> {
-        match self.monomorphize(constant.literal).val {
+        let ct = self.monomorphize(constant.literal);
+        let ct = match ct {
+            mir::ConstantSource::Ty(ct) => ct,
+            mir::ConstantSource::Val(val, _) => return Ok(val),
+        };
+        match ct.val {
             ty::ConstKind::Unevaluated(def, substs, promoted) => self
                 .cx
                 .tcx()
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index c7b1005fffc..cddcc7d576a 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -47,7 +47,25 @@ pub enum ConstValue<'tcx> {
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 static_assert_size!(ConstValue<'_>, 32);
 
+impl From<Scalar> for ConstValue<'tcx> {
+    fn from(s: Scalar) -> Self {
+        Self::Scalar(s)
+    }
+}
+
 impl<'tcx> ConstValue<'tcx> {
+    pub fn lift<'lifted>(self, tcx: TyCtxt<'lifted>) -> Option<ConstValue<'lifted>> {
+        Some(match self {
+            ConstValue::Scalar(s) => ConstValue::Scalar(s),
+            ConstValue::Slice { data, start, end } => {
+                ConstValue::Slice { data: tcx.lift(data)?, start, end }
+            }
+            ConstValue::ByRef { alloc, offset } => {
+                ConstValue::ByRef { alloc: tcx.lift(alloc)?, offset }
+            }
+        })
+    }
+
     #[inline]
     pub fn try_to_scalar(&self) -> Option<Scalar> {
         match *self {
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 44794628e46..20ba82a8e86 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -11,12 +11,12 @@ use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use crate::ty::print::{FmtPrinter, Printer};
 use crate::ty::subst::{Subst, SubstsRef};
 use crate::ty::{self, List, Ty, TyCtxt};
-use crate::ty::{AdtDef, InstanceDef, Region, UserTypeAnnotationIndex};
+use crate::ty::{AdtDef, InstanceDef, Region, ScalarInt, UserTypeAnnotationIndex};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, Namespace};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
 use rustc_hir::{self, GeneratorKind};
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::{Size, VariantIdx};
 
 use polonius_engine::Atom;
 pub use rustc_ast::Mutability;
@@ -30,6 +30,7 @@ use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::asm::InlineAsmRegOrRegClass;
 use std::borrow::Cow;
+use std::convert::TryInto;
 use std::fmt::{self, Debug, Display, Formatter, Write};
 use std::ops::{ControlFlow, Index, IndexMut};
 use std::slice;
@@ -2032,7 +2033,7 @@ impl<'tcx> Operand<'tcx> {
         Operand::Constant(box Constant {
             span,
             user_ty: None,
-            literal: ty::Const::zero_sized(tcx, ty),
+            literal: ConstantSource::Ty(ty::Const::zero_sized(tcx, ty)),
         })
     }
 
@@ -2063,7 +2064,7 @@ impl<'tcx> Operand<'tcx> {
         Operand::Constant(box Constant {
             span,
             user_ty: None,
-            literal: ty::Const::from_scalar(tcx, val, ty),
+            literal: ConstantSource::Val(val.into(), ty),
         })
     }
 
@@ -2405,12 +2406,21 @@ pub struct Constant<'tcx> {
     /// Needed for NLL to impose user-given type constraints.
     pub user_ty: Option<UserTypeAnnotationIndex>,
 
-    pub literal: &'tcx ty::Const<'tcx>,
+    pub literal: ConstantSource<'tcx>,
+}
+
+#[derive(Clone, Copy, PartialEq, PartialOrd, TyEncodable, TyDecodable, Hash, HashStable, Debug)]
+pub enum ConstantSource<'tcx> {
+    /// This constant came from the type system
+    Ty(&'tcx ty::Const<'tcx>),
+    /// This constant cannot go back into the type system, as it represents
+    /// something the type system cannot handle (e.g. pointers).
+    Val(interpret::ConstValue<'tcx>, Ty<'tcx>),
 }
 
 impl Constant<'tcx> {
     pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
-        match self.literal.val.try_to_scalar() {
+        match self.literal.const_for_ty()?.val.try_to_scalar() {
             Some(Scalar::Ptr(ptr)) => match tcx.global_alloc(ptr.alloc_id) {
                 GlobalAlloc::Static(def_id) => {
                     assert!(!tcx.is_thread_local_static(def_id));
@@ -2422,7 +2432,92 @@ impl Constant<'tcx> {
         }
     }
     pub fn ty(&self) -> Ty<'tcx> {
-        self.literal.ty
+        self.literal.ty()
+    }
+}
+
+impl From<&'tcx ty::Const<'tcx>> for ConstantSource<'tcx> {
+    fn from(ct: &'tcx ty::Const<'tcx>) -> Self {
+        Self::Ty(ct)
+    }
+}
+
+impl ConstantSource<'tcx> {
+    /// Returns `None` if the constant is not trivially safe for use in the type system.
+    pub fn const_for_ty(&self) -> Option<&'tcx ty::Const<'tcx>> {
+        match self {
+            ConstantSource::Ty(c) => Some(c),
+            ConstantSource::Val(..) => None,
+        }
+    }
+
+    pub fn ty(&self) -> Ty<'tcx> {
+        match self {
+            ConstantSource::Ty(c) => c.ty,
+            ConstantSource::Val(_, ty) => ty,
+        }
+    }
+
+    #[inline]
+    pub fn try_to_value(self) -> Option<interpret::ConstValue<'tcx>> {
+        match self {
+            ConstantSource::Ty(c) => c.val.try_to_value(),
+            ConstantSource::Val(val, _) => Some(val),
+        }
+    }
+
+    #[inline]
+    pub fn try_to_scalar(self) -> Option<Scalar> {
+        self.try_to_value()?.try_to_scalar()
+    }
+
+    #[inline]
+    pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
+        self.try_to_value()?.try_to_scalar()?.to_int().ok()
+    }
+
+    #[inline]
+    pub fn try_to_bits(self, size: Size) -> Option<u128> {
+        self.try_to_scalar_int()?.to_bits(size).ok()
+    }
+
+    #[inline]
+    pub fn try_to_bool(self) -> Option<bool> {
+        self.try_to_scalar_int()?.try_into().ok()
+    }
+
+    #[inline]
+    pub fn try_eval_bits(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        ty: Ty<'tcx>,
+    ) -> Option<u128> {
+        match self {
+            Self::Ty(ct) => ct.try_eval_bits(tcx, param_env, ty),
+            Self::Val(val, t) => {
+                assert_eq!(*t, ty);
+                let size =
+                    tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
+                val.try_to_bits(size)
+            }
+        }
+    }
+
+    #[inline]
+    pub fn try_eval_bool(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<bool> {
+        match self {
+            Self::Ty(ct) => ct.try_eval_bool(tcx, param_env),
+            Self::Val(val, _) => val.try_to_bool(),
+        }
+    }
+
+    #[inline]
+    pub fn try_eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<u64> {
+        match self {
+            Self::Ty(ct) => ct.try_eval_usize(tcx, param_env),
+            Self::Val(val, _) => val.try_to_machine_usize(tcx),
+        }
     }
 }
 
@@ -2609,11 +2704,14 @@ impl<'tcx> Debug for Constant<'tcx> {
 
 impl<'tcx> Display for Constant<'tcx> {
     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
-        match self.literal.ty.kind() {
+        match self.ty().kind() {
             ty::FnDef(..) => {}
             _ => write!(fmt, "const ")?,
         }
-        pretty_print_const(self.literal, fmt, true)
+        match self.literal {
+            ConstantSource::Ty(c) => pretty_print_const(c, fmt, true),
+            ConstantSource::Val(val, ty) => pretty_print_const_value(val, ty, fmt, true),
+        }
     }
 }
 
@@ -2632,6 +2730,23 @@ fn pretty_print_const(
     })
 }
 
+fn pretty_print_const_value(
+    val: interpret::ConstValue<'tcx>,
+    ty: Ty<'tcx>,
+    fmt: &mut Formatter<'_>,
+    print_types: bool,
+) -> fmt::Result {
+    use crate::ty::print::PrettyPrinter;
+    ty::tls::with(|tcx| {
+        let val = val.lift(tcx).unwrap();
+        let ty = tcx.lift(ty).unwrap();
+        let mut cx = FmtPrinter::new(tcx, fmt, Namespace::ValueNS);
+        cx.print_alloc_ids = true;
+        cx.pretty_print_const_value(val, ty, print_types)?;
+        Ok(())
+    })
+}
+
 impl<'tcx> graph::DirectedGraph for Body<'tcx> {
     type Node = BasicBlock;
 }
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 3961fd938be..6e819145976 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -227,7 +227,7 @@ impl<'tcx> Operand<'tcx> {
     {
         match self {
             &Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty,
-            &Operand::Constant(ref c) => c.literal.ty,
+            &Operand::Constant(ref c) => c.literal.ty(),
         }
     }
 }
diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs
index 6fabddbd149..4ad69a2cb98 100644
--- a/compiler/rustc_middle/src/mir/type_foldable.rs
+++ b/compiler/rustc_middle/src/mir/type_foldable.rs
@@ -343,5 +343,22 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
     }
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
         self.literal.visit_with(visitor)
+        // FIXME: should this be visiting the `user_ty`, too?
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ConstantSource<'tcx> {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+        match self {
+            ConstantSource::Ty(c) => ConstantSource::Ty(c.fold_with(folder)),
+            ConstantSource::Val(v, t) => ConstantSource::Val(v, t.fold_with(folder)),
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        match *self {
+            ConstantSource::Ty(c) => c.visit_with(visitor),
+            ConstantSource::Val(_, t) => t.visit_with(visitor),
+        }
     }
 }
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 4e81612c0b9..9015e771864 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -871,7 +871,10 @@ macro_rules! make_mir_visitor {
 
                 self.visit_span(span);
                 drop(user_ty); // no visit method for this
-                self.visit_const(literal, location);
+                match literal {
+                    ConstantSource::Ty(ct) => self.visit_const(ct, location),
+                    ConstantSource::Val(_, t) => self.visit_ty(t, TyContext::Location(location)),
+                }
             }
 
             fn super_span(&mut self, _span: & $($mutability)? Span) {
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
index 04ea3cbd8b6..bc15b3972c9 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
@@ -81,12 +81,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let terminator = self.body[location.block].terminator();
         debug!("add_moved_or_invoked_closure_note: terminator={:?}", terminator);
         if let TerminatorKind::Call {
-            func: Operand::Constant(box Constant { literal: ty::Const { ty: const_ty, .. }, .. }),
+            func: Operand::Constant(box Constant { literal, .. }),
             args,
             ..
         } = &terminator.kind
         {
-            if let ty::FnDef(id, _) = *const_ty.kind() {
+            if let ty::FnDef(id, _) = *literal.ty().kind() {
                 debug!("add_moved_or_invoked_closure_note: id={:?}", id);
                 if self.infcx.tcx.parent(id) == self.infcx.tcx.lang_items().fn_once_trait() {
                     let closure = match args.first() {
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
index ab7e75bf4f1..d744db064b6 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
@@ -282,7 +282,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
 
     fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
         self.super_constant(constant, location);
-        let ty = self.sanitize_type(constant, constant.literal.ty);
+        let ty = self.sanitize_type(constant, constant.literal.ty());
 
         self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| {
             let live_region_vid =
@@ -296,7 +296,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
 
         if let Some(annotation_index) = constant.user_ty {
             if let Err(terr) = self.cx.relate_type_and_user_type(
-                constant.literal.ty,
+                constant.literal.ty(),
                 ty::Variance::Invariant,
                 &UserTypeProjection { base: annotation_index, projs: vec![] },
                 location.to_locations(),
@@ -308,13 +308,22 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
                     constant,
                     "bad constant user type {:?} vs {:?}: {:?}",
                     annotation,
-                    constant.literal.ty,
+                    constant.literal.ty(),
                     terr,
                 );
             }
         } else {
             let tcx = self.tcx();
-            if let ty::ConstKind::Unevaluated(def, substs, promoted) = constant.literal.val {
+            let maybe_uneval = match constant.literal {
+                ConstantSource::Ty(ct) => match ct.val {
+                    ty::ConstKind::Unevaluated(def, substs, promoted) => {
+                        Some((def, substs, promoted))
+                    }
+                    _ => None,
+                },
+                _ => None,
+            };
+            if let Some((def, substs, promoted)) = maybe_uneval {
                 if let Some(promoted) = promoted {
                     let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
                                      promoted: &Body<'tcx>,
@@ -349,7 +358,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
                         location.to_locations(),
                         ConstraintCategory::Boring,
                         self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
-                            constant.literal.ty,
+                            constant.literal.ty(),
                             def.did,
                             UserSubsts { substs, user_self_ty: None },
                         )),
@@ -367,7 +376,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
                 let unnormalized_ty = tcx.type_of(static_def_id);
                 let locations = location.to_locations();
                 let normalized_ty = self.cx.normalize(unnormalized_ty, locations);
-                let literal_ty = constant.literal.ty.builtin_deref(true).unwrap().ty;
+                let literal_ty = constant.literal.ty().builtin_deref(true).unwrap().ty;
 
                 if let Err(terr) = self.cx.eq_types(
                     normalized_ty,
@@ -379,7 +388,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
                 }
             }
 
-            if let ty::FnDef(def_id, substs) = *constant.literal.ty.kind() {
+            if let ty::FnDef(def_id, substs) = *constant.literal.ty().kind() {
                 let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
                 self.cx.normalize_and_prove_instantiated_predicates(
                     instantiated_predicates,
diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs
index 6b796eb3721..149a9f81ea0 100644
--- a/compiler/rustc_mir/src/interpret/eval_context.rs
+++ b/compiler/rustc_mir/src/interpret/eval_context.rs
@@ -689,7 +689,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             let span = const_.span;
             let const_ =
                 self.subst_from_current_frame_and_normalize_erasing_regions(const_.literal);
-            self.const_to_op(const_, None).map_err(|err| {
+            self.mir_const_to_op(&const_, None).map_err(|err| {
                 // If there was an error, set the span of the current frame to this constant.
                 // Avoiding doing this when evaluation succeeds.
                 self.frame_mut().loc = Err(span);
diff --git a/compiler/rustc_mir/src/interpret/operand.rs b/compiler/rustc_mir/src/interpret/operand.rs
index 2c4aba19e4a..69ab2abaf27 100644
--- a/compiler/rustc_mir/src/interpret/operand.rs
+++ b/compiler/rustc_mir/src/interpret/operand.rs
@@ -532,7 +532,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // * During ConstProp, with `TooGeneric` or since the `requried_consts` were not all
                 //   checked yet.
                 // * During CTFE, since promoteds in `const`/`static` initializer bodies can fail.
-                self.const_to_op(val, layout)?
+
+                self.mir_const_to_op(&val, layout)?
             }
         };
         trace!("{:?}: {:?}", mir_op, *op);
@@ -556,28 +557,45 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         val: &ty::Const<'tcx>,
         layout: Option<TyAndLayout<'tcx>>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
-        let tag_scalar = |scalar| -> InterpResult<'tcx, _> {
-            Ok(match scalar {
-                Scalar::Ptr(ptr) => Scalar::Ptr(self.global_base_pointer(ptr)?),
-                Scalar::Int(int) => Scalar::Int(int),
-            })
-        };
-        // Early-return cases.
-        let val_val = match val.val {
+        match val.val {
             ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric),
             ty::ConstKind::Error(_) => throw_inval!(AlreadyReported(ErrorReported)),
             ty::ConstKind::Unevaluated(def, substs, promoted) => {
                 let instance = self.resolve(def, substs)?;
-                return Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into());
+                Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into())
             }
             ty::ConstKind::Infer(..) | ty::ConstKind::Placeholder(..) => {
                 span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", val)
             }
-            ty::ConstKind::Value(val_val) => val_val,
-        };
+            ty::ConstKind::Value(val_val) => self.const_val_to_op(val_val, val.ty, layout),
+        }
+    }
+
+    crate fn mir_const_to_op(
+        &self,
+        val: &mir::ConstantSource<'tcx>,
+        layout: Option<TyAndLayout<'tcx>>,
+    ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
+        match val {
+            mir::ConstantSource::Ty(ct) => self.const_to_op(ct, layout),
+            mir::ConstantSource::Val(val, ty) => self.const_val_to_op(*val, ty, None),
+        }
+    }
+
+    crate fn const_val_to_op(
+        &self,
+        val_val: ConstValue<'tcx>,
+        ty: Ty<'tcx>,
+        layout: Option<TyAndLayout<'tcx>>,
+    ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         // Other cases need layout.
-        let layout =
-            from_known_layout(self.tcx, self.param_env, layout, || self.layout_of(val.ty))?;
+        let tag_scalar = |scalar| -> InterpResult<'tcx, _> {
+            Ok(match scalar {
+                Scalar::Ptr(ptr) => Scalar::Ptr(self.global_base_pointer(ptr)?),
+                Scalar::Int(int) => Scalar::Int(int),
+            })
+        };
+        let layout = from_known_layout(self.tcx, self.param_env, layout, || self.layout_of(ty))?;
         let op = match val_val {
             ConstValue::ByRef { alloc, offset } => {
                 let id = self.tcx.create_memory_alloc(alloc);
diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs
index 20cb989196a..911224d8c1f 100644
--- a/compiler/rustc_mir/src/monomorphize/collector.rs
+++ b/compiler/rustc_mir/src/monomorphize/collector.rs
@@ -684,7 +684,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
                 for op in operands {
                     match *op {
                         mir::InlineAsmOperand::SymFn { ref value } => {
-                            let fn_ty = self.monomorphize(value.literal.ty);
+                            let fn_ty = self.monomorphize(value.literal.ty());
                             visit_fn_use(self.tcx, fn_ty, false, source, &mut self.output);
                         }
                         mir::InlineAsmOperand::SymStatic { def_id } => {
diff --git a/compiler/rustc_mir/src/shim.rs b/compiler/rustc_mir/src/shim.rs
index 0dbd7ce7f1d..796d024771d 100644
--- a/compiler/rustc_mir/src/shim.rs
+++ b/compiler/rustc_mir/src/shim.rs
@@ -421,7 +421,7 @@ impl CloneShimBuilder<'tcx> {
         let func = Operand::Constant(box Constant {
             span: self.span,
             user_ty: None,
-            literal: ty::Const::zero_sized(tcx, func_ty),
+            literal: ty::Const::zero_sized(tcx, func_ty).into(),
         });
 
         let ref_loc = self.make_place(
@@ -478,7 +478,7 @@ impl CloneShimBuilder<'tcx> {
         box Constant {
             span: self.span,
             user_ty: None,
-            literal: ty::Const::from_usize(self.tcx, value),
+            literal: ty::Const::from_usize(self.tcx, value).into(),
         }
     }
 
@@ -509,7 +509,7 @@ impl CloneShimBuilder<'tcx> {
                 Rvalue::Use(Operand::Constant(box Constant {
                     span: self.span,
                     user_ty: None,
-                    literal: len,
+                    literal: len.into(),
                 })),
             ))),
         ];
@@ -768,7 +768,7 @@ fn build_call_shim<'tcx>(
                 Operand::Constant(box Constant {
                     span,
                     user_ty: None,
-                    literal: ty::Const::zero_sized(tcx, ty),
+                    literal: ty::Const::zero_sized(tcx, ty).into(),
                 }),
                 rcvr.into_iter().collect::<Vec<_>>(),
             )
diff --git a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs b/compiler/rustc_mir/src/transform/check_consts/qualifs.rs
index 13d7166b4b5..748f65cba22 100644
--- a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/qualifs.rs
@@ -246,25 +246,27 @@ where
     };
 
     // Check the qualifs of the value of `const` items.
-    if let ty::ConstKind::Unevaluated(def, _, promoted) = constant.literal.val {
-        assert!(promoted.is_none());
-        // Don't peek inside trait associated constants.
-        if cx.tcx.trait_of_item(def.did).is_none() {
-            let qualifs = if let Some((did, param_did)) = def.as_const_arg() {
-                cx.tcx.at(constant.span).mir_const_qualif_const_arg((did, param_did))
-            } else {
-                cx.tcx.at(constant.span).mir_const_qualif(def.did)
-            };
-
-            if !Q::in_qualifs(&qualifs) {
-                return false;
-            }
+    if let Some(ct) = constant.literal.const_for_ty() {
+        if let ty::ConstKind::Unevaluated(def, _, promoted) = ct.val {
+            assert!(promoted.is_none());
+            // Don't peek inside trait associated constants.
+            if cx.tcx.trait_of_item(def.did).is_none() {
+                let qualifs = if let Some((did, param_did)) = def.as_const_arg() {
+                    cx.tcx.at(constant.span).mir_const_qualif_const_arg((did, param_did))
+                } else {
+                    cx.tcx.at(constant.span).mir_const_qualif(def.did)
+                };
+
+                if !Q::in_qualifs(&qualifs) {
+                    return false;
+                }
 
-            // Just in case the type is more specific than
-            // the definition, e.g., impl associated const
-            // with type parameters, take it into account.
+                // Just in case the type is more specific than
+                // the definition, e.g., impl associated const
+                // with type parameters, take it into account.
+            }
         }
     }
     // Otherwise use the qualifs of the type.
-    Q::in_any_value_of_ty(cx, constant.literal.ty)
+    Q::in_any_value_of_ty(cx, constant.literal.ty())
 }
diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs
index 9d03b1b027e..0d5c8953bc6 100644
--- a/compiler/rustc_mir/src/transform/const_prop.rs
+++ b/compiler/rustc_mir/src/transform/const_prop.rs
@@ -13,9 +13,9 @@ use rustc_middle::mir::visit::{
     MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor,
 };
 use rustc_middle::mir::{
-    AssertKind, BasicBlock, BinOp, Body, ClearCrossCrate, Constant, Local, LocalDecl, LocalKind,
-    Location, Operand, Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement,
-    StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE,
+    AssertKind, BasicBlock, BinOp, Body, ClearCrossCrate, Constant, ConstantSource, Local,
+    LocalDecl, LocalKind, Location, Operand, Place, Rvalue, SourceInfo, SourceScope,
+    SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE,
 };
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutError, TyAndLayout};
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
@@ -482,18 +482,21 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
             return None;
         }
 
-        match self.ecx.const_to_op(c.literal, None) {
+        match self.ecx.mir_const_to_op(&c.literal, None) {
             Ok(op) => Some(op),
             Err(error) => {
                 let tcx = self.ecx.tcx.at(c.span);
                 let err = ConstEvalErr::new(&self.ecx, error, Some(c.span));
                 if let Some(lint_root) = self.lint_root(source_info) {
-                    let lint_only = match c.literal.val {
-                        // Promoteds must lint and not error as the user didn't ask for them
-                        ConstKind::Unevaluated(_, _, Some(_)) => true,
-                        // Out of backwards compatibility we cannot report hard errors in unused
-                        // generic functions using associated constants of the generic parameters.
-                        _ => c.literal.needs_subst(),
+                    let lint_only = match c.literal {
+                        ConstantSource::Ty(ct) => match ct.val {
+                            // Promoteds must lint and not error as the user didn't ask for them
+                            ConstKind::Unevaluated(_, _, Some(_)) => true,
+                            // Out of backwards compatibility we cannot report hard errors in unused
+                            // generic functions using associated constants of the generic parameters.
+                            _ => c.literal.needs_subst(),
+                        },
+                        ConstantSource::Val(_, ty) => ty.needs_subst(),
                     };
                     if lint_only {
                         // Out of backwards compatibility we cannot report hard errors in unused
@@ -803,7 +806,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         Operand::Constant(Box::new(Constant {
             span,
             user_ty: None,
-            literal: ty::Const::from_scalar(self.tcx, scalar, ty),
+            literal: ty::Const::from_scalar(self.tcx, scalar, ty).into(),
         }))
     }
 
@@ -814,9 +817,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         source_info: SourceInfo,
     ) {
         if let Rvalue::Use(Operand::Constant(c)) = rval {
-            if !matches!(c.literal.val, ConstKind::Unevaluated(..)) {
-                trace!("skipping replace of Rvalue::Use({:?} because it is already a const", c);
-                return;
+            match c.literal {
+                ConstantSource::Ty(c) if matches!(c.val, ConstKind::Unevaluated(..)) => {}
+                _ => {
+                    trace!("skipping replace of Rvalue::Use({:?} because it is already a const", c);
+                    return;
+                }
             }
         }
 
@@ -883,13 +889,17 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                                 *rval = Rvalue::Use(Operand::Constant(Box::new(Constant {
                                     span: source_info.span,
                                     user_ty: None,
-                                    literal: self.ecx.tcx.mk_const(ty::Const {
-                                        ty,
-                                        val: ty::ConstKind::Value(ConstValue::ByRef {
-                                            alloc,
-                                            offset: Size::ZERO,
-                                        }),
-                                    }),
+                                    literal: self
+                                        .ecx
+                                        .tcx
+                                        .mk_const(ty::Const {
+                                            ty,
+                                            val: ty::ConstKind::Value(ConstValue::ByRef {
+                                                alloc,
+                                                offset: Size::ZERO,
+                                            }),
+                                        })
+                                        .into(),
                                 })));
                             }
                         }
diff --git a/compiler/rustc_mir/src/transform/elaborate_drops.rs b/compiler/rustc_mir/src/transform/elaborate_drops.rs
index 3d435f6d0e7..c0fcfb620ff 100644
--- a/compiler/rustc_mir/src/transform/elaborate_drops.rs
+++ b/compiler/rustc_mir/src/transform/elaborate_drops.rs
@@ -471,7 +471,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
         Rvalue::Use(Operand::Constant(Box::new(Constant {
             span,
             user_ty: None,
-            literal: ty::Const::from_bool(self.tcx, val),
+            literal: ty::Const::from_bool(self.tcx, val).into(),
         })))
     }
 
diff --git a/compiler/rustc_mir/src/transform/generator.rs b/compiler/rustc_mir/src/transform/generator.rs
index f299b6ecc28..c85e9b9b932 100644
--- a/compiler/rustc_mir/src/transform/generator.rs
+++ b/compiler/rustc_mir/src/transform/generator.rs
@@ -989,7 +989,7 @@ fn insert_panic_block<'tcx>(
         cond: Operand::Constant(box Constant {
             span: body.span,
             user_ty: None,
-            literal: ty::Const::from_bool(tcx, false),
+            literal: ty::Const::from_bool(tcx, false).into(),
         }),
         expected: true,
         msg: message,
diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs
index cf85503b3d5..dd06daecd5d 100644
--- a/compiler/rustc_mir/src/transform/inline.rs
+++ b/compiler/rustc_mir/src/transform/inline.rs
@@ -416,7 +416,7 @@ impl Inliner<'tcx> {
 
                 TerminatorKind::Call { func: Operand::Constant(ref f), cleanup, .. } => {
                     if let ty::FnDef(def_id, substs) =
-                        *callsite.callee.subst_mir(self.tcx, &f.literal.ty).kind()
+                        *callsite.callee.subst_mir(self.tcx, &f.literal.ty()).kind()
                     {
                         let substs = self.tcx.normalize_erasing_regions(self.param_env, substs);
                         if let Ok(Some(instance)) =
@@ -637,8 +637,11 @@ impl Inliner<'tcx> {
                 // `required_consts`, here we may not only have `ConstKind::Unevaluated`
                 // because we are calling `subst_and_normalize_erasing_regions`.
                 caller_body.required_consts.extend(
-                    callee_body.required_consts.iter().copied().filter(|&constant| {
-                        matches!(constant.literal.val, ConstKind::Unevaluated(_, _, _))
+                    callee_body.required_consts.iter().copied().filter(|&ct| {
+                        match ct.literal.const_for_ty() {
+                            Some(ct) => matches!(ct.val, ConstKind::Unevaluated(_, _, _)),
+                            None => true,
+                        }
                     }),
                 );
             }
diff --git a/compiler/rustc_mir/src/transform/instcombine.rs b/compiler/rustc_mir/src/transform/instcombine.rs
index bad82fe893e..7aaf0224164 100644
--- a/compiler/rustc_mir/src/transform/instcombine.rs
+++ b/compiler/rustc_mir/src/transform/instcombine.rs
@@ -79,7 +79,7 @@ impl<'tcx, 'a> InstCombineContext<'tcx, 'a> {
 
     fn try_eval_bool(&self, a: &Operand<'_>) -> Option<bool> {
         let a = a.constant()?;
-        if a.literal.ty.is_bool() { a.literal.val.try_to_bool() } else { None }
+        if a.literal.ty().is_bool() { a.literal.try_to_bool() } else { None }
     }
 
     /// Transform "&(*a)" ==> "a".
@@ -110,12 +110,13 @@ impl<'tcx, 'a> InstCombineContext<'tcx, 'a> {
     fn combine_len(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) {
         if let Rvalue::Len(ref place) = *rvalue {
             let place_ty = place.ty(self.local_decls, self.tcx).ty;
-            if let ty::Array(_, len) = place_ty.kind() {
+            if let ty::Array(_, len) = *place_ty.kind() {
                 if !self.should_combine(source_info, rvalue) {
                     return;
                 }
 
-                let constant = Constant { span: source_info.span, literal: len, user_ty: None };
+                let constant =
+                    Constant { span: source_info.span, literal: len.into(), user_ty: None };
                 *rvalue = Rvalue::Use(Operand::Constant(box constant));
             }
         }
diff --git a/compiler/rustc_mir/src/transform/lower_intrinsics.rs b/compiler/rustc_mir/src/transform/lower_intrinsics.rs
index d6a73360616..e6ee474285e 100644
--- a/compiler/rustc_mir/src/transform/lower_intrinsics.rs
+++ b/compiler/rustc_mir/src/transform/lower_intrinsics.rs
@@ -33,7 +33,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                                     Rvalue::Use(Operand::Constant(box Constant {
                                         span: terminator.source_info.span,
                                         user_ty: None,
-                                        literal: ty::Const::zero_sized(tcx, tcx.types.unit),
+                                        literal: ty::Const::zero_sized(tcx, tcx.types.unit).into(),
                                     })),
                                 )),
                             });
diff --git a/compiler/rustc_mir/src/transform/match_branches.rs b/compiler/rustc_mir/src/transform/match_branches.rs
index 15c2c3a160f..d04a7011ab0 100644
--- a/compiler/rustc_mir/src/transform/match_branches.rs
+++ b/compiler/rustc_mir/src/transform/match_branches.rs
@@ -93,8 +93,8 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
                         StatementKind::Assign(box (lhs_f, Rvalue::Use(Operand::Constant(f_c)))),
                         StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))),
                     ) if lhs_f == lhs_s
-                        && f_c.literal.ty.is_bool()
-                        && s_c.literal.ty.is_bool()
+                        && f_c.literal.ty().is_bool()
+                        && s_c.literal.ty().is_bool()
                         && f_c.literal.try_eval_bool(tcx, param_env).is_some()
                         && s_c.literal.try_eval_bool(tcx, param_env).is_some() => {}
 
diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs
index f60570483ce..7db790cf32b 100644
--- a/compiler/rustc_mir/src/transform/promote_consts.rs
+++ b/compiler/rustc_mir/src/transform/promote_consts.rs
@@ -921,7 +921,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                         let unit = Rvalue::Use(Operand::Constant(box Constant {
                             span: statement.source_info.span,
                             user_ty: None,
-                            literal: ty::Const::zero_sized(self.tcx, self.tcx.types.unit),
+                            literal: ty::Const::zero_sized(self.tcx, self.tcx.types.unit).into(),
                         }));
                         mem::replace(rhs, unit)
                     },
@@ -998,20 +998,22 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                 Operand::Constant(Box::new(Constant {
                     span,
                     user_ty: None,
-                    literal: tcx.mk_const(ty::Const {
-                        ty,
-                        val: ty::ConstKind::Unevaluated(
-                            def,
-                            InternalSubsts::for_item(tcx, def.did, |param, _| {
-                                if let ty::GenericParamDefKind::Lifetime = param.kind {
-                                    tcx.lifetimes.re_erased.into()
-                                } else {
-                                    tcx.mk_param_from_def(param)
-                                }
-                            }),
-                            Some(promoted_id),
-                        ),
-                    }),
+                    literal: tcx
+                        .mk_const(ty::Const {
+                            ty,
+                            val: ty::ConstKind::Unevaluated(
+                                def,
+                                InternalSubsts::for_item(tcx, def.did, |param, _| {
+                                    if let ty::GenericParamDefKind::Lifetime = param.kind {
+                                        tcx.lifetimes.re_erased.into()
+                                    } else {
+                                        tcx.mk_param_from_def(param)
+                                    }
+                                }),
+                                Some(promoted_id),
+                            ),
+                        })
+                        .into(),
                 }))
             };
             let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
@@ -1250,8 +1252,8 @@ crate fn is_const_fn_in_array_repeat_expression<'tcx>(
         if let Some(Terminator { kind: TerminatorKind::Call { func, destination, .. }, .. }) =
             &block.terminator
         {
-            if let Operand::Constant(box Constant { literal: ty::Const { ty, .. }, .. }) = func {
-                if let ty::FnDef(def_id, _) = *ty.kind() {
+            if let Operand::Constant(box Constant { literal, .. }) = func {
+                if let ty::FnDef(def_id, _) = *literal.ty().kind() {
                     if let Some((destination_place, _)) = destination {
                         if destination_place == place {
                             if is_const_fn(ccx.tcx, def_id) {
diff --git a/compiler/rustc_mir/src/transform/required_consts.rs b/compiler/rustc_mir/src/transform/required_consts.rs
index a63ab30a68f..2b518bd3a48 100644
--- a/compiler/rustc_mir/src/transform/required_consts.rs
+++ b/compiler/rustc_mir/src/transform/required_consts.rs
@@ -14,10 +14,10 @@ impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> {
 
 impl<'a, 'tcx> Visitor<'tcx> for RequiredConstsVisitor<'a, 'tcx> {
     fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) {
-        let const_kind = constant.literal.val;
-
-        if let ConstKind::Unevaluated(_, _, _) = const_kind {
-            self.required_consts.push(*constant);
+        if let Some(ct) = constant.literal.const_for_ty() {
+            if let ConstKind::Unevaluated(_, _, _) = ct.val {
+                self.required_consts.push(*constant);
+            }
         }
     }
 }
diff --git a/compiler/rustc_mir/src/transform/rustc_peek.rs b/compiler/rustc_mir/src/transform/rustc_peek.rs
index 7598be4e4a1..a6b8f20f6d4 100644
--- a/compiler/rustc_mir/src/transform/rustc_peek.rs
+++ b/compiler/rustc_mir/src/transform/rustc_peek.rs
@@ -205,7 +205,7 @@ impl PeekCall {
         if let mir::TerminatorKind::Call { func: Operand::Constant(func), args, .. } =
             &terminator.kind
         {
-            if let ty::FnDef(def_id, substs) = *func.literal.ty.kind() {
+            if let ty::FnDef(def_id, substs) = *func.literal.ty().kind() {
                 let sig = tcx.fn_sig(def_id);
                 let name = tcx.item_name(def_id);
                 if sig.abi() != Abi::RustIntrinsic || name != sym::rustc_peek {
diff --git a/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs b/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs
index 32df40ebf9e..9f473f3bae5 100644
--- a/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs
+++ b/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs
@@ -205,12 +205,12 @@ fn find_branch_value_info<'tcx>(
     match (left, right) {
         (Constant(branch_value), Copy(to_switch_on) | Move(to_switch_on))
         | (Copy(to_switch_on) | Move(to_switch_on), Constant(branch_value)) => {
-            let branch_value_ty = branch_value.literal.ty;
+            let branch_value_ty = branch_value.literal.ty();
             // we only want to apply this optimization if we are matching on integrals (and chars), as it is not possible to switch on floats
             if !branch_value_ty.is_integral() && !branch_value_ty.is_char() {
                 return None;
             };
-            let branch_value_scalar = branch_value.literal.val.try_to_scalar()?;
+            let branch_value_scalar = branch_value.literal.try_to_scalar()?;
             Some((branch_value_scalar, branch_value_ty, *to_switch_on))
         }
         _ => None,
diff --git a/compiler/rustc_mir/src/util/elaborate_drops.rs b/compiler/rustc_mir/src/util/elaborate_drops.rs
index b22dadcd7d2..e9190d7ebef 100644
--- a/compiler/rustc_mir/src/util/elaborate_drops.rs
+++ b/compiler/rustc_mir/src/util/elaborate_drops.rs
@@ -1035,7 +1035,7 @@ where
         Operand::Constant(box Constant {
             span: self.source_info.span,
             user_ty: None,
-            literal: ty::Const::from_usize(self.tcx(), val.into()),
+            literal: ty::Const::from_usize(self.tcx(), val.into()).into(),
         })
     }
 
diff --git a/compiler/rustc_mir/src/util/find_self_call.rs b/compiler/rustc_mir/src/util/find_self_call.rs
index 5b146eeb87c..ddda98d1616 100644
--- a/compiler/rustc_mir/src/util/find_self_call.rs
+++ b/compiler/rustc_mir/src/util/find_self_call.rs
@@ -17,8 +17,8 @@ pub fn find_self_call<'tcx>(
         &body[block].terminator
     {
         debug!("find_self_call: func={:?}", func);
-        if let Operand::Constant(box Constant { literal: ty::Const { ty, .. }, .. }) = func {
-            if let ty::FnDef(def_id, substs) = *ty.kind() {
+        if let Operand::Constant(box Constant { literal, .. }) = func {
+            if let ty::FnDef(def_id, substs) = *literal.ty().kind() {
                 if let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
                     tcx.opt_associated_item(def_id)
                 {
diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs
index 247a0beccaf..8e38a87a8f4 100644
--- a/compiler/rustc_mir/src/util/pretty.rs
+++ b/compiler/rustc_mir/src/util/pretty.rs
@@ -439,7 +439,7 @@ impl Visitor<'tcx> for ExtraComments<'tcx> {
     fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
         self.super_constant(constant, location);
         let Constant { span, user_ty, literal } = constant;
-        match literal.ty.kind() {
+        match literal.ty().kind() {
             ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char => {}
             // Unit type
             ty::Tuple(tys) if tys.is_empty() => {}
@@ -449,7 +449,12 @@ impl Visitor<'tcx> for ExtraComments<'tcx> {
                 if let Some(user_ty) = user_ty {
                     self.push(&format!("+ user_ty: {:?}", user_ty));
                 }
-                self.push(&format!("+ literal: {:?}", literal));
+                match literal {
+                    ConstantSource::Ty(literal) => self.push(&format!("+ literal: {:?}", literal)),
+                    ConstantSource::Val(val, ty) => {
+                        self.push(&format!("+ literal: {:?}, {}", val, ty))
+                    }
+                }
             }
         }
     }
diff --git a/compiler/rustc_mir_build/src/build/cfg.rs b/compiler/rustc_mir_build/src/build/cfg.rs
index 42e2b242d77..e562e52f841 100644
--- a/compiler/rustc_mir_build/src/build/cfg.rs
+++ b/compiler/rustc_mir_build/src/build/cfg.rs
@@ -68,7 +68,7 @@ impl<'tcx> CFG<'tcx> {
             Rvalue::Use(Operand::Constant(box Constant {
                 span: source_info.span,
                 user_ty: None,
-                literal: ty::Const::zero_sized(tcx, tcx.types.unit),
+                literal: ty::Const::zero_sized(tcx, tcx.types.unit).into(),
             })),
         );
     }
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index 727aedb0ef8..c8f9993def3 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -11,7 +11,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     crate fn as_constant(&mut self, expr: &Expr<'_, 'tcx>) -> Constant<'tcx> {
         let this = self;
         let Expr { ty, temp_lifetime: _, span, ref kind } = *expr;
-        match kind {
+        match *kind {
             ExprKind::Scope { region_scope: _, lint_level: _, value } => this.as_constant(value),
             ExprKind::Literal { literal, user_ty, const_id: _ } => {
                 let user_ty = user_ty.map(|user_ty| {
@@ -22,11 +22,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     })
                 });
                 assert_eq!(literal.ty, ty);
-                Constant { span, user_ty, literal }
+                Constant { span, user_ty, literal: literal.into() }
             }
-            ExprKind::StaticRef { literal, .. } => Constant { span, user_ty: None, literal },
+            ExprKind::StaticRef { literal, .. } => Constant { span, user_ty: None, literal: literal.into() },
             ExprKind::ConstBlock { value } => {
-                Constant { span: span, user_ty: None, literal: value }
+                Constant { span: span, user_ty: None, literal: value.into() }
             }
             _ => span_bug!(span, "expression is not a valid constant {:?}", kind),
         }
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index d73e5eef70c..65531b60818 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -219,7 +219,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 block.and(Rvalue::Use(Operand::Constant(box Constant {
                     span: expr_span,
                     user_ty: None,
-                    literal: ty::Const::zero_sized(this.tcx, this.tcx.types.unit),
+                    literal: ty::Const::zero_sized(this.tcx, this.tcx.types.unit).into(),
                 })))
             }
             ExprKind::Yield { .. }
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 47f75825fb6..1dc6506e30d 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -146,7 +146,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     Constant {
                         span: expr_span,
                         user_ty: None,
-                        literal: ty::Const::from_bool(this.tcx, true),
+                        literal: ty::Const::from_bool(this.tcx, true).into(),
                     },
                 );
 
@@ -157,7 +157,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     Constant {
                         span: expr_span,
                         user_ty: None,
-                        literal: ty::Const::from_bool(this.tcx, false),
+                        literal: ty::Const::from_bool(this.tcx, false).into(),
                     },
                 );
 
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 48abaa8d35f..7f26c0e5d76 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -429,7 +429,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     // Need to experiment.
                     user_ty: None,
 
-                    literal: method,
+                    literal: method.into(),
                 }),
                 args: vec![val, expect],
                 destination: Some((eq_result, eq_block)),
diff --git a/compiler/rustc_mir_build/src/build/misc.rs b/compiler/rustc_mir_build/src/build/misc.rs
index 62c217a12aa..a1126d1c3d5 100644
--- a/compiler/rustc_mir_build/src/build/misc.rs
+++ b/compiler/rustc_mir_build/src/build/misc.rs
@@ -30,6 +30,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         span: Span,
         literal: &'tcx ty::Const<'tcx>,
     ) -> Operand<'tcx> {
+        let literal = literal.into();
         let constant = box Constant { span, user_ty: None, literal };
         Operand::Constant(constant)
     }
@@ -57,7 +58,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             Constant {
                 span: source_info.span,
                 user_ty: None,
-                literal: ty::Const::from_usize(self.tcx, value),
+                literal: ty::Const::from_usize(self.tcx, value).into(),
             },
         );
         temp
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index f4983dd7531..5ace45e4c7c 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -377,7 +377,10 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
                 let local = self.place_to_local(span, p)?;
                 Ok(self.locals[local])
             }
-            mir::Operand::Constant(ct) => Ok(self.add_node(Node::Leaf(ct.literal), span)),
+            mir::Operand::Constant(ct) => match ct.literal {
+                mir::ConstantSource::Ty(ct) => Ok(self.add_node(Node::Leaf(ct), span)),
+                mir::ConstantSource::Val(..) => self.error(Some(span), "unsupported constant")?,
+            },
         }
     }