about summary refs log tree commit diff
diff options
context:
space:
mode:
authorb-naber <bn263@gmx.de>2022-06-27 16:32:47 +0200
committerb-naber <bn263@gmx.de>2022-09-13 17:40:59 +0200
commita4bbb8db5c4c702265b8afcc1313684a127ddd6a (patch)
treef1643aa200cd35761c02faf68189ec86276fb0d9
parent7098c181f8447810fadb1776d3ffa3cdc93ce402 (diff)
downloadrust-a4bbb8db5c4c702265b8afcc1313684a127ddd6a.tar.gz
rust-a4bbb8db5c4c702265b8afcc1313684a127ddd6a.zip
use ty::Unevaluated<'tcx, ()> in type system
-rw-r--r--Cargo.lock84
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs19
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/constant.rs36
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs13
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs7
-rw-r--r--compiler/rustc_const_eval/src/transform/promote_consts.rs12
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs7
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs11
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs4
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs70
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs23
-rw-r--r--compiler/rustc_middle/src/mir/type_foldable.rs3
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs1
-rw-r--r--compiler/rustc_middle/src/ty/abstract_const.rs2
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs6
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs11
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs12
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs6
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs26
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs25
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs6
-rw-r--r--compiler/rustc_mir_transform/src/required_consts.rs16
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs17
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs34
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs2
-rw-r--r--compiler/rustc_typeck/src/collect.rs4
-rw-r--r--src/librustdoc/clean/utils.rs5
32 files changed, 301 insertions, 189 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 4e0e72d3415..36bd77c5d93 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -288,7 +288,7 @@ dependencies = [
 
 [[package]]
 name = "cargo"
-version = "0.66.0"
+version = "0.65.0"
 dependencies = [
  "anyhow",
  "atty",
@@ -299,6 +299,7 @@ dependencies = [
  "cargo-util",
  "clap",
  "crates-io",
+ "crossbeam-utils",
  "curl",
  "curl-sys",
  "env_logger 0.9.0",
@@ -322,6 +323,7 @@ dependencies = [
  "libgit2-sys",
  "log",
  "memchr",
+ "num_cpus",
  "opener",
  "openssl",
  "os_info",
@@ -381,7 +383,6 @@ dependencies = [
 name = "cargo-miri"
 version = "0.1.0"
 dependencies = [
- "cargo_metadata 0.15.0",
  "directories",
  "rustc-workspace-hack",
  "rustc_version",
@@ -430,7 +431,6 @@ dependencies = [
  "termcolor",
  "toml_edit",
  "url",
- "winapi",
 ]
 
 [[package]]
@@ -1004,6 +1004,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "ctor"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c"
+dependencies = [
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "curl"
 version = "0.4.43"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1560,9 +1570,9 @@ dependencies = [
 
 [[package]]
 name = "git2"
-version = "0.15.0"
+version = "0.14.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2994bee4a3a6a51eb90c218523be382fd7ea09b16380b9312e9dbe955ff7c7d1"
+checksum = "d0155506aab710a86160ddb504a480d2964d7ab5b9e62419be69e0032bc5931c"
 dependencies = [
  "bitflags",
  "libc",
@@ -1575,9 +1585,9 @@ dependencies = [
 
 [[package]]
 name = "git2-curl"
-version = "0.16.0"
+version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed817a00721e2f8037ba722e60358d4956dae9cca10315fc982f967907d3b0cd"
+checksum = "1ee51709364c341fbb6fe2a385a290fb9196753bdde2fc45447d27cd31b11b13"
 dependencies = [
  "curl",
  "git2",
@@ -1935,29 +1945,10 @@ dependencies = [
 ]
 
 [[package]]
-name = "libffi"
-version = "3.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e454b3efb16fba3b17810ae5e41df02b649e564ab3c5a34b3b93ed07ad287e6"
-dependencies = [
- "libc",
- "libffi-sys",
-]
-
-[[package]]
-name = "libffi-sys"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab4106b7f09d7b87d021334d5618fac1dfcfb824d4c5fe111ff0074dfd242e15"
-dependencies = [
- "cc",
-]
-
-[[package]]
 name = "libgit2-sys"
-version = "0.14.0+1.5.0"
+version = "0.13.4+1.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47a00859c70c8a4f7218e6d1cc32875c4b55f6799445b842b0d8ed5e4c3d959b"
+checksum = "d0fa6563431ede25f5cc7f6d803c6afbc1c5d3ad3d4925d12c882bf2b526f5d1"
 dependencies = [
  "cc",
  "libc",
@@ -2247,8 +2238,6 @@ dependencies = [
  "getrandom 0.2.0",
  "lazy_static",
  "libc",
- "libffi",
- "libloading",
  "log",
  "measureme",
  "rand 0.8.5",
@@ -2422,6 +2411,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
 
 [[package]]
+name = "output_vt100"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
 name = "owo-colors"
 version = "3.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2663,6 +2661,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 
 [[package]]
+name = "pretty_assertions"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755"
+dependencies = [
+ "ctor",
+ "diff",
+ "output_vt100",
+ "yansi",
+]
+
+[[package]]
 name = "pretty_env_logger"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4540,9 +4550,9 @@ checksum = "da73c8f77aebc0e40c300b93f0a5f1bece7a248a36eee287d4e095f35c7b7d6e"
 
 [[package]]
 name = "snapbox"
-version = "0.3.3"
+version = "0.2.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44d199ccf8f606592df2d145db26f2aa45344e23c64b074cc5a4047f1d99b0f7"
+checksum = "767a1d5da232b6959cd1bd5c9e8db8a7cce09c3038e89deedb49a549a2aefd93"
 dependencies = [
  "concolor",
  "content_inspector",
@@ -4558,9 +4568,9 @@ dependencies = [
 
 [[package]]
 name = "snapbox-macros"
-version = "0.3.0"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a253e6f894cfa440cba00600a249fa90869d8e0ec45ab274a456e043a0ce8f2"
+checksum = "c01dea7e04cbb27ef4c86e9922184608185f7cd95c1763bc30d727cda4a5e930"
 
 [[package]]
 name = "socket2"
@@ -5039,16 +5049,14 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
 
 [[package]]
 name = "ui_test"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d1f546a5883ae78da735bba529ec1116661e2f73582f23920d994dc97da3a22"
+version = "0.1.0"
 dependencies = [
  "cargo_metadata 0.15.0",
  "color-eyre",
  "colored",
  "crossbeam",
- "diff",
  "lazy_static",
+ "pretty_assertions",
  "regex",
  "rustc_version",
  "serde",
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index fc0e95f30c9..ed9ede029a8 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -354,11 +354,13 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
             let tcx = self.tcx();
             let maybe_uneval = match constant.literal {
                 ConstantKind::Ty(ct) => match ct.kind() {
-                    ty::ConstKind::Unevaluated(uv) => Some(uv),
+                    ty::ConstKind::Unevaluated(uv) => Some(uv.expand()),
                     _ => None,
                 },
+                ConstantKind::Unevaluated(uv, _) => Some(uv),
                 _ => None,
             };
+
             if let Some(uv) = maybe_uneval {
                 if let Some(promoted) = uv.promoted {
                     let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
@@ -1813,11 +1815,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         if let Operand::Constant(constant) = op {
             let maybe_uneval = match constant.literal {
                 ConstantKind::Ty(ct) => match ct.kind() {
-                    ty::ConstKind::Unevaluated(uv) => Some(uv),
+                    ty::ConstKind::Unevaluated(uv) => Some(uv.expand()),
                     _ => None,
                 },
+                ConstantKind::Unevaluated(uv, _) => Some(uv),
                 _ => None,
             };
+
             if let Some(uv) = maybe_uneval {
                 if uv.promoted.is_none() {
                     let tcx = self.tcx();
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index 0305341da78..7bf578b6a4e 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -124,11 +124,7 @@ pub(crate) fn codegen_constant<'tcx>(
 ) -> CValue<'tcx> {
     let const_ = match fx.monomorphize(constant.literal) {
         ConstantKind::Ty(ct) => ct,
-        ConstantKind::Val(val, ty) => return codegen_const_value(fx, val, ty),
-    };
-    let const_val = match const_.kind() {
-        ConstKind::Value(valtree) => fx.tcx.valtree_to_const_val((const_.ty(), valtree)),
-        ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
+        ConstantKind::Unevaluated(mir::Unevaluated { def, substs, promoted })
             if fx.tcx.is_static(def.did) =>
         {
             assert!(substs.is_empty());
@@ -136,7 +132,7 @@ pub(crate) fn codegen_constant<'tcx>(
 
             return codegen_static_ref(fx, def.did, fx.layout_of(const_.ty())).to_cvalue(fx);
         }
-        ConstKind::Unevaluated(unevaluated) => {
+        ConstantKind::Unevaluated(unevaluated) => {
             match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) {
                 Ok(const_val) => const_val,
                 Err(_) => {
@@ -144,6 +140,17 @@ pub(crate) fn codegen_constant<'tcx>(
                 }
             }
         }
+        ConstantKind::Val(val, ty) => return codegen_const_value(fx, val, ty),
+    };
+    let const_val = match const_.kind() {
+        ConstKind::Value(valtree) => fx.tcx.valtree_to_const_val((const_.ty(), valtree)),
+        ConstKind::Unevaluated(ty::Unevaluated { def, 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(const_.ty())).to_cvalue(fx);
+        }
         ConstKind::Param(_)
         | ConstKind::Infer(_)
         | ConstKind::Bound(_, _)
diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs
index 9a995fbf65c..4c6ab457c49 100644
--- a/compiler/rustc_codegen_ssa/src/mir/constant.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs
@@ -25,26 +25,26 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         constant: &mir::Constant<'tcx>,
     ) -> Result<ConstValue<'tcx>, ErrorHandled> {
         let ct = self.monomorphize(constant.literal);
-        let ct = match ct {
-            mir::ConstantKind::Ty(ct) => ct,
+        let uv = match ct {
+            mir::ConstantKind::Ty(ct) => match ct.kind() {
+                ty::ConstKind::Unevaluated(uv) => uv.expand(),
+                ty::ConstKind::Value(val) => {
+                    return Ok(self.cx.tcx().valtree_to_const_val((ct.ty(), val)));
+                }
+                err => span_bug!(
+                    constant.span,
+                    "encountered bad ConstKind after monomorphizing: {:?}",
+                    err
+                ),
+            },
+            mir::ConstantKind::Unevaluated(uv, _) => uv,
             mir::ConstantKind::Val(val, _) => return Ok(val),
         };
-        match ct.kind() {
-            ty::ConstKind::Unevaluated(ct) => self
-                .cx
-                .tcx()
-                .const_eval_resolve(ty::ParamEnv::reveal_all(), ct, None)
-                .map_err(|err| {
-                    self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
-                    err
-                }),
-            ty::ConstKind::Value(val) => Ok(self.cx.tcx().valtree_to_const_val((ct.ty(), val))),
-            err => span_bug!(
-                constant.span,
-                "encountered bad ConstKind after monomorphizing: {:?}",
-                err
-            ),
-        }
+
+        self.cx.tcx().const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).map_err(|err| {
+            self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
+            err
+        })
     }
 
     /// process constant containing SIMD shuffle indices
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index f6c4f7dd112..9784de1fffc 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -565,7 +565,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
             ty::ConstKind::Unevaluated(uv) => {
                 let instance = self.resolve(uv.def, uv.substs)?;
-                Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())
+                Ok(self.eval_to_allocation(GlobalId { instance, promoted: None })?.into())
             }
             ty::ConstKind::Bound(..) | ty::ConstKind::Infer(..) => {
                 span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", c)
@@ -578,6 +578,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         }
     }
 
+    /// Tries to evaluate an unevaluated constant from the MIR (and not the type-system).
+    #[inline]
+    pub fn uneval_to_op(
+        &self,
+        uneval: &ty::Unevaluated<'tcx>,
+    ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
+        let instance = self.resolve(uneval.def, uneval.substs)?;
+        Ok(self.eval_to_allocation(GlobalId { instance, promoted: None })?.into())
+    }
+
     pub fn mir_const_to_op(
         &self,
         val: &mir::ConstantKind<'tcx>,
@@ -586,6 +596,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         match val {
             mir::ConstantKind::Ty(ct) => self.const_to_op(*ct, layout),
             mir::ConstantKind::Val(val, ty) => self.const_val_to_op(*val, *ty, layout),
+            mir::ConstantKind::Unevaluated(uv, _) => self.uneval_to_op(uv),
         }
     }
 
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index 45dadcfff2e..fce799d47ec 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -347,14 +347,15 @@ where
 
     // Check the qualifs of the value of `const` items.
     if let Some(ct) = constant.literal.const_for_ty() {
-        if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) = ct.kind()
+        if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: _ }) =
+            ct.kind()
         {
             // Use qualifs of the type for the promoted. Promoteds in MIR body should be possible
             // only for `NeedsNonConstDrop` with precise drop checking. This is the only const
             // check performed after the promotion. Verify that with an assertion.
-            assert!(promoted.is_none() || Q::ALLOW_PROMOTED);
+
             // Don't peek inside trait associated constants.
-            if promoted.is_none() && cx.tcx.trait_of_item(def.did).is_none() {
+            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 {
diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index f5ba408bee0..f7a7cc88a52 100644
--- a/compiler/rustc_const_eval/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -840,21 +840,15 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                 promoted.span = span;
                 promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span);
                 let substs = tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def.did));
-                let _const = tcx.mk_const(ty::ConstS {
-                    ty,
-                    kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
-                        def,
-                        substs,
-                        promoted: Some(promoted_id),
-                    }),
-                });
+                let uneval = ty::Unevaluated { def, substs, promoted: Some(promoted_id) };
 
                 Operand::Constant(Box::new(Constant {
                     span,
                     user_ty: None,
-                    literal: ConstantKind::from_const(_const, tcx),
+                    literal: ConstantKind::Unevaluated(uneval, ty),
                 }))
             };
+
             let blocks = self.source.basic_blocks.as_mut();
             let local_decls = &mut self.source.local_decls;
             let loc = candidate.location;
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index 524383e381f..c406df9e411 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -743,7 +743,8 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                 }
             }
             ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
-                assert_eq!(promoted, None);
+                assert_eq!(promoted, ());
+
                 let substs = self.relate_with_variance(
                     ty::Variance::Invariant,
                     ty::VarianceDiagInfo::default(),
@@ -964,13 +965,15 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
                 }
             }
             ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
-                assert_eq!(promoted, None);
+                assert_eq!(promoted, ());
+
                 let substs = self.relate_with_variance(
                     ty::Variance::Invariant,
                     ty::VarianceDiagInfo::default(),
                     substs,
                     substs,
                 )?;
+
                 Ok(self.tcx().mk_const(ty::ConstS {
                     ty: c.ty(),
                     kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index bbbc044b85a..7bd8f423a01 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1673,7 +1673,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn try_const_eval_resolve(
         &self,
         param_env: ty::ParamEnv<'tcx>,
-        unevaluated: ty::Unevaluated<'tcx>,
+        unevaluated: ty::Unevaluated<'tcx, ()>,
         ty: Ty<'tcx>,
         span: Option<Span>,
     ) -> Result<ty::Const<'tcx>, ErrorHandled> {
@@ -1708,7 +1708,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn const_eval_resolve(
         &self,
         mut param_env: ty::ParamEnv<'tcx>,
-        unevaluated: ty::Unevaluated<'tcx>,
+        unevaluated: ty::Unevaluated<'tcx, ()>,
         span: Option<Span>,
     ) -> EvalToValTreeResult<'tcx> {
         let mut substs = self.resolve_vars_if_possible(unevaluated.substs);
@@ -1739,11 +1739,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         debug!(?param_env_erased);
         debug!(?substs_erased);
 
-        let unevaluated = ty::Unevaluated {
-            def: unevaluated.def,
-            substs: substs_erased,
-            promoted: unevaluated.promoted,
-        };
+        let unevaluated =
+            ty::Unevaluated { def: unevaluated.def, substs: substs_erased, promoted: () };
 
         // The return value is the evaluated value which doesn't contain any reference to inference
         // variables, thus we don't need to substitute back the original values.
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index 786927e2dad..4207988d700 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -63,7 +63,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn const_eval_resolve_for_typeck(
         self,
         param_env: ty::ParamEnv<'tcx>,
-        ct: ty::Unevaluated<'tcx>,
+        ct: ty::Unevaluated<'tcx, ()>,
         span: Option<Span>,
     ) -> EvalToValTreeResult<'tcx> {
         // Cannot resolve `Unevaluated` constants that contain inference
@@ -78,7 +78,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
         match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
             Ok(Some(instance)) => {
-                let cid = GlobalId { instance, promoted: ct.promoted };
+                let cid = GlobalId { instance, promoted: None };
                 self.const_eval_global_id_for_typeck(param_env, cid, span)
             }
             Ok(None) => Err(ErrorHandled::TooGeneric),
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index dd768c5358d..7c9b1e492d9 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -3,7 +3,7 @@
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
 
 use crate::mir::interpret::{
-    AllocRange, ConstAllocation, ConstValue, GlobalAlloc, LitToConstInput, Scalar,
+    AllocRange, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, LitToConstInput, Scalar,
 };
 use crate::mir::visit::MirVisitable;
 use crate::ty::codec::{TyDecoder, TyEncoder};
@@ -2061,6 +2061,10 @@ pub struct Constant<'tcx> {
 pub enum ConstantKind<'tcx> {
     /// This constant came from the type system
     Ty(ty::Const<'tcx>),
+
+    /// An unevaluated constant that cannot go back into the type system.
+    Unevaluated(ty::Unevaluated<'tcx, Option<Promoted>>, Ty<'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>),
@@ -2091,7 +2095,7 @@ impl<'tcx> ConstantKind<'tcx> {
     pub fn const_for_ty(&self) -> Option<ty::Const<'tcx>> {
         match self {
             ConstantKind::Ty(c) => Some(*c),
-            ConstantKind::Val(..) => None,
+            ConstantKind::Val(..) | ConstantKind::Unevaluated(..) => None,
         }
     }
 
@@ -2099,7 +2103,7 @@ impl<'tcx> ConstantKind<'tcx> {
     pub fn ty(&self) -> Ty<'tcx> {
         match self {
             ConstantKind::Ty(c) => c.ty(),
-            ConstantKind::Val(_, ty) => *ty,
+            ConstantKind::Val(_, ty) | ConstantKind::Unevaluated(_, ty) => *ty,
         }
     }
 
@@ -2111,6 +2115,7 @@ impl<'tcx> ConstantKind<'tcx> {
                 _ => None,
             },
             ConstantKind::Val(val, _) => Some(val),
+            ConstantKind::Unevaluated(..) => None,
         }
     }
 
@@ -2125,6 +2130,7 @@ impl<'tcx> ConstantKind<'tcx> {
                 _ => None,
             },
             ConstantKind::Val(val, _) => val.try_to_scalar(),
+            ConstantKind::Unevaluated(..) => None,
         }
     }
 
@@ -2157,6 +2163,14 @@ impl<'tcx> ConstantKind<'tcx> {
                 }
             }
             Self::Val(_, _) => self,
+            Self::Unevaluated(uneval, ty) => {
+                // FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
+                match tcx.const_eval_resolve(param_env, uneval, None) {
+                    Ok(val) => Self::Val(val, ty),
+                    Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => self,
+                    Err(_) => Self::Ty(tcx.const_error(ty)),
+                }
+            }
         }
     }
 
@@ -2182,6 +2196,18 @@ impl<'tcx> ConstantKind<'tcx> {
                     tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
                 val.try_to_bits(size)
             }
+            Self::Unevaluated(uneval, ty) => {
+                match tcx.const_eval_resolve(param_env, *uneval, None) {
+                    Ok(val) => {
+                        let size = tcx
+                            .layout_of(param_env.with_reveal_all_normalized(tcx).and(*ty))
+                            .ok()?
+                            .size;
+                        val.try_to_bits(size)
+                    }
+                    Err(_) => None,
+                }
+            }
         }
     }
 
@@ -2190,6 +2216,12 @@ impl<'tcx> ConstantKind<'tcx> {
         match self {
             Self::Ty(ct) => ct.try_eval_bool(tcx, param_env),
             Self::Val(val, _) => val.try_to_bool(),
+            Self::Unevaluated(uneval, _) => {
+                match tcx.const_eval_resolve(param_env, *uneval, None) {
+                    Ok(val) => val.try_to_bool(),
+                    Err(_) => None,
+                }
+            }
         }
     }
 
@@ -2198,6 +2230,12 @@ impl<'tcx> ConstantKind<'tcx> {
         match self {
             Self::Ty(ct) => ct.try_eval_usize(tcx, param_env),
             Self::Val(val, _) => val.try_to_machine_usize(tcx),
+            Self::Unevaluated(uneval, _) => {
+                match tcx.const_eval_resolve(param_env, *uneval, None) {
+                    Ok(val) => val.try_to_machine_usize(tcx),
+                    Err(_) => None,
+                }
+            }
         }
     }
 
@@ -2293,15 +2331,16 @@ impl<'tcx> ConstantKind<'tcx> {
         let substs =
             ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
                 .substs;
-        debug_assert!(!substs.has_free_regions());
-        Self::Ty(tcx.mk_const(ty::ConstS {
-            kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
-                def: ty::WithOptConstParam::unknown(def_id).to_global(),
-                substs,
-                promoted: None,
-            }),
-            ty,
-        }))
+
+        let uneval = ty::Unevaluated {
+            def: ty::WithOptConstParam::unknown(def_id).to_global(),
+            substs,
+            promoted: None,
+        };
+
+        debug_assert!(!uneval.has_free_regions());
+
+        Self::Unevaluated(uneval, ty)
     }
 
     #[instrument(skip(tcx), level = "debug", ret)]
@@ -2398,7 +2437,7 @@ impl<'tcx> ConstantKind<'tcx> {
                     kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
                         def: def.to_global(),
                         substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
-                        promoted: None,
+                        promoted: (),
                     }),
                     ty,
                 }))
@@ -2412,6 +2451,7 @@ impl<'tcx> ConstantKind<'tcx> {
                 let const_val = tcx.valtree_to_const_val((c.ty(), valtree));
                 Self::Val(const_val, c.ty())
             }
+            ty::ConstKind::Unevaluated(uv) => Self::Unevaluated(uv.expand(), c.ty()),
             _ => Self::Ty(c),
         }
     }
@@ -2612,6 +2652,10 @@ impl<'tcx> Display for ConstantKind<'tcx> {
         match *self {
             ConstantKind::Ty(c) => pretty_print_const(c, fmt, true),
             ConstantKind::Val(val, ty) => pretty_print_const_value(val, ty, fmt, true),
+            ConstantKind::Unevaluated(..) => {
+                fmt.write_str("_")?;
+                Ok(())
+            }
         }
     }
 }
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 88c16189f1d..3c559e2fe20 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -464,12 +464,14 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
             let val = match literal {
                 ConstantKind::Ty(ct) => match ct.kind() {
                     ty::ConstKind::Param(p) => format!("Param({})", p),
-                    ty::ConstKind::Unevaluated(uv) => format!(
-                        "Unevaluated({}, {:?}, {:?})",
-                        self.tcx.def_path_str(uv.def.did),
-                        uv.substs,
-                        uv.promoted,
-                    ),
+                    ty::ConstKind::Unevaluated(uv) => {
+                        format!(
+                            "Unevaluated({}, {:?}, {:?})",
+                            self.tcx.def_path_str(uv.def.did),
+                            uv.substs,
+                            uv.promoted,
+                        )
+                    }
                     ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)),
                     ty::ConstKind::Error(_) => "Error".to_string(),
                     // These variants shouldn't exist in the MIR.
@@ -477,6 +479,14 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
                     | ty::ConstKind::Infer(_)
                     | ty::ConstKind::Bound(..) => bug!("unexpected MIR constant: {:?}", literal),
                 },
+                ConstantKind::Unevaluated(uv, _) => {
+                    format!(
+                        "Unevaluated({}, {:?}, {:?})",
+                        self.tcx.def_path_str(uv.def.did),
+                        uv.substs,
+                        uv.promoted,
+                    )
+                }
                 // To keep the diffs small, we render this like we render `ty::Const::Value`.
                 //
                 // This changes once `ty::Const::Value` is represented using valtrees.
@@ -702,6 +712,7 @@ pub fn write_allocations<'tcx>(
                 ConstantKind::Val(val, _) => {
                     self.0.extend(alloc_ids_from_const_val(val));
                 }
+                ConstantKind::Unevaluated(..) => {}
             }
         }
     }
diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs
index 82a6b0c506f..e5aadac8739 100644
--- a/compiler/rustc_middle/src/mir/type_foldable.rs
+++ b/compiler/rustc_middle/src/mir/type_foldable.rs
@@ -235,6 +235,9 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ConstantKind<'tcx> {
         match self {
             ConstantKind::Ty(c) => Ok(ConstantKind::Ty(c.try_fold_with(folder)?)),
             ConstantKind::Val(v, t) => Ok(ConstantKind::Val(v, t.try_fold_with(folder)?)),
+            ConstantKind::Unevaluated(uv, t) => {
+                Ok(ConstantKind::Unevaluated(uv, t.try_fold_with(folder)?))
+            }
         }
     }
 }
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 708ea4398c8..6dde8c8b65d 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -879,6 +879,7 @@ macro_rules! make_mir_visitor {
                 match literal {
                     ConstantKind::Ty(ct) => self.visit_const($(& $mutability)? *ct, location),
                     ConstantKind::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
+                    ConstantKind::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
                 }
             }
 
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index bed809930da..8f79b4705ad 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -42,7 +42,7 @@ impl<'tcx> AbstractConst<'tcx> {
         ct: ty::Const<'tcx>,
     ) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> {
         match ct.kind() {
-            ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv.shrink()),
+            ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv),
             ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => Err(reported),
             _ => Ok(None),
         }
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 2eb5cffa6bc..339ff4d3593 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -41,7 +41,7 @@ pub struct ConstS<'tcx> {
 }
 
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-static_assert_size!(ConstS<'_>, 48);
+static_assert_size!(ConstS<'_>, 40);
 
 impl<'tcx> Const<'tcx> {
     #[inline]
@@ -84,7 +84,7 @@ impl<'tcx> Const<'tcx> {
                 kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
                     def: def.to_global(),
                     substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
-                    promoted: None,
+                    promoted: (),
                 }),
                 ty,
             }),
@@ -181,7 +181,7 @@ impl<'tcx> Const<'tcx> {
                     kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
                         def: ty::WithOptConstParam::unknown(def_id).to_global(),
                         substs,
-                        promoted: None,
+                        promoted: (),
                     }),
                     ty,
                 })
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index ff20da65c01..3c21b89c97d 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -11,6 +11,7 @@ use rustc_macros::HashStable;
 use rustc_target::abi::Size;
 
 use super::ScalarInt;
+
 /// An unevaluated, potentially generic, constant.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
 #[derive(Hash, HashStable)]
@@ -66,7 +67,7 @@ pub enum ConstKind<'tcx> {
 
     /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
     /// variants when the code is monomorphic enough for that.
-    Unevaluated(Unevaluated<'tcx>),
+    Unevaluated(Unevaluated<'tcx, ()>),
 
     /// Used to hold computed value.
     Value(ty::ValTree<'tcx>),
@@ -77,7 +78,7 @@ pub enum ConstKind<'tcx> {
 }
 
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-static_assert_size!(ConstKind<'_>, 40);
+static_assert_size!(ConstKind<'_>, 32);
 
 impl<'tcx> ConstKind<'tcx> {
     #[inline]
@@ -184,6 +185,8 @@ impl<'tcx> ConstKind<'tcx> {
         if let ConstKind::Unevaluated(unevaluated) = self {
             use crate::mir::interpret::ErrorHandled;
 
+            assert_eq!(unevaluated.promoted, ());
+
             // HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
             // also does later, but we want to do it before checking for
             // inference variables.
@@ -204,7 +207,7 @@ impl<'tcx> ConstKind<'tcx> {
                 tcx.param_env(unevaluated.def.did).and(ty::Unevaluated {
                     def: unevaluated.def,
                     substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did),
-                    promoted: unevaluated.promoted,
+                    promoted: (),
                 })
             } else {
                 param_env_and
@@ -228,7 +231,7 @@ impl<'tcx> ConstKind<'tcx> {
                     }
                 }
                 EvalMode::Mir => {
-                    match tcx.const_eval_resolve(param_env, unevaluated, None) {
+                    match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) {
                         // NOTE(eddyb) `val` contains no lifetimes/types/consts,
                         // and we use the original type, so nothing from `substs`
                         // (which may be identity substs, see above),
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index e9eecfe78d3..afe97e5f92f 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1197,15 +1197,9 @@ pub trait PrettyPrinter<'tcx>:
         }
 
         match ct.kind() {
-            ty::ConstKind::Unevaluated(ty::Unevaluated {
-                def,
-                substs,
-                promoted: Some(promoted),
-            }) => {
-                p!(print_value_path(def.did, substs));
-                p!(write("::{:?}", promoted));
-            }
-            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: None }) => {
+            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
+                assert_eq!(promoted, ());
+
                 match self.tcx().def_kind(def.did) {
                     DefKind::Static(..) | DefKind::Const | DefKind::AssocConst => {
                         p!(print_value_path(def.did, substs))
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 81476195d29..488d9242b11 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -613,7 +613,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
         (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
             if tcx.features().generic_const_exprs =>
         {
-            tcx.try_unify_abstract_consts(relation.param_env().and((au.shrink(), bu.shrink())))
+            tcx.try_unify_abstract_consts(relation.param_env().and((au, bu)))
         }
 
         // While this is slightly incorrect, it shouldn't matter for `min_const_generics`
@@ -622,6 +622,8 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
         (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
             if au.def == bu.def && au.promoted == bu.promoted =>
         {
+            assert_eq!(au.promoted, ());
+
             let substs = relation.relate_with_variance(
                 ty::Variance::Invariant,
                 ty::VarianceDiagInfo::default(),
@@ -632,7 +634,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
                 kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
                     def: au.def,
                     substs,
-                    promoted: au.promoted,
+                    promoted: (),
                 }),
                 ty: a.ty(),
             }));
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 4968032b416..ff80f732b40 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -565,23 +565,19 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         let value = value.eval(self.tcx, self.param_env);
 
         match value {
-            mir::ConstantKind::Ty(c) => {
-                match c.kind() {
-                    ConstKind::Param(_) => {
-                        self.errors.push(PatternError::ConstParamInPattern(span));
-                        return PatKind::Wild;
-                    }
-                    ConstKind::Unevaluated(_) => {
-                        // If we land here it means the const can't be evaluated because it's `TooGeneric`.
-                        self.tcx
-                            .sess
-                            .span_err(span, "constant pattern depends on a generic parameter");
-                        return PatKind::Wild;
-                    }
-                    _ => bug!("Expected either ConstKind::Param or ConstKind::Unevaluated"),
+            mir::ConstantKind::Ty(c) => match c.kind() {
+                ConstKind::Param(_) => {
+                    self.errors.push(PatternError::ConstParamInPattern(span));
+                    return PatKind::Wild;
                 }
-            }
+                _ => bug!("Expected ConstKind::Param"),
+            },
             mir::ConstantKind::Val(_, _) => self.const_to_pat(value, id, span, false).kind,
+            mir::ConstantKind::Unevaluated(..) => {
+                // If we land here it means the const can't be evaluated because it's `TooGeneric`.
+                self.tcx.sess.span_err(span, "constant pattern depends on a generic parameter");
+                return PatKind::Wild;
+            }
         }
     }
 
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index 082d6c9f07e..cd94af2d3c6 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -22,9 +22,7 @@ use rustc_middle::mir::{
 };
 use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
-use rustc_middle::ty::{
-    self, ConstInt, ConstKind, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitable,
-};
+use rustc_middle::ty::{self, ConstInt, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitable};
 use rustc_session::lint;
 use rustc_span::Span;
 use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout};
@@ -301,18 +299,17 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                 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 {
-                        ConstantKind::Ty(ct) => match ct.kind() {
+                        ConstantKind::Ty(_) => c.literal.needs_subst(),
+                        ConstantKind::Unevaluated(
+                            ty::Unevaluated { def: _, substs: _, promoted: Some(_) },
+                            _,
+                        ) => {
                             // Promoteds must lint and not error as the user didn't ask for them
-                            ConstKind::Unevaluated(ty::Unevaluated {
-                                def: _,
-                                substs: _,
-                                promoted: 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(),
-                        },
-                        ConstantKind::Val(_, ty) => ty.needs_subst(),
+                            true
+                        }
+                        ConstantKind::Unevaluated(_, ty) | ConstantKind::Val(_, ty) => {
+                            ty.needs_subst()
+                        }
                     };
                     if lint_only {
                         // Out of backwards compatibility we cannot report hard errors in unused
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index ba00f16308e..2ad9f582fbe 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -8,7 +8,7 @@ use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
 use rustc_middle::ty::subst::Subst;
-use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
 use rustc_session::config::OptLevel;
 use rustc_span::def_id::DefId;
 use rustc_span::{hygiene::ExpnKind, ExpnData, LocalExpnId, Span};
@@ -606,7 +606,9 @@ impl<'tcx> Inliner<'tcx> {
                 caller_body.required_consts.extend(
                     callee_body.required_consts.iter().copied().filter(|&ct| {
                         match ct.literal.const_for_ty() {
-                            Some(ct) => matches!(ct.kind(), ConstKind::Unevaluated(_)),
+                            Some(_) => {
+                                bug!("should never encounter ty::Unevaluated in required_consts")
+                            }
                             None => true,
                         }
                     }),
diff --git a/compiler/rustc_mir_transform/src/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs
index 827ce0c02ac..022a7a95fa1 100644
--- a/compiler/rustc_mir_transform/src/required_consts.rs
+++ b/compiler/rustc_mir_transform/src/required_consts.rs
@@ -1,5 +1,5 @@
 use rustc_middle::mir::visit::Visitor;
-use rustc_middle::mir::{Constant, Location};
+use rustc_middle::mir::{Constant, ConstantKind, Location};
 use rustc_middle::ty::ConstKind;
 
 pub struct RequiredConstsVisitor<'a, 'tcx> {
@@ -15,8 +15,18 @@ impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> {
 impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> {
     fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) {
         let literal = constant.literal;
-        if let Some(ct) = literal.const_for_ty() && let ConstKind::Unevaluated(_) = ct.kind() {
-            self.required_consts.push(*constant);
+        match literal {
+            ConstantKind::Ty(c) => match c.kind() {
+                ConstKind::Unevaluated(uv) => {
+                    let literal = ConstantKind::Unevaluated(uv.expand(), c.ty());
+                    let new_constant =
+                        Constant { span: constant.span, user_ty: constant.user_ty, literal };
+                    self.required_consts.push(new_constant);
+                }
+                _ => {}
+            },
+            ConstantKind::Unevaluated(..) => self.required_consts.push(*constant),
+            ConstantKind::Val(..) => {}
         }
     }
 }
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index be74a9d11e3..72fb566aff7 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -767,7 +767,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
                 ty::ConstKind::Unevaluated(ct) => {
                     debug!(?ct);
                     let param_env = ty::ParamEnv::reveal_all();
-                    match self.tcx.const_eval_resolve(param_env, ct, None) {
+                    match self.tcx.const_eval_resolve(param_env, ct.expand(), None) {
                         // The `monomorphize` call should have evaluated that constant already.
                         Ok(val) => val,
                         Err(ErrorHandled::Reported(_) | ErrorHandled::Linted) => return,
@@ -780,6 +780,19 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
                 }
                 _ => return,
             },
+            mir::ConstantKind::Unevaluated(uv, _) => {
+                let param_env = ty::ParamEnv::reveal_all();
+                match self.tcx.const_eval_resolve(param_env, uv, None) {
+                    // The `monomorphize` call should have evaluated that constant already.
+                    Ok(val) => val,
+                    Err(ErrorHandled::Reported(_) | ErrorHandled::Linted) => return,
+                    Err(ErrorHandled::TooGeneric) => span_bug!(
+                        self.body.source_info(location).span,
+                        "collection encountered polymorphic constant: {:?}",
+                        literal
+                    ),
+                }
+            }
         };
         collect_const_value(self.tcx, val, self.output);
         self.visit_ty(literal.ty(), TyContext::Location(location));
@@ -798,7 +811,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
                 collect_const_value(self.tcx, const_val, self.output)
             }
             ty::ConstKind::Unevaluated(unevaluated) => {
-                match self.tcx.const_eval_resolve(param_env, unevaluated, None) {
+                match self.tcx.const_eval_resolve(param_env, unevaluated.expand(), None) {
                     // The `monomorphize` call should have evaluated that constant already.
                     Ok(val) => span_bug!(
                         self.body.source_info(location).span,
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index 98156a94ec4..d083a3e00b6 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -9,7 +9,7 @@ use rustc_hir::{def::DefKind, def_id::DefId, ConstContext};
 use rustc_index::bit_set::FiniteBitSet;
 use rustc_middle::mir::{
     visit::{TyContext, Visitor},
-    Local, LocalDecl, Location,
+    ConstantKind, Local, LocalDecl, Location,
 };
 use rustc_middle::ty::{
     self,
@@ -292,7 +292,29 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
                 self.unused_parameters.clear(param.index);
                 ControlFlow::CONTINUE
             }
-            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p)})
+            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
+                if matches!(
+                    self.tcx.def_kind(def.did),
+                    DefKind::AnonConst | DefKind::InlineConst
+                ) =>
+            {
+                assert_eq!(promoted, ());
+
+                self.visit_child_body(def.did, substs);
+                ControlFlow::CONTINUE
+            }
+            _ => c.super_visit_with(self),
+        }
+    }
+
+    fn visit_mir_const(&mut self, constant: ConstantKind<'tcx>) -> ControlFlow<Self::BreakTy> {
+        if !constant.has_param_types_or_consts() {
+            return ControlFlow::CONTINUE;
+        }
+
+        match constant {
+            ConstantKind::Ty(_) => constant.super_visit_with(self),
+            ConstantKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p) }, _)
                 // Avoid considering `T` unused when constants are of the form:
                 //   `<Self as Foo<T>>::foo::promoted[p]`
                 if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self =>
@@ -303,13 +325,9 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
                 self.visit_body(&promoted[p]);
                 ControlFlow::CONTINUE
             }
-            ty::ConstKind::Unevaluated(uv)
-                if matches!(self.tcx.def_kind(uv.def.did), DefKind::AnonConst | DefKind::InlineConst) =>
-            {
-                self.visit_child_body(uv.def.did, uv.substs);
-                ControlFlow::CONTINUE
+            ConstantKind::Val(..) | ConstantKind::Unevaluated(..) => {
+                constant.super_visit_with(self)
             }
-            _ => c.super_visit_with(self),
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 254bc4ab663..5a213987e87 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -183,7 +183,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
                 FailureKind::Concrete => {}
             }
         }
-        let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span));
+        let concrete = infcx.const_eval_resolve(param_env, uv, Some(span));
         match concrete {
             Err(ErrorHandled::TooGeneric) => {
                 Err(NotConstEvaluatable::Error(infcx.tcx.sess.delay_span_bug(
@@ -210,7 +210,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
         // and hopefully soon change this to an error.
         //
         // See #74595 for more details about this.
-        let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span));
+        let concrete = infcx.const_eval_resolve(param_env, uv, Some(span));
 
         match concrete {
           // If we're evaluating a foreign constant, under a nightly compiler without generic
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 3763a98c488..6bb6aef1d05 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -509,11 +509,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
                         if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
                             (c1.kind(), c2.kind())
                         {
-                            if infcx.try_unify_abstract_consts(
-                                a.shrink(),
-                                b.shrink(),
-                                obligation.param_env,
-                            ) {
+                            if infcx.try_unify_abstract_consts(a, b, obligation.param_env) {
                                 return ProcessResult::Changed(vec![]);
                             }
                         }
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index f65fc5bad0d..17afd325f03 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -366,7 +366,9 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
                     _ => mir::ConstantKind::Ty(const_folded),
                 }
             }
-            mir::ConstantKind::Val(_, _) => constant.try_super_fold_with(self)?,
+            mir::ConstantKind::Val(_, _) | mir::ConstantKind::Unevaluated(..) => {
+                constant.try_super_fold_with(self)?
+            }
         })
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 8b15e10ba9c..c8896027ba1 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -699,11 +699,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
                             (c1.kind(), c2.kind())
                         {
-                            if self.infcx.try_unify_abstract_consts(
-                                a.shrink(),
-                                b.shrink(),
-                                obligation.param_env,
-                            ) {
+                            if self.infcx.try_unify_abstract_consts(a, b, obligation.param_env) {
                                 return Ok(EvaluatedToOk);
                             }
                         }
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 9d3a1a4a031..ff6b5c73386 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -456,7 +456,7 @@ impl<'tcx> WfPredicates<'tcx> {
                             self.out.extend(obligations);
 
                             let predicate =
-                                ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv.shrink()))
+                                ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))
                                     .to_predicate(self.tcx());
                             let cause = self.cause(traits::WellFormed(None));
                             self.out.push(traits::Obligation::with_depth(
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 3e7a6c3c548..cbc4eab85fd 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -2372,10 +2372,10 @@ fn const_evaluatable_predicates_of<'tcx>(
             let def_id = self.tcx.hir().local_def_id(c.hir_id);
             let ct = ty::Const::from_anon_const(self.tcx, def_id);
             if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
-                assert_eq!(uv.promoted, None);
+                assert_eq!(uv.promoted, ());
                 let span = self.tcx.hir().span(c.hir_id);
                 self.preds.insert((
-                    ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv.shrink()))
+                    ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))
                         .to_predicate(self.tcx),
                     span,
                 ));
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 395f213ca87..070956deca3 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -235,14 +235,13 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
 pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
     match n.kind() {
         ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) => {
+            assert_eq!(promoted, ());
             let mut s = if let Some(def) = def.as_local() {
                 print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def.did))
             } else {
                 inline::print_inlined_const(cx.tcx, def.did)
             };
-            if let Some(promoted) = promoted {
-                s.push_str(&format!("::{:?}", promoted))
-            }
+
             s
         }
         _ => {