about summary refs log tree commit diff
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2021-07-17 18:48:07 +0200
committerlcnr <rust@lcnr.de>2021-08-26 11:00:30 +0200
commitab9108b70f25ecd9cce1ab756b82cb00de6c6927 (patch)
treee170e754ffe5d4fdad51e85fdb043a9cc98e1dc8
parentcc47998e2877f13712a12b3814cc2bbf07fbae09 (diff)
downloadrust-ab9108b70f25ecd9cce1ab756b82cb00de6c6927.tar.gz
rust-ab9108b70f25ecd9cce1ab756b82cb00de6c6927.zip
update `TypeFlags` to deal with missing ct substs
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs2
-rw-r--r--compiler/rustc_infer/src/infer/freshen.rs2
-rw-r--r--compiler/rustc_lint/src/builtin.rs2
-rw-r--r--compiler/rustc_lint/src/noop_method_call.rs2
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs10
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs6
-rw-r--r--compiler/rustc_middle/src/ty/erase_regions.rs4
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs18
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs103
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs6
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs4
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs4
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs20
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs6
-rw-r--r--compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs2
-rw-r--r--compiler/rustc_mir/src/interpret/util.rs24
-rw-r--r--compiler/rustc_mir/src/monomorphize/polymorphize.rs8
-rw-r--r--compiler/rustc_mir/src/shim.rs24
-rw-r--r--compiler/rustc_mir/src/transform/const_prop.rs11
-rw-r--r--compiler/rustc_mir/src/transform/inline/cycle.rs2
-rw-r--r--compiler/rustc_mir/src/transform/mod.rs6
-rw-r--r--compiler/rustc_mir/src/transform/promote_consts.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs10
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs3
-rw-r--r--compiler/rustc_trait_selection/src/opaque_types.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs12
-rw-r--r--compiler/rustc_type_ir/src/lib.rs112
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs2
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs8
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs12
-rw-r--r--compiler/rustc_typeck/src/check/writeback.rs2
-rw-r--r--compiler/rustc_typeck/src/collect/type_of.rs11
-rw-r--r--compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs2
44 files changed, 305 insertions, 166 deletions
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 8375d4c7ca5..2e8a9604017 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -499,7 +499,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                         ty::Adt(def, ..) if !def.is_box() => {
                             // Again, only create type information if full debuginfo is enabled
                             if cx.sess().opts.debuginfo == DebugInfo::Full
-                                && !impl_self_ty.needs_subst()
+                                && !impl_self_ty.needs_subst(cx.tcx)
                             {
                                 Some(type_metadata(cx, impl_self_ty, rustc_span::DUMMY_SP))
                             } else {
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 58ce31e0c4c..673d348a2a8 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1398,7 +1398,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"),
                 LocalRef::Operand(None) => {
                     let dst_layout = bx.layout_of(self.monomorphized_place_ty(dst.as_ref()));
-                    assert!(!dst_layout.ty.has_erasable_regions());
+                    assert!(!dst_layout.ty.has_erasable_regions(self.cx.tcx()));
                     let place = PlaceRef::alloca(bx, dst_layout);
                     place.storage_live(bx);
                     self.codegen_transmute_into(bx, src, place);
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 3bbc481b610..e2edd448267 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -216,7 +216,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         let mut allocate_local = |local| {
             let decl = &mir.local_decls[local];
             let layout = bx.layout_of(fx.monomorphize(decl.ty));
-            assert!(!layout.ty.has_erasable_regions());
+            assert!(!layout.ty.has_erasable_regions(cx.tcx()));
 
             if local == mir::RETURN_PLACE && fx.fn_abi.ret.is_indirect() {
                 debug!("alloc: {:?} (return place) -> place", local);
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 448dd662348..c6e150d114c 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -470,7 +470,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
     {
         let needs_canonical_flags = if canonicalize_region_mode.any() {
             TypeFlags::NEEDS_INFER |
-            TypeFlags::HAS_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_FREE_REGIONS`
+            TypeFlags::HAS_POTENTIAL_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_xxx_FREE_REGIONS`
             TypeFlags::HAS_TY_PLACEHOLDER |
             TypeFlags::HAS_CT_PLACEHOLDER
         } else {
diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs
index 4af1bdf97a7..c40e409891b 100644
--- a/compiler/rustc_infer/src/infer/freshen.rs
+++ b/compiler/rustc_infer/src/infer/freshen.rs
@@ -146,7 +146,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if !t.needs_infer() && !t.has_erasable_regions() {
+        if !t.needs_infer() && !t.has_erasable_regions(self.tcx()) {
             return t;
         }
 
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index b4f11a8a044..8f848f54aad 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1656,7 +1656,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
                     ConstEquate(..) |
                     TypeWellFormedFromEnv(..) => continue,
                 };
-                if predicate.is_global() {
+                if predicate.is_global(cx.tcx) {
                     cx.struct_span_lint(TRIVIAL_BOUNDS, span, |lint| {
                         lint.build(&format!(
                             "{} bound {} does not depend on any type \
diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs
index 479cc00199f..908d847915f 100644
--- a/compiler/rustc_lint/src/noop_method_call.rs
+++ b/compiler/rustc_lint/src/noop_method_call.rs
@@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
             _ => return,
         };
         let substs = cx.typeck_results().node_substs(expr.hir_id);
-        if substs.needs_subst() {
+        if substs.needs_subst(cx.tcx) {
             // We can't resolve on types that require monomorphization, so we don't handle them if
             // we need to perfom substitution.
             return;
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 00c2f0a0299..6a7758bedfb 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -242,6 +242,7 @@ pub struct Body<'tcx> {
 
 impl<'tcx> Body<'tcx> {
     pub fn new(
+        tcx: TyCtxt<'tcx>,
         source: MirSource<'tcx>,
         basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
         source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
@@ -284,7 +285,7 @@ impl<'tcx> Body<'tcx> {
             predecessor_cache: PredecessorCache::new(),
             is_cyclic: GraphIsCyclicCache::new(),
         };
-        body.is_polymorphic = body.has_param_types_or_consts();
+        body.is_polymorphic = body.has_param_types_or_consts(tcx);
         body
     }
 
@@ -293,7 +294,10 @@ impl<'tcx> Body<'tcx> {
     /// The returned MIR contains no `LocalDecl`s (even for the return place) or source scopes. It
     /// is only useful for testing but cannot be `#[cfg(test)]` because it is used in a different
     /// crate.
-    pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
+    pub fn new_cfg_only(
+        tcx: TyCtxt<'tcx>,
+        basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
+    ) -> Self {
         let mut body = Body {
             phase: MirPhase::Build,
             source: MirSource::item(DefId::local(CRATE_DEF_INDEX)),
@@ -311,7 +315,7 @@ impl<'tcx> Body<'tcx> {
             predecessor_cache: PredecessorCache::new(),
             is_cyclic: GraphIsCyclicCache::new(),
         };
-        body.is_polymorphic = body.has_param_types_or_consts();
+        body.is_polymorphic = body.has_param_types_or_consts(tcx);
         body
     }
 
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index ab2c57ac605..174c35dbc71 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -12,6 +12,12 @@ use rustc_target::abi::Size;
 
 use super::ScalarInt;
 /// An unevaluated, potentially generic, constant.
+///
+/// If `substs_` is `None` it means that this anon const
+/// still has its default substs.
+///
+/// We check for all possible substs in `fn default_anon_const_substs`,
+/// so refer to that check for more info.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
 #[derive(Hash, HashStable)]
 pub struct Unevaluated<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
index 759d1a017aa..63eb55ed1a6 100644
--- a/compiler/rustc_middle/src/ty/erase_regions.rs
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -21,7 +21,9 @@ impl<'tcx> TyCtxt<'tcx> {
         T: TypeFoldable<'tcx>,
     {
         // If there's nothing to erase avoid performing the query at all
-        if !value.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) {
+        if !value
+            .has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_POTENTIAL_FREE_REGIONS)
+        {
             return value;
         }
         debug!("erase_regions({:?})", value);
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 89cba4aab83..41c2447cfc5 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -34,6 +34,12 @@ impl FlagComputation {
         result.flags
     }
 
+    pub fn for_unevaluated_const(uv: ty::Unevaluated<'_>) -> TypeFlags {
+        let mut result = FlagComputation::new();
+        result.add_unevaluated_const(uv);
+        result.flags
+    }
+
     fn add_flags(&mut self, flags: TypeFlags) {
         self.flags = self.flags | flags;
     }
@@ -91,7 +97,7 @@ impl FlagComputation {
             &ty::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
 
             &ty::Param(_) => {
-                self.add_flags(TypeFlags::HAS_TY_PARAM);
+                self.add_flags(TypeFlags::HAS_KNOWN_TY_PARAM);
                 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
 
@@ -292,7 +298,7 @@ impl FlagComputation {
                 self.add_bound_var(debruijn);
             }
             ty::ConstKind::Param(_) => {
-                self.add_flags(TypeFlags::HAS_CT_PARAM);
+                self.add_flags(TypeFlags::HAS_KNOWN_CT_PARAM);
                 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
             ty::ConstKind::Placeholder(_) => {
@@ -305,8 +311,12 @@ impl FlagComputation {
     }
 
     fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'tcx>) {
-        // TODO
-        self.add_substs(ct.substs_.unwrap());
+        if let Some(substs) = ct.substs_ {
+            self.add_substs(substs);
+        } else {
+            self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
+            self.add_flags(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_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 6e70e8ddaed..0c5e292e6eb 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -74,8 +74,14 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
         self.has_vars_bound_at_or_above(ty::INNERMOST)
     }
 
+    fn definitely_has_type_flags(&self, tcx: TyCtxt<'tcx>, flags: TypeFlags) -> bool {
+        self.visit_with(&mut HasTypeFlagsVisitor { tcx: Some(tcx), flags }).break_value()
+            == Some(FoundFlags)
+    }
+
     fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags)
+        self.visit_with(&mut HasTypeFlagsVisitor { tcx: None, flags }).break_value()
+            == Some(FoundFlags)
     }
     fn has_projections(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_PROJECTION)
@@ -86,8 +92,18 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
     fn references_error(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_ERROR)
     }
-    fn has_param_types_or_consts(&self) -> bool {
-        self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM)
+    fn has_potential_param_types_or_consts(&self) -> bool {
+        self.has_type_flags(
+            TypeFlags::HAS_KNOWN_TY_PARAM
+                | TypeFlags::HAS_KNOWN_CT_PARAM
+                | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS,
+        )
+    }
+    fn has_param_types_or_consts(&self, tcx: TyCtxt<'tcx>) -> bool {
+        self.definitely_has_type_flags(
+            tcx,
+            TypeFlags::HAS_KNOWN_TY_PARAM | TypeFlags::HAS_KNOWN_CT_PARAM,
+        )
     }
     fn has_infer_regions(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_RE_INFER)
@@ -108,13 +124,18 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
                 | TypeFlags::HAS_CT_PLACEHOLDER,
         )
     }
-    fn needs_subst(&self) -> bool {
-        self.has_type_flags(TypeFlags::NEEDS_SUBST)
+    fn potentially_needs_subst(&self) -> bool {
+        self.has_type_flags(
+            TypeFlags::KNOWN_NEEDS_SUBST | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS,
+        )
+    }
+    fn needs_subst(&self, tcx: TyCtxt<'tcx>) -> bool {
+        self.definitely_has_type_flags(tcx, TypeFlags::KNOWN_NEEDS_SUBST)
     }
     /// "Free" regions in this context means that it has any region
     /// that is not (a) erased or (b) late-bound.
-    fn has_free_regions(&self) -> bool {
-        self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
+    fn has_free_regions(&self, tcx: TyCtxt<'tcx>) -> bool {
+        self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_REGIONS)
     }
 
     fn has_erased_regions(&self) -> bool {
@@ -122,15 +143,25 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
     }
 
     /// True if there are any un-erased free regions.
-    fn has_erasable_regions(&self) -> bool {
-        self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
+    fn has_erasable_regions(&self, tcx: TyCtxt<'tcx>) -> bool {
+        self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_REGIONS)
+    }
+
+    /// Indicates whether this value definitely references only 'global'
+    /// generic parameters that are the same regardless of what fn we are
+    /// in. This is used for caching.
+    ///
+    /// Note that this function is pessimistic and may incorrectly return
+    /// `false`.
+    fn is_known_global(&self) -> bool {
+        !self.has_type_flags(TypeFlags::HAS_POTENTIAL_FREE_LOCAL_NAMES)
     }
 
     /// Indicates whether this value references only 'global'
     /// generic parameters that are the same regardless of what fn we are
     /// in. This is used for caching.
-    fn is_global(&self) -> bool {
-        !self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES)
+    fn is_global(&self, tcx: TyCtxt<'tcx>) -> bool {
+        !self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_LOCAL_NAMES)
     }
 
     /// True if there are any late-bound regions
@@ -217,6 +248,10 @@ pub trait TypeVisitor<'tcx>: Sized {
         c.super_visit_with(self)
     }
 
+    fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
+        uv.super_visit_with(self)
+    }
+
     fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
         p.super_visit_with(self)
     }
@@ -369,7 +404,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
             fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 // We're only interested in types involving regions
-                if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) {
+                if ty.flags().intersects(TypeFlags::HAS_POTENTIAL_FREE_REGIONS) {
                     ty.super_visit_with(self)
                 } else {
                     ControlFlow::CONTINUE
@@ -1078,23 +1113,19 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
 struct FoundFlags;
 
 // FIXME: Optimize for checking for infer flags
-struct HasTypeFlagsVisitor {
+struct HasTypeFlagsVisitor<'tcx> {
+    tcx: Option<TyCtxt<'tcx>>,
     flags: ty::TypeFlags,
 }
 
-impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
+impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor<'tcx> {
     type BreakTy = FoundFlags;
     fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
-        // TypeFlagsVisitor must not look into the default anon const substs
-        // as that would cause cycle errors, but we do care about them for
-        // some flags.
-        //
-        // We therefore have to be very careful here.
-        None
+        self.tcx
     }
 
     #[inline]
-    fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         debug!(
             "HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}",
             t,
@@ -1103,6 +1134,11 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
         );
         if t.flags().intersects(self.flags) {
             ControlFlow::Break(FoundFlags)
+        } else if self.tcx.is_some()
+            && t.flags().intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS)
+            && self.flags.intersects(TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS)
+        {
+            t.super_visit_with(self)
         } else {
             ControlFlow::CONTINUE
         }
@@ -1125,6 +1161,26 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
         debug!("HasTypeFlagsVisitor: c={:?} c.flags={:?} self.flags={:?}", c, flags, self.flags);
         if flags.intersects(self.flags) {
             ControlFlow::Break(FoundFlags)
+        } else if self.tcx.is_some()
+            && flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS)
+            && self.flags.intersects(TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS)
+        {
+            c.super_visit_with(self)
+        } else {
+            ControlFlow::CONTINUE
+        }
+    }
+
+    fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
+        let flags = FlagComputation::for_unevaluated_const(uv);
+        debug!("HasTypeFlagsVisitor: uv={:?} uv.flags={:?} self.flags={:?}", uv, flags, self.flags);
+        if flags.intersects(self.flags) {
+            ControlFlow::Break(FoundFlags)
+        } else if self.tcx.is_some()
+            && flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS)
+            && self.flags.intersects(TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS)
+        {
+            uv.super_visit_with(self)
         } else {
             ControlFlow::CONTINUE
         }
@@ -1138,6 +1194,11 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
         );
         if predicate.inner.flags.intersects(self.flags) {
             ControlFlow::Break(FoundFlags)
+        } else if self.tcx.is_some()
+            && predicate.inner.flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS)
+            && self.flags.intersects(TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS)
+        {
+            predicate.super_visit_with(self)
         } else {
             ControlFlow::CONTINUE
         }
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 8f90c7a8845..6761fbaf536 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1727,7 +1727,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
         // Ignore layouts that are done with non-empty environments or
         // non-monomorphic layouts, as the user only wants to see the stuff
         // resulting from the final codegen session.
-        if layout.ty.has_param_types_or_consts() || !self.param_env.caller_bounds().is_empty() {
+        if layout.ty.has_param_types_or_consts(self.tcx)
+            || !self.param_env.caller_bounds().is_empty()
+        {
             return;
         }
 
@@ -1894,7 +1896,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
                 let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
                 match tail.kind() {
                     ty::Param(_) | ty::Projection(_) => {
-                        debug_assert!(tail.has_param_types_or_consts());
+                        debug_assert!(tail.has_param_types_or_consts(tcx));
                         Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
                     }
                     _ => bug!(
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 62e093581b8..eccc1ebd805 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1292,7 +1292,7 @@ impl<'tcx> ParamEnv<'tcx> {
             Reveal::UserFacing => ParamEnvAnd { param_env: self, value },
 
             Reveal::All => {
-                if value.is_global() {
+                if value.is_known_global() {
                     ParamEnvAnd { param_env: self.without_caller_bounds(), value }
                 } else {
                     ParamEnvAnd { param_env: self, value }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 13222363096..5c3da507e14 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1201,7 +1201,9 @@ pub trait PrettyPrinter<'tcx>:
             //
             // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
             // correct `ty::ParamEnv` to allow printing *all* constant values.
-            (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => {
+            (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..))
+                if !ty.has_potential_param_types_or_consts() =>
+            {
                 let contents = self.tcx().destructure_const(
                     ty::ParamEnv::reveal_all()
                         .and(self.tcx().mk_const(ty::Const { val: ty::ConstKind::Value(ct), ty })),
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index fe7d46240cb..369dfaf32a0 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -1086,6 +1086,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> {
         }
     }
 
+    fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        visitor.visit_unevaluated_const(*self)
+    }
+
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
         if let Some(tcx) = visitor.tcx_for_anon_const_substs() {
             self.substs(tcx).visit_with(visitor)
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 8e0a2d4a28d..8b893b779c0 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1565,26 +1565,26 @@ impl RegionKind {
 
         match *self {
             ty::ReVar(..) => {
-                flags = flags | TypeFlags::HAS_FREE_REGIONS;
-                flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
+                flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
+                flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
                 flags = flags | TypeFlags::HAS_RE_INFER;
             }
             ty::RePlaceholder(..) => {
-                flags = flags | TypeFlags::HAS_FREE_REGIONS;
-                flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
+                flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
+                flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
                 flags = flags | TypeFlags::HAS_RE_PLACEHOLDER;
             }
             ty::ReEarlyBound(..) => {
-                flags = flags | TypeFlags::HAS_FREE_REGIONS;
-                flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
-                flags = flags | TypeFlags::HAS_RE_PARAM;
+                flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
+                flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
+                flags = flags | TypeFlags::HAS_KNOWN_RE_PARAM;
             }
             ty::ReFree { .. } => {
-                flags = flags | TypeFlags::HAS_FREE_REGIONS;
-                flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
+                flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
+                flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
             }
             ty::ReEmpty(_) | ty::ReStatic => {
-                flags = flags | TypeFlags::HAS_FREE_REGIONS;
+                flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
             }
             ty::ReLateBound(..) => {
                 flags = flags | TypeFlags::HAS_RE_LATE_BOUND;
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index 84ec2e76c0b..2438d1a1602 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -486,7 +486,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if !t.needs_subst() {
+        if !t.potentially_needs_subst() {
             return t;
         }
 
@@ -497,10 +497,6 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
     }
 
     fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
-        if !c.needs_subst() {
-            return c;
-        }
-
         if let ty::ConstKind::Param(p) = c.val {
             self.const_for_param(p, c)
         } else {
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs b/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs
index e411f1dc108..566c11811e6 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs
@@ -171,7 +171,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
         for (local, location) in drop_used {
             if !live_locals.contains(&local) {
                 let local_ty = self.cx.body.local_decls[local].ty;
-                if local_ty.has_free_regions() {
+                if local_ty.has_free_regions(self.cx.typeck.tcx()) {
                     self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations);
                 }
             }
diff --git a/compiler/rustc_mir/src/interpret/util.rs b/compiler/rustc_mir/src/interpret/util.rs
index b9d6e002e2d..37c13c2d42a 100644
--- a/compiler/rustc_mir/src/interpret/util.rs
+++ b/compiler/rustc_mir/src/interpret/util.rs
@@ -9,7 +9,7 @@ where
     T: TypeFoldable<'tcx>,
 {
     debug!("ensure_monomorphic_enough: ty={:?}", ty);
-    if !ty.needs_subst() {
+    if !ty.potentially_needs_subst() {
         return Ok(());
     }
 
@@ -25,19 +25,8 @@ where
             Some(self.tcx)
         }
 
-        fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-            if !c.needs_subst() {
-                return ControlFlow::CONTINUE;
-            }
-
-            match c.val {
-                ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam),
-                _ => c.super_visit_with(self),
-            }
-        }
-
         fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-            if !ty.needs_subst() {
+            if !ty.potentially_needs_subst() {
                 return ControlFlow::CONTINUE;
             }
 
@@ -54,7 +43,7 @@ where
                         let is_used = unused_params.contains(index).map_or(true, |unused| !unused);
                         // Only recurse when generic parameters in fns, closures and generators
                         // are used and require substitution.
-                        match (is_used, subst.needs_subst()) {
+                        match (is_used, subst.needs_subst(self.tcx)) {
                             // Just in case there are closures or generators within this subst,
                             // recurse.
                             (true, true) => return subst.super_visit_with(self),
@@ -77,6 +66,13 @@ where
                 _ => ty.super_visit_with(self),
             }
         }
+
+        fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+            match c.val {
+                ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam),
+                _ => c.super_visit_with(self),
+            }
+        }
     }
 
     let mut vis = UsedParamsNeedSubstVisitor { tcx };
diff --git a/compiler/rustc_mir/src/monomorphize/polymorphize.rs b/compiler/rustc_mir/src/monomorphize/polymorphize.rs
index b086053a0c1..368ac70b552 100644
--- a/compiler/rustc_mir/src/monomorphize/polymorphize.rs
+++ b/compiler/rustc_mir/src/monomorphize/polymorphize.rs
@@ -288,7 +288,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
     }
     #[instrument(skip(self))]
     fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-        if !c.has_param_types_or_consts() {
+        if !c.has_potential_param_types_or_consts() {
             return ControlFlow::CONTINUE;
         }
 
@@ -321,7 +321,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
 
     #[instrument(skip(self))]
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-        if !ty.has_param_types_or_consts() {
+        if !ty.has_potential_param_types_or_consts() {
             return ControlFlow::CONTINUE;
         }
 
@@ -363,7 +363,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a, 'tcx> {
 
     #[instrument(skip(self))]
     fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-        if !c.has_param_types_or_consts() {
+        if !c.has_potential_param_types_or_consts() {
             return ControlFlow::CONTINUE;
         }
 
@@ -381,7 +381,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a, 'tcx> {
 
     #[instrument(skip(self))]
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-        if !ty.has_param_types_or_consts() {
+        if !ty.has_potential_param_types_or_consts() {
             return ControlFlow::CONTINUE;
         }
 
diff --git a/compiler/rustc_mir/src/shim.rs b/compiler/rustc_mir/src/shim.rs
index 8c3d828894c..8083ec95447 100644
--- a/compiler/rustc_mir/src/shim.rs
+++ b/compiler/rustc_mir/src/shim.rs
@@ -163,7 +163,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
 
     let source = MirSource::from_instance(ty::InstanceDef::DropGlue(def_id, ty));
     let mut body =
-        new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span);
+        new_body(tcx, source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span);
 
     if ty.is_some() {
         // The first argument (index 0), but add 1 for the return value.
@@ -202,6 +202,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
 }
 
 fn new_body<'tcx>(
+    tcx: TyCtxt<'tcx>,
     source: MirSource<'tcx>,
     basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
     local_decls: IndexVec<Local, LocalDecl<'tcx>>,
@@ -209,6 +210,7 @@ fn new_body<'tcx>(
     span: Span,
 ) -> Body<'tcx> {
     Body::new(
+        tcx,
         source,
         basic_blocks,
         IndexVec::from_elem_n(
@@ -353,7 +355,14 @@ impl CloneShimBuilder<'tcx> {
             self.def_id,
             self.sig.inputs_and_output[0],
         ));
-        new_body(source, self.blocks, self.local_decls, self.sig.inputs().len(), self.span)
+        new_body(
+            self.tcx,
+            source,
+            self.blocks,
+            self.local_decls,
+            self.sig.inputs().len(),
+            self.span,
+        )
     }
 
     fn source_info(&self) -> SourceInfo {
@@ -851,8 +860,14 @@ fn build_call_shim<'tcx>(
         block(&mut blocks, vec![], TerminatorKind::Resume, true);
     }
 
-    let mut body =
-        new_body(MirSource::from_instance(instance), blocks, local_decls, sig.inputs().len(), span);
+    let mut body = new_body(
+        tcx,
+        MirSource::from_instance(instance),
+        blocks,
+        local_decls,
+        sig.inputs().len(),
+        span,
+    );
 
     if let Abi::RustCall = sig.abi {
         body.spread_arg = Some(Local::new(sig.inputs().len()));
@@ -917,6 +932,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
 
     let source = MirSource::item(ctor_id);
     let body = new_body(
+        tcx,
         source,
         IndexVec::from_elem_n(start_block, 1),
         local_decls,
diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs
index 98581f76821..0d58625633f 100644
--- a/compiler/rustc_mir/src/transform/const_prop.rs
+++ b/compiler/rustc_mir/src/transform/const_prop.rs
@@ -120,7 +120,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
             .predicates_of(def_id.to_def_id())
             .predicates
             .iter()
-            .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
+            .filter_map(|(p, _)| if p.is_global(tcx) { Some(*p) } else { None });
         if traits::impossible_predicates(
             tcx,
             traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(),
@@ -132,6 +132,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
         trace!("ConstProp starting for {:?}", def_id);
 
         let dummy_body = &Body::new(
+            tcx,
             body.source,
             body.basic_blocks().clone(),
             body.source_scopes.clone(),
@@ -468,7 +469,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
     /// Returns the value, if any, of evaluating `c`.
     fn eval_constant(&mut self, c: &Constant<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
         // FIXME we need to revisit this for #67176
-        if c.needs_subst() {
+        if c.needs_subst(self.tcx) {
             return None;
         }
 
@@ -488,9 +489,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                             }) => 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(),
+                            _ => c.literal.needs_subst(*tcx),
                         },
-                        ConstantKind::Val(_, ty) => ty.needs_subst(),
+                        ConstantKind::Val(_, ty) => ty.needs_subst(*tcx),
                     };
                     if lint_only {
                         // Out of backwards compatibility we cannot report hard errors in unused
@@ -720,7 +721,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         }
 
         // FIXME we need to revisit this for #67176
-        if rvalue.needs_subst() {
+        if rvalue.needs_subst(self.tcx) {
             return None;
         }
 
diff --git a/compiler/rustc_mir/src/transform/inline/cycle.rs b/compiler/rustc_mir/src/transform/inline/cycle.rs
index c9eafafff57..46628b928de 100644
--- a/compiler/rustc_mir/src/transform/inline/cycle.rs
+++ b/compiler/rustc_mir/src/transform/inline/cycle.rs
@@ -89,7 +89,7 @@ crate fn mir_callgraph_reachable(
                     // FIXME: A not fully substituted drop shim can cause ICEs if one attempts to
                     // have its MIR built. Likely oli-obk just screwed up the `ParamEnv`s, so this
                     // needs some more analysis.
-                    if callee.needs_subst() {
+                    if callee.needs_subst(tcx) {
                         continue;
                     }
                 }
diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs
index fa648a6dd49..d4c2456e9a4 100644
--- a/compiler/rustc_mir/src/transform/mod.rs
+++ b/compiler/rustc_mir/src/transform/mod.rs
@@ -400,7 +400,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -
         }
     }
 
-    debug_assert!(!body.has_free_regions(), "Free regions in MIR for CTFE");
+    debug_assert!(!body.has_free_regions(tcx), "Free regions in MIR for CTFE");
 
     body
 }
@@ -594,7 +594,7 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
         tcx.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(did)).steal();
     run_optimization_passes(tcx, &mut body);
 
-    debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR");
+    debug_assert!(!body.has_free_regions(tcx), "Free regions in optimized MIR");
 
     body
 }
@@ -621,7 +621,7 @@ fn promoted_mir<'tcx>(
         run_post_borrowck_cleanup_passes(tcx, body);
     }
 
-    debug_assert!(!promoted.has_free_regions(), "Free regions in promoted MIR");
+    debug_assert!(!promoted.has_free_regions(tcx), "Free regions in promoted MIR");
 
     tcx.arena.alloc(promoted)
 }
diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs
index 14c9b3b0d47..1b43670ba3a 100644
--- a/compiler/rustc_mir/src/transform/promote_consts.rs
+++ b/compiler/rustc_mir/src/transform/promote_consts.rs
@@ -992,6 +992,7 @@ pub fn promote_candidates<'tcx>(
         scope.parent_scope = None;
 
         let promoted = Body::new(
+            tcx,
             body.source, // `promoted` gets filled in below
             IndexVec::new(),
             IndexVec::from_elem_n(scope, 1),
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index bfebe860971..0a760a740dc 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -239,10 +239,10 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
         // The exception is `body.user_type_annotations`, which is used unmodified
         // by borrow checking.
         debug_assert!(
-            !(body.local_decls.has_free_regions()
-                || body.basic_blocks().has_free_regions()
-                || body.var_debug_info.has_free_regions()
-                || body.yield_ty().has_free_regions()),
+            !(body.local_decls.has_free_regions(tcx)
+                || body.basic_blocks().has_free_regions(tcx)
+                || body.var_debug_info.has_free_regions(tcx)
+                || body.yield_ty().has_free_regions(tcx)),
             "Unexpected free regions in MIR: {:?}",
             body,
         );
@@ -755,6 +755,7 @@ fn construct_error<'a, 'tcx>(
     cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
 
     let mut body = Body::new(
+        tcx,
         MirSource::item(def.did.to_def_id()),
         cfg.basic_blocks,
         source_scopes,
@@ -843,6 +844,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
 
         Body::new(
+            self.tcx,
             MirSource::item(self.def_id),
             self.cfg.basic_blocks,
             self.source_scopes,
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 1b4e6b4e381..267e2d8808f 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -109,7 +109,7 @@ fn get_symbol_hash<'tcx>(
         // Include the main item-type. Note that, in this case, the
         // assertions about `needs_subst` may not hold, but this item-type
         // ought to be the same for every reference anyway.
-        assert!(!item_type.has_erasable_regions());
+        assert!(!item_type.has_erasable_regions(tcx));
         hcx.while_hashing_spans(false, |hcx| {
             hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
                 item_type.hash_stable(hcx, &mut hasher);
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index c4c1ec8ce4e..3ac9d1e5745 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -277,7 +277,8 @@ impl Printer<'tcx> for &mut SymbolMangler<'tcx> {
 
         // Encode impl generic params if the substitutions contain parameters (implying
         // polymorphization is enabled) and this isn't an inherent impl.
-        if impl_trait_ref.is_some() && substs.iter().any(|a| a.has_param_types_or_consts()) {
+        if impl_trait_ref.is_some() && substs.iter().any(|a| a.has_param_types_or_consts(self.tcx))
+        {
             self = self.path_generic_args(
                 |this| {
                     this.path_append_ns(
diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs
index f89ca0fed03..b743c809ca2 100644
--- a/compiler/rustc_trait_selection/src/opaque_types.rs
+++ b/compiler/rustc_trait_selection/src/opaque_types.rs
@@ -583,7 +583,7 @@ where
 
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         // We're only interested in types involving regions
-        if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) {
+        if !ty.flags().intersects(ty::TypeFlags::HAS_POTENTIAL_FREE_REGIONS) {
             return ControlFlow::CONTINUE;
         }
 
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 9bb4af16a8f..6ab079ad404 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -391,7 +391,7 @@ fn orphan_check_trait_ref<'tcx>(
 ) -> Result<(), OrphanCheckErr<'tcx>> {
     debug!("orphan_check_trait_ref(trait_ref={:?}, in_crate={:?})", trait_ref, in_crate);
 
-    if trait_ref.needs_infer() && trait_ref.needs_subst() {
+    if trait_ref.needs_infer() && trait_ref.needs_subst(tcx) {
         bug!(
             "can't orphan check a trait ref with both params and inference variables {:?}",
             trait_ref
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 2f1e7e9d509..2cc74ca2abb 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -91,7 +91,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
                         let leaf = leaf.subst(tcx, ct.substs);
                         if leaf.has_infer_types_or_consts() {
                             failure_kind = FailureKind::MentionsInfer;
-                        } else if leaf.has_param_types_or_consts() {
+                        } else if leaf.has_param_types_or_consts(tcx) {
                             failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
                         }
 
@@ -101,7 +101,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
                         let ty = ty.subst(tcx, ct.substs);
                         if ty.has_infer_types_or_consts() {
                             failure_kind = FailureKind::MentionsInfer;
-                        } else if ty.has_param_types_or_consts() {
+                        } else if ty.has_param_types_or_consts(tcx) {
                             failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
                         }
 
@@ -158,7 +158,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
     let concrete =
         infcx.const_eval_resolve(param_env, ty::Unevaluated::new(def, substs), Some(span));
 
-    if concrete.is_ok() && substs.has_param_types_or_consts() {
+    if concrete.is_ok() && substs.has_param_types_or_consts(infcx.tcx) {
         match infcx.tcx.def_kind(def.did) {
             DefKind::AnonConst => {
                 let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(def);
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 110d83cbe28..edf2274ab54 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -669,7 +669,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
         stalled_on: &mut Vec<TyOrConstInferVar<'tcx>>,
     ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
         let infcx = self.selcx.infcx();
-        if obligation.predicate.is_global() {
+        if obligation.predicate.is_known_global() {
             // no type variables present, can use evaluation for better caching.
             // FIXME: consider caching errors too.
             //
@@ -728,7 +728,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
     ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
         let tcx = self.selcx.tcx();
 
-        if obligation.predicate.is_global() {
+        if obligation.predicate.is_global(tcx) {
             // no type variables present, can use evaluation for better caching.
             // FIXME: consider caching errors too.
             //
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 477d29f1a4f..43ee1c3304a 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -450,7 +450,7 @@ fn subst_and_check_impossible_predicates<'tcx>(
     debug!("subst_and_check_impossible_predicates(key={:?})", key);
 
     let mut predicates = tcx.predicates_of(key.0).instantiate(tcx, key.1).predicates;
-    predicates.retain(|predicate| !predicate.needs_subst());
+    predicates.retain(|predicate| !predicate.needs_subst(tcx));
     let result = impossible_predicates(tcx, predicates);
 
     debug!("subst_and_check_impossible_predicates(key={:?}) = {:?}", key, result);
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index c150b222266..1c4e7e6c589 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -544,7 +544,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 },
 
                 ty::PredicateKind::TypeOutlives(pred) => {
-                    if pred.0.is_global() {
+                    if pred.0.is_known_global() {
                         Ok(EvaluatedToOk)
                     } else {
                         Ok(EvaluatedToOkModuloRegions)
@@ -692,8 +692,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         debug!(?obligation, "evaluate_trait_predicate_recursively");
 
         if !self.intercrate
-            && obligation.is_global()
-            && obligation.param_env.caller_bounds().iter().all(|bound| bound.needs_subst())
+            && obligation.is_global(self.tcx())
+            && obligation
+                .param_env
+                .caller_bounds()
+                .iter()
+                .all(|bound| bound.needs_subst(self.tcx()))
         {
             // If a param env has no global bounds, global obligations do not
             // depend on its particular value in order to work, so we can clear
@@ -1452,7 +1456,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // the param_env so that it can be given the lowest priority. See
         // #50825 for the motivation for this.
         let is_global =
-            |cand: &ty::PolyTraitRef<'_>| cand.is_global() && !cand.has_late_bound_regions();
+            |cand: &ty::PolyTraitRef<'_>| cand.is_known_global() && !cand.has_late_bound_regions();
 
         // (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`,
         // and `DiscriminantKindCandidate` to anything else.
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 2d102127dd9..c405bbe2d1f 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -19,94 +19,116 @@ bitflags! {
         // Does this have parameters? Used to determine whether substitution is
         // required.
         /// Does this have `Param`?
-        const HAS_TY_PARAM                = 1 << 0;
+        const HAS_KNOWN_TY_PARAM                = 1 << 0;
         /// Does this have `ReEarlyBound`?
-        const HAS_RE_PARAM                = 1 << 1;
+        const HAS_KNOWN_RE_PARAM                = 1 << 1;
         /// Does this have `ConstKind::Param`?
-        const HAS_CT_PARAM                = 1 << 2;
+        const HAS_KNOWN_CT_PARAM                = 1 << 2;
 
-        const NEEDS_SUBST                 = TypeFlags::HAS_TY_PARAM.bits
-                                          | TypeFlags::HAS_RE_PARAM.bits
-                                          | TypeFlags::HAS_CT_PARAM.bits;
+        const KNOWN_NEEDS_SUBST                 = TypeFlags::HAS_KNOWN_TY_PARAM.bits
+                                                | TypeFlags::HAS_KNOWN_RE_PARAM.bits
+                                                | TypeFlags::HAS_KNOWN_CT_PARAM.bits;
 
         /// Does this have `Infer`?
-        const HAS_TY_INFER                = 1 << 3;
+        const HAS_TY_INFER                      = 1 << 3;
         /// Does this have `ReVar`?
-        const HAS_RE_INFER                = 1 << 4;
+        const HAS_RE_INFER                      = 1 << 4;
         /// Does this have `ConstKind::Infer`?
-        const HAS_CT_INFER                = 1 << 5;
+        const HAS_CT_INFER                      = 1 << 5;
 
         /// Does this have inference variables? Used to determine whether
         /// inference is required.
-        const NEEDS_INFER                 = TypeFlags::HAS_TY_INFER.bits
-                                          | TypeFlags::HAS_RE_INFER.bits
-                                          | TypeFlags::HAS_CT_INFER.bits;
+        const NEEDS_INFER                       = TypeFlags::HAS_TY_INFER.bits
+                                                | TypeFlags::HAS_RE_INFER.bits
+                                                | TypeFlags::HAS_CT_INFER.bits;
 
         /// Does this have `Placeholder`?
-        const HAS_TY_PLACEHOLDER          = 1 << 6;
+        const HAS_TY_PLACEHOLDER                = 1 << 6;
         /// Does this have `RePlaceholder`?
-        const HAS_RE_PLACEHOLDER          = 1 << 7;
+        const HAS_RE_PLACEHOLDER                = 1 << 7;
         /// Does this have `ConstKind::Placeholder`?
-        const HAS_CT_PLACEHOLDER          = 1 << 8;
+        const HAS_CT_PLACEHOLDER                = 1 << 8;
 
         /// `true` if there are "names" of regions and so forth
         /// that are local to a particular fn/inferctxt
-        const HAS_FREE_LOCAL_REGIONS      = 1 << 9;
+        const HAS_KNOWN_FREE_LOCAL_REGIONS      = 1 << 9;
 
         /// `true` if there are "names" of types and regions and so forth
         /// that are local to a particular fn
-        const HAS_FREE_LOCAL_NAMES        = TypeFlags::HAS_TY_PARAM.bits
-                                          | TypeFlags::HAS_CT_PARAM.bits
-                                          | TypeFlags::HAS_TY_INFER.bits
-                                          | TypeFlags::HAS_CT_INFER.bits
-                                          | TypeFlags::HAS_TY_PLACEHOLDER.bits
-                                          | TypeFlags::HAS_CT_PLACEHOLDER.bits
-                                          // We consider 'freshened' types and constants
-                                          // to depend on a particular fn.
-                                          // The freshening process throws away information,
-                                          // which can make things unsuitable for use in a global
-                                          // cache. Note that there is no 'fresh lifetime' flag -
-                                          // freshening replaces all lifetimes with `ReErased`,
-                                          // which is different from how types/const are freshened.
-                                          | TypeFlags::HAS_TY_FRESH.bits
-                                          | TypeFlags::HAS_CT_FRESH.bits
-                                          | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits;
+        const HAS_KNOWN_FREE_LOCAL_NAMES        = TypeFlags::HAS_KNOWN_TY_PARAM.bits
+                                                | TypeFlags::HAS_KNOWN_CT_PARAM.bits
+                                                | TypeFlags::HAS_TY_INFER.bits
+                                                | TypeFlags::HAS_CT_INFER.bits
+                                                | TypeFlags::HAS_TY_PLACEHOLDER.bits
+                                                | TypeFlags::HAS_CT_PLACEHOLDER.bits
+                                                // We consider 'freshened' types and constants
+                                                // to depend on a particular fn.
+                                                // The freshening process throws away information,
+                                                // which can make things unsuitable for use in a global
+                                                // cache. Note that there is no 'fresh lifetime' flag -
+                                                // freshening replaces all lifetimes with `ReErased`,
+                                                // which is different from how types/const are freshened.
+                                                | TypeFlags::HAS_TY_FRESH.bits
+                                                | TypeFlags::HAS_CT_FRESH.bits
+                                                | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS.bits;
+
+        const HAS_POTENTIAL_FREE_LOCAL_NAMES    = TypeFlags::HAS_KNOWN_FREE_LOCAL_NAMES.bits
+                                                | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS.bits;
 
         /// Does this have `Projection`?
-        const HAS_TY_PROJECTION           = 1 << 10;
+        const HAS_TY_PROJECTION                 = 1 << 10;
         /// Does this have `Opaque`?
-        const HAS_TY_OPAQUE               = 1 << 11;
+        const HAS_TY_OPAQUE                     = 1 << 11;
         /// Does this have `ConstKind::Unevaluated`?
-        const HAS_CT_PROJECTION           = 1 << 12;
+        const HAS_CT_PROJECTION                 = 1 << 12;
 
         /// Could this type be normalized further?
-        const HAS_PROJECTION              = TypeFlags::HAS_TY_PROJECTION.bits
-                                          | TypeFlags::HAS_TY_OPAQUE.bits
-                                          | TypeFlags::HAS_CT_PROJECTION.bits;
+        const HAS_PROJECTION                    = TypeFlags::HAS_TY_PROJECTION.bits
+                                                | TypeFlags::HAS_TY_OPAQUE.bits
+                                                | TypeFlags::HAS_CT_PROJECTION.bits;
 
         /// Is an error type/const reachable?
-        const HAS_ERROR                   = 1 << 13;
+        const HAS_ERROR                         = 1 << 13;
 
         /// Does this have any region that "appears free" in the type?
         /// Basically anything but `ReLateBound` and `ReErased`.
-        const HAS_FREE_REGIONS            = 1 << 14;
+        const HAS_KNOWN_FREE_REGIONS            = 1 << 14;
+
+        const HAS_POTENTIAL_FREE_REGIONS        = TypeFlags::HAS_KNOWN_FREE_REGIONS.bits
+                                                | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS.bits;
 
         /// Does this have any `ReLateBound` regions? Used to check
         /// if a global bound is safe to evaluate.
-        const HAS_RE_LATE_BOUND           = 1 << 15;
+        const HAS_RE_LATE_BOUND                 = 1 << 15;
 
         /// Does this have any `ReErased` regions?
-        const HAS_RE_ERASED               = 1 << 16;
+        const HAS_RE_ERASED                     = 1 << 16;
 
         /// Does this value have parameters/placeholders/inference variables which could be
         /// replaced later, in a way that would change the results of `impl` specialization?
-        const STILL_FURTHER_SPECIALIZABLE = 1 << 17;
+        ///
+        /// Note that this flag being set is not a guarantee, as it is also
+        /// set if there are any anon consts with unknown default substs.
+        const STILL_FURTHER_SPECIALIZABLE       = 1 << 17;
 
         /// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`?
-        const HAS_TY_FRESH                = 1 << 18;
+        const HAS_TY_FRESH                      = 1 << 18;
 
         /// Does this value have `InferConst::Fresh`?
-        const HAS_CT_FRESH                = 1 << 19;
+        const HAS_CT_FRESH                      = 1 << 19;
+
+        /// Does this value have unknown default anon const substs.
+        ///
+        /// For more details refer to...
+        /// FIXME(@lcnr): ask me for now, still have to write all of this.
+        const HAS_UNKNOWN_DEFAULT_CONST_SUBSTS  = 1 << 20;
+        /// Flags which can be influenced by default anon const substs.
+        const MAY_NEED_DEFAULT_CONST_SUBSTS     = TypeFlags::HAS_KNOWN_RE_PARAM.bits
+                                                | TypeFlags::HAS_KNOWN_TY_PARAM.bits
+                                                | TypeFlags::HAS_KNOWN_CT_PARAM.bits
+                                                | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS.bits
+                                                | TypeFlags::HAS_KNOWN_FREE_REGIONS.bits;
+
     }
 }
 
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 2879b7fcd91..bbfceeeff48 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -2204,7 +2204,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 self.prohibit_generics(path.segments);
                 // Try to evaluate any array length constants.
                 let normalized_ty = self.normalize_ty(span, tcx.at(span).type_of(def_id));
-                if forbid_generic && normalized_ty.needs_subst() {
+                if forbid_generic && normalized_ty.needs_subst(tcx) {
                     let mut err = tcx.sess.struct_span_err(
                         path.span,
                         "generic `Self` types are currently not permitted in anonymous constants",
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index 15fa696b6c4..25d1c8706e8 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -239,7 +239,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.tag(),
         );
 
-        if Self::can_contain_user_lifetime_bounds((substs, user_self_ty)) {
+        if self.can_contain_user_lifetime_bounds((substs, user_self_ty)) {
             let canonicalized = self.infcx.canonicalize_user_type_annotation(UserType::TypeOf(
                 def_id,
                 UserSubsts { substs, user_self_ty },
@@ -481,7 +481,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let ty = self.to_ty(ast_ty);
         debug!("to_ty_saving_user_provided_ty: ty={:?}", ty);
 
-        if Self::can_contain_user_lifetime_bounds(ty) {
+        if self.can_contain_user_lifetime_bounds(ty) {
             let c_ty = self.infcx.canonicalize_response(UserType::Ty(ty));
             debug!("to_ty_saving_user_provided_ty: c_ty={:?}", c_ty);
             self.typeck_results.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty);
@@ -526,11 +526,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     // reader, although I have my doubts). Also pass in types with inference
     // types, because they may be repeated. Other sorts of things are already
     // sufficiently enforced with erased regions. =)
-    fn can_contain_user_lifetime_bounds<T>(t: T) -> bool
+    fn can_contain_user_lifetime_bounds<T>(&self, t: T) -> bool
     where
         T: TypeFoldable<'tcx>,
     {
-        t.has_free_regions() || t.has_projections() || t.has_infer_types()
+        t.has_free_regions(self.tcx) || t.has_projections() || t.has_infer_types()
     }
 
     pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> {
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 0d121b9da87..057a15a4358 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -746,7 +746,7 @@ fn check_where_clauses<'tcx, 'fcx>(
                     // Ignore dependent defaults -- that is, where the default of one type
                     // parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
                     // be sure if it will error or not as user might always specify the other.
-                    if !ty.needs_subst() {
+                    if !ty.needs_subst(tcx) {
                         fcx.register_wf_obligation(
                             ty.into(),
                             tcx.def_span(param.def_id),
@@ -762,7 +762,7 @@ fn check_where_clauses<'tcx, 'fcx>(
                     // for `struct Foo<const N: usize, const M: usize = { 1 - 2 }>`
                     // we should eagerly error.
                     let default_ct = tcx.const_param_default(param.def_id);
-                    if !default_ct.needs_subst() {
+                    if !default_ct.needs_subst(tcx) {
                         fcx.register_wf_obligation(
                             default_ct.into(),
                             tcx.def_span(param.def_id),
@@ -796,7 +796,7 @@ fn check_where_clauses<'tcx, 'fcx>(
                 if is_our_default(param) {
                     let default_ty = tcx.type_of(param.def_id);
                     // ... and it's not a dependent default, ...
-                    if !default_ty.needs_subst() {
+                    if !default_ty.needs_subst(tcx) {
                         // ... then substitute it with the default.
                         return default_ty.into();
                     }
@@ -809,7 +809,7 @@ fn check_where_clauses<'tcx, 'fcx>(
                 if is_our_default(param) {
                     let default_ct = tcx.const_param_default(param.def_id);
                     // ... and it's not a dependent default, ...
-                    if !default_ct.needs_subst() {
+                    if !default_ct.needs_subst(tcx) {
                         // ... then substitute it with the default.
                         return default_ct.into();
                     }
@@ -858,7 +858,7 @@ fn check_where_clauses<'tcx, 'fcx>(
             let substituted_pred = pred.subst(tcx, substs);
             // Don't check non-defaulted params, dependent defaults (including lifetimes)
             // or preds with multiple params.
-            if substituted_pred.has_param_types_or_consts()
+            if substituted_pred.has_param_types_or_consts(tcx)
                 || param_count.params.len() > 1
                 || has_region
             {
@@ -1380,7 +1380,7 @@ fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, span: Span, id: hir::HirId) {
     for obligation in implied_obligations {
         let pred = obligation.predicate;
         // Match the existing behavior.
-        if pred.is_global() && !pred.has_late_bound_regions() {
+        if pred.is_global(fcx.tcx) && !pred.has_late_bound_regions() {
             let pred = fcx.normalize_associated_types_in(span, pred);
             let obligation = traits::Obligation::new(
                 traits::ObligationCause::new(span, id, traits::TrivialBound),
diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs
index 2e59defdb7b..c57ec9ef78f 100644
--- a/compiler/rustc_typeck/src/check/writeback.rs
+++ b/compiler/rustc_typeck/src/check/writeback.rs
@@ -130,7 +130,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
 
     fn write_ty_to_typeck_results(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) {
         debug!("write_ty_to_typeck_results({:?}, {:?})", hir_id, ty);
-        assert!(!ty.needs_infer() && !ty.has_placeholders() && !ty.has_free_regions());
+        assert!(!ty.needs_infer() && !ty.has_placeholders() && !ty.has_free_regions(self.tcx()));
         self.typeck_results.node_types_mut().insert(hir_id, ty);
     }
 
diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs
index 98f5f73b7be..9b10874b8bc 100644
--- a/compiler/rustc_typeck/src/collect/type_of.rs
+++ b/compiler/rustc_typeck/src/collect/type_of.rs
@@ -275,7 +275,16 @@ fn get_path_containing_arg_in_pat<'hir>(
 }
 
 pub(super) fn default_anon_const_substs(tcx: TyCtxt<'_>, def_id: DefId) -> SubstsRef<'_> {
-    InternalSubsts::identity_for_item(tcx, def_id)
+    let substs = InternalSubsts::identity_for_item(tcx, def_id);
+    // We only expect substs with the following type flags as default substs.
+    //
+    // Getting this wrong can lead to ICE and unsoundness, so we assert it here.
+    for arg in substs.iter().flat_map(|s| s.walk(tcx)) {
+        let allowed_flags = ty::TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS
+            | ty::TypeFlags::STILL_FURTHER_SPECIALIZABLE;
+        assert!(!arg.has_type_flags(!allowed_flags));
+    }
+    substs
 }
 
 pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
index 2d71c87bee7..d3e4be128a8 100644
--- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
@@ -363,7 +363,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
     match predicate.kind().skip_binder() {
         // Global predicates are either always true or always false, so we
         // are fine to specialize on.
-        _ if predicate.is_global() => (),
+        _ if predicate.is_global(tcx) => (),
         // We allow specializing on explicitly marked traits with no associated
         // items.
         ty::PredicateKind::Trait(ty::TraitPredicate {
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 5e559991c16..90b2aa16896 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -117,7 +117,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
         let fn_def_id = cx.tcx.hir().local_def_id(hir_id);
 
         let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds().iter())
-            .filter(|p| !p.is_global())
+            .filter(|p| !p.is_global(cx.tcx))
             .filter_map(|obligation| {
                 // Note that we do not want to deal with qualified predicates here.
                 match obligation.predicate.kind().no_bound_vars() {
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 98f3937ba3d..ddff1686ba2 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1581,7 +1581,7 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool {
         .predicates_of(did)
         .predicates
         .iter()
-        .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
+        .filter_map(|(p, _)| if p.is_global(cx.tcx) { Some(*p) } else { None });
     traits::impossible_predicates(
         cx.tcx,
         traits::elaborate_predicates(cx.tcx, predicates)