about summary refs log tree commit diff
path: root/compiler/rustc_middle/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle/src')
-rw-r--r--compiler/rustc_middle/src/infer/unify_key.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs10
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs37
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs3
-rw-r--r--compiler/rustc_middle/src/mir/type_foldable.rs20
-rw-r--r--compiler/rustc_middle/src/mir/type_visitable.rs13
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/abstract_const.rs2
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs3
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs39
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs9
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs4
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs40
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs4
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs29
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs12
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs30
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs41
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs30
19 files changed, 207 insertions, 123 deletions
diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs
index f2627885d03..41d8c7ffdb9 100644
--- a/compiler/rustc_middle/src/infer/unify_key.rs
+++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -129,7 +129,7 @@ impl<'tcx> UnifyKey for ty::ConstVid<'tcx> {
 }
 
 impl<'tcx> UnifyValue for ConstVarValue<'tcx> {
-    type Error = (ty::Const<'tcx>, ty::Const<'tcx>);
+    type Error = NoError;
 
     fn unify_values(&value1: &Self, &value2: &Self) -> Result<Self, Self::Error> {
         Ok(match (value1.val, value2.val) {
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index a8c7505329c..734c31192c7 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -36,7 +36,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn const_eval_resolve(
         self,
         param_env: ty::ParamEnv<'tcx>,
-        ct: ty::Unevaluated<'tcx>,
+        ct: mir::UnevaluatedConst<'tcx>,
         span: Option<Span>,
     ) -> EvalToConstValueResult<'tcx> {
         // Cannot resolve `Unevaluated` constants that contain inference
@@ -49,7 +49,11 @@ impl<'tcx> TyCtxt<'tcx> {
             bug!("did not expect inference variables here");
         }
 
-        match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
+        match ty::Instance::resolve_opt_const_arg(
+            self, param_env,
+            // FIXME: maybe have a seperate version for resolving mir::UnevaluatedConst?
+            ct.def, ct.substs,
+        ) {
             Ok(Some(instance)) => {
                 let cid = GlobalId { instance, promoted: ct.promoted };
                 self.const_eval_global_id(param_env, cid, span)
@@ -63,7 +67,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn const_eval_resolve_for_typeck(
         self,
         param_env: ty::ParamEnv<'tcx>,
-        ct: ty::Unevaluated<'tcx, ()>,
+        ct: ty::UnevaluatedConst<'tcx>,
         span: Option<Span>,
     ) -> EvalToValTreeResult<'tcx> {
         // Cannot resolve `Unevaluated` constants that contain inference
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 86ffce8ceb4..78a16788815 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -2055,7 +2055,7 @@ pub enum ConstantKind<'tcx> {
     Ty(ty::Const<'tcx>),
 
     /// An unevaluated mir constant which is not part of the type system.
-    Unevaluated(ty::Unevaluated<'tcx, Option<Promoted>>, Ty<'tcx>),
+    Unevaluated(UnevaluatedConst<'tcx>, Ty<'tcx>),
 
     /// This constant cannot go back into the type system, as it represents
     /// something the type system cannot handle (e.g. pointers).
@@ -2315,12 +2315,11 @@ impl<'tcx> ConstantKind<'tcx> {
             ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
                 .substs;
 
-        let uneval = ty::Unevaluated {
+        let uneval = UnevaluatedConst {
             def: ty::WithOptConstParam::unknown(def_id).to_global(),
             substs,
             promoted: None,
         };
-
         debug_assert!(!uneval.has_free_regions());
 
         Self::Unevaluated(uneval, ty)
@@ -2404,7 +2403,7 @@ impl<'tcx> ConstantKind<'tcx> {
 
         let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
         let span = tcx.hir().span(hir_id);
-        let uneval = ty::Unevaluated::new(def.to_global(), substs);
+        let uneval = UnevaluatedConst::new(def.to_global(), substs);
         debug!(?span, ?param_env);
 
         match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
@@ -2417,7 +2416,7 @@ impl<'tcx> ConstantKind<'tcx> {
                 // Error was handled in `const_eval_resolve`. Here we just create a
                 // new unevaluated const and error hard later in codegen
                 Self::Unevaluated(
-                    ty::Unevaluated {
+                    UnevaluatedConst {
                         def: def.to_global(),
                         substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
                         promoted: None,
@@ -2440,6 +2439,34 @@ impl<'tcx> ConstantKind<'tcx> {
     }
 }
 
+/// An unevaluated (potentially generic) constant used in MIR.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
+#[derive(Hash, HashStable)]
+pub struct UnevaluatedConst<'tcx> {
+    pub def: ty::WithOptConstParam<DefId>,
+    pub substs: SubstsRef<'tcx>,
+    pub promoted: Option<Promoted>,
+}
+
+impl<'tcx> UnevaluatedConst<'tcx> {
+    // FIXME: probably should get rid of this method. It's also wrong to
+    // shrink and then later expand a promoted.
+    #[inline]
+    pub fn shrink(self) -> ty::UnevaluatedConst<'tcx> {
+        ty::UnevaluatedConst { def: self.def, substs: self.substs }
+    }
+}
+
+impl<'tcx> UnevaluatedConst<'tcx> {
+    #[inline]
+    pub fn new(
+        def: ty::WithOptConstParam<DefId>,
+        substs: SubstsRef<'tcx>,
+    ) -> UnevaluatedConst<'tcx> {
+        UnevaluatedConst { def, substs, promoted: Default::default() }
+    }
+}
+
 /// A collection of projections into user types.
 ///
 /// They are projections because a binding can occur a part of a
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 0b42137d4e3..05dcfba77b2 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -466,10 +466,9 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
                     ty::ConstKind::Param(p) => format!("Param({})", p),
                     ty::ConstKind::Unevaluated(uv) => {
                         format!(
-                            "Unevaluated({}, {:?}, {:?})",
+                            "Unevaluated({}, {:?})",
                             self.tcx.def_path_str(uv.def.did),
                             uv.substs,
-                            uv.promoted,
                         )
                     }
                     ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)),
diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs
index 9d098c8083e..8e18cad442e 100644
--- a/compiler/rustc_middle/src/mir/type_foldable.rs
+++ b/compiler/rustc_middle/src/mir/type_foldable.rs
@@ -3,6 +3,7 @@
 use rustc_ast::InlineAsmTemplatePiece;
 
 use super::*;
+use crate::mir;
 use crate::ty;
 
 TrivialTypeTraversalAndLiftImpls! {
@@ -50,6 +51,25 @@ impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
     }
 }
 
+impl<'tcx> TypeFoldable<'tcx> for mir::UnevaluatedConst<'tcx> {
+    fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        folder.try_fold_mir_unevaluated(self)
+    }
+}
+
+impl<'tcx> TypeSuperFoldable<'tcx> for mir::UnevaluatedConst<'tcx> {
+    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(mir::UnevaluatedConst {
+            def: self.def,
+            substs: self.substs.try_fold_with(folder)?,
+            promoted: self.promoted,
+        })
+    }
+}
+
 impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
     #[inline(always)]
     fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
diff --git a/compiler/rustc_middle/src/mir/type_visitable.rs b/compiler/rustc_middle/src/mir/type_visitable.rs
index be19bb486d4..a136ca4d8c3 100644
--- a/compiler/rustc_middle/src/mir/type_visitable.rs
+++ b/compiler/rustc_middle/src/mir/type_visitable.rs
@@ -1,6 +1,7 @@
 //! `TypeVisitable` implementations for MIR types
 
 use super::*;
+use crate::mir;
 
 impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix<R, C> {
     fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
@@ -8,6 +9,18 @@ impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix<R, C> {
     }
 }
 
+impl<'tcx> TypeVisitable<'tcx> for mir::UnevaluatedConst<'tcx> {
+    fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        visitor.visit_mir_unevaluated(*self)
+    }
+}
+
+impl<'tcx> TypeSuperVisitable<'tcx> for mir::UnevaluatedConst<'tcx> {
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        self.substs.visit_with(visitor)
+    }
+}
+
 impl<'tcx> TypeVisitable<'tcx> for ConstantKind<'tcx> {
     fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
         visitor.visit_mir_const(*self)
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 7ea8c9ed3d3..121a5b9f492 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -377,7 +377,7 @@ rustc_queries! {
     }
 
     query try_unify_abstract_consts(key:
-        ty::ParamEnvAnd<'tcx, (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>
+        ty::ParamEnvAnd<'tcx, (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>
     )>) -> bool {
         desc {
             |tcx| "trying to unify the generic constants {} and {}",
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index 8e0a1f1f9ac..641e53f2a15 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -30,7 +30,7 @@ pub struct AbstractConst<'tcx> {
 impl<'tcx> AbstractConst<'tcx> {
     pub fn new(
         tcx: TyCtxt<'tcx>,
-        uv: ty::Unevaluated<'tcx, ()>,
+        uv: ty::UnevaluatedConst<'tcx>,
     ) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> {
         let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?;
         debug!("AbstractConst::new({:?}) = {:?}", uv, inner);
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 4bc821dcfa1..315e3794f15 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -78,10 +78,9 @@ impl<'tcx> Const<'tcx> {
         match Self::try_eval_lit_or_param(tcx, ty, expr) {
             Some(v) => v,
             None => tcx.mk_const(ty::ConstS {
-                kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
+                kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst {
                     def: def.to_global(),
                     substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
-                    promoted: (),
                 }),
                 ty,
             }),
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 4550152804e..c444ec23563 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -1,7 +1,7 @@
 use std::convert::TryInto;
 
+use crate::mir;
 use crate::mir::interpret::{AllocId, ConstValue, Scalar};
-use crate::mir::Promoted;
 use crate::ty::subst::{InternalSubsts, SubstsRef};
 use crate::ty::ParamEnv;
 use crate::ty::{self, TyCtxt, TypeVisitable};
@@ -12,40 +12,34 @@ use rustc_target::abi::Size;
 
 use super::ScalarInt;
 
-/// An unevaluated, potentially generic, constant.
+/// An unevaluated (potentially generic) constant used in the type-system.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
 #[derive(Hash, HashStable)]
-pub struct Unevaluated<'tcx, P = Option<Promoted>> {
+pub struct UnevaluatedConst<'tcx> {
     pub def: ty::WithOptConstParam<DefId>,
     pub substs: SubstsRef<'tcx>,
-    pub promoted: P,
 }
 
-impl rustc_errors::IntoDiagnosticArg for Unevaluated<'_> {
+impl rustc_errors::IntoDiagnosticArg for UnevaluatedConst<'_> {
     fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
         format!("{:?}", self).into_diagnostic_arg()
     }
 }
 
-impl<'tcx> Unevaluated<'tcx> {
+impl<'tcx> UnevaluatedConst<'tcx> {
     #[inline]
-    pub fn shrink(self) -> Unevaluated<'tcx, ()> {
-        debug_assert_eq!(self.promoted, None);
-        Unevaluated { def: self.def, substs: self.substs, promoted: () }
+    pub fn expand(self) -> mir::UnevaluatedConst<'tcx> {
+        mir::UnevaluatedConst { def: self.def, substs: self.substs, promoted: None }
     }
 }
 
-impl<'tcx> Unevaluated<'tcx, ()> {
+impl<'tcx> UnevaluatedConst<'tcx> {
     #[inline]
-    pub fn expand(self) -> Unevaluated<'tcx> {
-        Unevaluated { def: self.def, substs: self.substs, promoted: None }
-    }
-}
-
-impl<'tcx, P: Default> Unevaluated<'tcx, P> {
-    #[inline]
-    pub fn new(def: ty::WithOptConstParam<DefId>, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx, P> {
-        Unevaluated { def, substs, promoted: Default::default() }
+    pub fn new(
+        def: ty::WithOptConstParam<DefId>,
+        substs: SubstsRef<'tcx>,
+    ) -> UnevaluatedConst<'tcx> {
+        UnevaluatedConst { def, substs }
     }
 }
 
@@ -67,7 +61,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(UnevaluatedConst<'tcx>),
 
     /// Used to hold computed value.
     Value(ty::ValTree<'tcx>),
@@ -185,8 +179,6 @@ 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,10 +196,9 @@ impl<'tcx> ConstKind<'tcx> {
             // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
             // we can call `infcx.const_eval_resolve` which handles inference variables.
             let param_env_and = if param_env_and.needs_infer() {
-                tcx.param_env(unevaluated.def.did).and(ty::Unevaluated {
+                tcx.param_env(unevaluated.def.did).and(ty::UnevaluatedConst {
                     def: unevaluated.def,
                     substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did),
-                    promoted: (),
                 })
             } else {
                 param_env_and
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 8d019a3bad8..41bb3c71401 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -384,14 +384,7 @@ impl DeepRejectCtxt {
             // they might unify with any value.
             ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => true,
             ty::ConstKind::Value(obl) => match k {
-                ty::ConstKind::Value(imp) => {
-                    // FIXME(valtrees): Once we have valtrees, we can just
-                    // compare them directly here.
-                    match (obl.try_to_scalar_int(), imp.try_to_scalar_int()) {
-                        (Some(obl), Some(imp)) => obl == imp,
-                        _ => true,
-                    }
-                }
+                ty::ConstKind::Value(imp) => obl == imp,
                 _ => true,
             },
 
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 98b8a7386fe..a6d0678e99d 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -34,7 +34,7 @@ impl FlagComputation {
         result.flags
     }
 
-    pub fn for_unevaluated_const(uv: ty::Unevaluated<'_>) -> TypeFlags {
+    pub fn for_unevaluated_const(uv: ty::UnevaluatedConst<'_>) -> TypeFlags {
         let mut result = FlagComputation::new();
         result.add_unevaluated_const(uv);
         result.flags
@@ -313,7 +313,7 @@ impl FlagComputation {
         }
     }
 
-    fn add_unevaluated_const<P>(&mut self, ct: ty::Unevaluated<'_, P>) {
+    fn add_unevaluated_const(&mut self, ct: ty::UnevaluatedConst<'_>) {
         self.add_substs(ct.substs);
         self.add_flags(TypeFlags::HAS_CT_PROJECTION);
     }
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index cac95e14a23..e4234442fae 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -128,7 +128,17 @@ pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> {
         c.super_fold_with(self)
     }
 
-    fn fold_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ty::Unevaluated<'tcx> {
+    fn fold_ty_unevaluated(
+        &mut self,
+        uv: ty::UnevaluatedConst<'tcx>,
+    ) -> ty::UnevaluatedConst<'tcx> {
+        uv.super_fold_with(self)
+    }
+
+    fn fold_mir_unevaluated(
+        &mut self,
+        uv: mir::UnevaluatedConst<'tcx>,
+    ) -> mir::UnevaluatedConst<'tcx> {
         uv.super_fold_with(self)
     }
 
@@ -172,10 +182,17 @@ pub trait FallibleTypeFolder<'tcx>: Sized {
         c.try_super_fold_with(self)
     }
 
-    fn try_fold_unevaluated(
+    fn try_fold_ty_unevaluated(
+        &mut self,
+        c: ty::UnevaluatedConst<'tcx>,
+    ) -> Result<ty::UnevaluatedConst<'tcx>, Self::Error> {
+        c.try_super_fold_with(self)
+    }
+
+    fn try_fold_mir_unevaluated(
         &mut self,
-        c: ty::Unevaluated<'tcx>,
-    ) -> Result<ty::Unevaluated<'tcx>, Self::Error> {
+        c: mir::UnevaluatedConst<'tcx>,
+    ) -> Result<mir::UnevaluatedConst<'tcx>, Self::Error> {
         c.try_super_fold_with(self)
     }
 
@@ -225,11 +242,18 @@ where
         Ok(self.fold_const(c))
     }
 
-    fn try_fold_unevaluated(
+    fn try_fold_ty_unevaluated(
+        &mut self,
+        c: ty::UnevaluatedConst<'tcx>,
+    ) -> Result<ty::UnevaluatedConst<'tcx>, !> {
+        Ok(self.fold_ty_unevaluated(c))
+    }
+
+    fn try_fold_mir_unevaluated(
         &mut self,
-        c: ty::Unevaluated<'tcx>,
-    ) -> Result<ty::Unevaluated<'tcx>, !> {
-        Ok(self.fold_unevaluated(c))
+        c: mir::UnevaluatedConst<'tcx>,
+    ) -> Result<mir::UnevaluatedConst<'tcx>, !> {
+        Ok(self.fold_mir_unevaluated(c))
     }
 
     fn try_fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> Result<ty::Predicate<'tcx>, !> {
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 982aacc7686..63dd213a085 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -73,7 +73,7 @@ pub use self::closure::{
     CAPTURE_STRUCT_LOCAL,
 };
 pub use self::consts::{
-    Const, ConstInt, ConstKind, ConstS, InferConst, ScalarInt, Unevaluated, ValTree,
+    Const, ConstInt, ConstKind, ConstS, InferConst, ScalarInt, UnevaluatedConst, ValTree,
 };
 pub use self::context::{
     tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
@@ -682,7 +682,7 @@ pub enum PredicateKind<'tcx> {
     Coerce(CoercePredicate<'tcx>),
 
     /// Constant initializer must evaluate successfully.
-    ConstEvaluatable(ty::Unevaluated<'tcx, ()>),
+    ConstEvaluatable(ty::UnevaluatedConst<'tcx>),
 
     /// Constants must be equal. The first component is the const that is expected.
     ConstEquate(Const<'tcx>, Const<'tcx>),
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index b6cd5396b1d..99e5722ddad 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1088,17 +1088,9 @@ pub trait PrettyPrinter<'tcx>:
                         .generics_of(principal.def_id)
                         .own_substs_no_defaults(cx.tcx(), principal.substs);
 
-                    // Don't print `'_` if there's no unerased regions.
-                    let print_regions = args.iter().any(|arg| match arg.unpack() {
-                        GenericArgKind::Lifetime(r) => !r.is_erased(),
-                        _ => false,
-                    });
-                    let mut args = args.iter().cloned().filter(|arg| match arg.unpack() {
-                        GenericArgKind::Lifetime(_) => print_regions,
-                        _ => true,
-                    });
                     let mut projections = predicates.projection_bounds();
 
+                    let mut args = args.iter().cloned();
                     let arg0 = args.next();
                     let projection0 = projections.next();
                     if arg0.is_some() || projection0.is_some() {
@@ -1201,9 +1193,7 @@ pub trait PrettyPrinter<'tcx>:
         }
 
         match ct.kind() {
-            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
-                assert_eq!(promoted, ());
-
+            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
                 match self.tcx().def_kind(def.did) {
                     DefKind::Static(..) | DefKind::Const | DefKind::AssocConst => {
                         p!(print_value_path(def.did, substs))
@@ -1847,22 +1837,11 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
     ) -> Result<Self::Path, Self::Error> {
         self = print_prefix(self)?;
 
-        // Don't print `'_` if there's no unerased regions.
-        let print_regions = self.tcx.sess.verbose()
-            || args.iter().any(|arg| match arg.unpack() {
-                GenericArgKind::Lifetime(r) => !r.is_erased(),
-                _ => false,
-            });
-        let args = args.iter().cloned().filter(|arg| match arg.unpack() {
-            GenericArgKind::Lifetime(_) => print_regions,
-            _ => true,
-        });
-
-        if args.clone().next().is_some() {
+        if args.first().is_some() {
             if self.in_value {
                 write!(self, "::")?;
             }
-            self.generic_delimiters(|cx| cx.comma_sep(args))
+            self.generic_delimiters(|cx| cx.comma_sep(args.iter().cloned()))
         } else {
             Ok(self)
         }
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 0d97d4acdfc..cdb618e030a 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -621,11 +621,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
         // While this is slightly incorrect, it shouldn't matter for `min_const_generics`
         // and is the better alternative to waiting until `generic_const_exprs` can
         // be stabilized.
-        (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
-            if au.def == bu.def && au.promoted == bu.promoted =>
-        {
-            assert_eq!(au.promoted, ());
-
+        (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => {
             let substs = relation.relate_with_variance(
                 ty::Variance::Invariant,
                 ty::VarianceDiagInfo::default(),
@@ -633,11 +629,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
                 bu.substs,
             )?;
             return Ok(tcx.mk_const(ty::ConstS {
-                kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
-                    def: au.def,
-                    substs,
-                    promoted: (),
-                }),
+                kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def: au.def, substs }),
                 ty: a.ty(),
             }));
         }
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 004fcffdc40..3b42f4b51fc 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -829,45 +829,29 @@ impl<'tcx> TypeVisitable<'tcx> for InferConst<'tcx> {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> {
+impl<'tcx> TypeFoldable<'tcx> for ty::UnevaluatedConst<'tcx> {
     fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        folder.try_fold_unevaluated(self)
+        folder.try_fold_ty_unevaluated(self)
     }
 }
 
-impl<'tcx> TypeVisitable<'tcx> for ty::Unevaluated<'tcx> {
+impl<'tcx> TypeVisitable<'tcx> for ty::UnevaluatedConst<'tcx> {
     fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        visitor.visit_unevaluated(*self)
+        visitor.visit_ty_unevaluated(*self)
     }
 }
 
-impl<'tcx> TypeSuperFoldable<'tcx> for ty::Unevaluated<'tcx> {
+impl<'tcx> TypeSuperFoldable<'tcx> for ty::UnevaluatedConst<'tcx> {
     fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
         self,
         folder: &mut F,
     ) -> Result<Self, F::Error> {
-        Ok(ty::Unevaluated {
-            def: self.def,
-            substs: self.substs.try_fold_with(folder)?,
-            promoted: self.promoted,
-        })
+        Ok(ty::UnevaluatedConst { def: self.def, substs: self.substs.try_fold_with(folder)? })
     }
 }
 
-impl<'tcx> TypeSuperVisitable<'tcx> for ty::Unevaluated<'tcx> {
+impl<'tcx> TypeSuperVisitable<'tcx> for ty::UnevaluatedConst<'tcx> {
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
         self.substs.visit_with(visitor)
     }
 }
-
-impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> {
-    fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        Ok(self.expand().try_fold_with(folder)?.shrink())
-    }
-}
-
-impl<'tcx> TypeVisitable<'tcx> for ty::Unevaluated<'tcx, ()> {
-    fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.expand().visit_with(visitor)
-    }
-}
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index d2f73f274f8..258fb2e2f9f 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -19,7 +19,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_index::vec::Idx;
 use rustc_macros::HashStable;
-use rustc_span::symbol::{kw, Symbol};
+use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_target::abi::VariantIdx;
 use rustc_target::spec::abi;
 use std::borrow::Cow;
@@ -1133,9 +1133,13 @@ pub struct ProjectionTy<'tcx> {
 
 impl<'tcx> ProjectionTy<'tcx> {
     pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
-        let parent = tcx.parent(self.item_def_id);
-        assert_eq!(tcx.def_kind(parent), DefKind::Trait);
-        parent
+        match tcx.def_kind(self.item_def_id) {
+            DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.item_def_id),
+            DefKind::ImplTraitPlaceholder => {
+                tcx.parent(tcx.impl_trait_in_trait_parent(self.item_def_id))
+            }
+            kind => bug!("unexpected DefKind in ProjectionTy: {kind:?}"),
+        }
     }
 
     /// Extracts the underlying trait reference and own substs from this projection.
@@ -2207,6 +2211,35 @@ impl<'tcx> Ty<'tcx> {
             }
         }
     }
+
+    // If `self` is a primitive, return its [`Symbol`].
+    pub fn primitive_symbol(self) -> Option<Symbol> {
+        match self.kind() {
+            ty::Bool => Some(sym::bool),
+            ty::Char => Some(sym::char),
+            ty::Float(f) => match f {
+                ty::FloatTy::F32 => Some(sym::f32),
+                ty::FloatTy::F64 => Some(sym::f64),
+            },
+            ty::Int(f) => match f {
+                ty::IntTy::Isize => Some(sym::isize),
+                ty::IntTy::I8 => Some(sym::i8),
+                ty::IntTy::I16 => Some(sym::i16),
+                ty::IntTy::I32 => Some(sym::i32),
+                ty::IntTy::I64 => Some(sym::i64),
+                ty::IntTy::I128 => Some(sym::i128),
+            },
+            ty::Uint(f) => match f {
+                ty::UintTy::Usize => Some(sym::usize),
+                ty::UintTy::U8 => Some(sym::u8),
+                ty::UintTy::U16 => Some(sym::u16),
+                ty::UintTy::U32 => Some(sym::u32),
+                ty::UintTy::U64 => Some(sym::u64),
+                ty::UintTy::U128 => Some(sym::u128),
+            },
+            _ => None,
+        }
+    }
 }
 
 /// Extra information about why we ended up with a particular variance.
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 5f8cb578202..9c3b6a794e1 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -199,7 +199,17 @@ pub trait TypeVisitor<'tcx>: Sized {
         c.super_visit_with(self)
     }
 
-    fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty_unevaluated(
+        &mut self,
+        uv: ty::UnevaluatedConst<'tcx>,
+    ) -> ControlFlow<Self::BreakTy> {
+        uv.super_visit_with(self)
+    }
+
+    fn visit_mir_unevaluated(
+        &mut self,
+        uv: mir::UnevaluatedConst<'tcx>,
+    ) -> ControlFlow<Self::BreakTy> {
         uv.super_visit_with(self)
     }
 
@@ -597,7 +607,10 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
 
     #[inline]
     #[instrument(level = "trace", ret)]
-    fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty_unevaluated(
+        &mut self,
+        uv: ty::UnevaluatedConst<'tcx>,
+    ) -> ControlFlow<Self::BreakTy> {
         let flags = FlagComputation::for_unevaluated_const(uv);
         trace!(r.flags=?flags);
         if flags.intersects(self.flags) {
@@ -607,6 +620,19 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
         }
     }
 
+    fn visit_mir_unevaluated(
+        &mut self,
+        uv: mir::UnevaluatedConst<'tcx>,
+    ) -> ControlFlow<Self::BreakTy> {
+        let flags = FlagComputation::for_unevaluated_const(uv.shrink());
+        trace!(r.flags=?flags);
+        if flags.intersects(self.flags) {
+            ControlFlow::Break(FoundFlags)
+        } else {
+            ControlFlow::CONTINUE
+        }
+    }
+
     #[inline]
     #[instrument(level = "trace", ret)]
     fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {