about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc_codegen_ssa/back/symbol_export.rs4
-rw-r--r--src/librustc_codegen_ssa/mir/constant.rs4
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs5
-rw-r--r--src/librustc_infer/infer/mod.rs4
-rw-r--r--src/librustc_interface/passes.rs3
-rw-r--r--src/librustc_metadata/rmeta/decoder/cstore_impl.rs4
-rw-r--r--src/librustc_middle/arena.rs30
-rw-r--r--src/librustc_middle/mir/interpret/queries.rs4
-rw-r--r--src/librustc_middle/mir/mono.rs4
-rw-r--r--src/librustc_middle/mir/query.rs40
-rw-r--r--src/librustc_middle/query/mod.rs118
-rw-r--r--src/librustc_middle/ty/context.rs19
-rw-r--r--src/librustc_middle/ty/instance.rs64
-rw-r--r--src/librustc_middle/ty/mod.rs100
-rw-r--r--src/librustc_middle/ty/print/pretty.rs16
-rw-r--r--src/librustc_middle/ty/query/keys.rs33
-rw-r--r--src/librustc_middle/ty/relate.rs8
-rw-r--r--src/librustc_middle/ty/structural_impls.rs18
-rw-r--r--src/librustc_middle/ty/sty.rs27
-rw-r--r--src/librustc_mir/borrow_check/mod.rs62
-rw-r--r--src/librustc_mir/borrow_check/nll.rs10
-rw-r--r--src/librustc_mir/borrow_check/type_check/mod.rs4
-rw-r--r--src/librustc_mir/borrow_check/universal_regions.rs49
-rw-r--r--src/librustc_mir/const_eval/eval_queries.rs25
-rw-r--r--src/librustc_mir/const_eval/machine.rs4
-rw-r--r--src/librustc_mir/interpret/eval_context.rs24
-rw-r--r--src/librustc_mir/interpret/operand.rs4
-rw-r--r--src/librustc_mir/monomorphize/collector.rs10
-rw-r--r--src/librustc_mir/monomorphize/partitioning.rs5
-rw-r--r--src/librustc_mir/transform/check_consts/qualifs.rs11
-rw-r--r--src/librustc_mir/transform/check_consts/validation.rs4
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs44
-rw-r--r--src/librustc_mir/transform/mod.rs186
-rw-r--r--src/librustc_mir/transform/promote_consts.rs17
-rw-r--r--src/librustc_mir/util/pretty.rs5
-rw-r--r--src/librustc_mir_build/build/mod.rs20
-rw-r--r--src/librustc_mir_build/hair/cx/expr.rs12
-rw-r--r--src/librustc_mir_build/hair/cx/mod.rs21
-rw-r--r--src/librustc_trait_selection/traits/fulfill.rs4
-rw-r--r--src/librustc_trait_selection/traits/select/mod.rs4
-rw-r--r--src/librustc_trait_selection/traits/wf.rs10
-rw-r--r--src/librustc_ty/instance.rs53
-rw-r--r--src/librustc_typeck/astconv.rs10
-rw-r--r--src/librustc_typeck/check/method/confirm.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs37
-rw-r--r--src/librustc_typeck/check/wfcheck.rs7
-rw-r--r--src/librustc_typeck/collect.rs1
-rw-r--r--src/librustc_typeck/collect/type_of.rs274
-rw-r--r--src/librustdoc/clean/utils.rs8
-rw-r--r--src/test/incremental/hashes/call_expressions.rs16
-rw-r--r--src/test/incremental/hashes/closure_expressions.rs6
-rw-r--r--src/test/incremental/hashes/enum_constructors.rs28
-rw-r--r--src/test/incremental/hashes/exported_vs_not.rs6
-rw-r--r--src/test/incremental/hashes/for_loops.rs16
-rw-r--r--src/test/incremental/hashes/function_interfaces.rs14
-rw-r--r--src/test/incremental/hashes/if_expressions.rs12
-rw-r--r--src/test/incremental/hashes/inherent_impls.rs20
-rw-r--r--src/test/incremental/hashes/inline_asm.rs12
-rw-r--r--src/test/incremental/hashes/let_expressions.rs24
-rw-r--r--src/test/incremental/hashes/loop_expressions.rs10
-rw-r--r--src/test/incremental/hashes/match_expressions.rs26
-rw-r--r--src/test/incremental/hashes/panic_exprs.rs18
-rw-r--r--src/test/incremental/hashes/struct_constructors.rs16
-rw-r--r--src/test/incremental/hashes/unary_and_binary_exprs.rs56
-rw-r--r--src/test/incremental/hashes/while_let_loops.rs12
-rw-r--r--src/test/incremental/hashes/while_loops.rs12
-rw-r--r--src/test/mir-opt/const-promotion-extern-static/rustc.BAR.PromoteTemps.diff4
-rw-r--r--src/test/mir-opt/const-promotion-extern-static/rustc.FOO.PromoteTemps.diff4
-rw-r--r--src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff4
-rw-r--r--src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff4
-rw-r--r--src/test/mir-opt/const_prop/const_prop_fails_gracefully/rustc.main.ConstProp.diff4
-rw-r--r--src/test/mir-opt/const_prop/control-flow-simplification/rustc.hello.ConstProp.diff4
-rw-r--r--src/test/mir-opt/const_prop/ref_deref/rustc.main.ConstProp.diff4
-rw-r--r--src/test/mir-opt/const_prop/ref_deref/rustc.main.PromoteTemps.diff4
-rw-r--r--src/test/mir-opt/const_prop/ref_deref_project/rustc.main.ConstProp.diff4
-rw-r--r--src/test/mir-opt/const_prop/ref_deref_project/rustc.main.PromoteTemps.diff4
-rw-r--r--src/test/mir-opt/const_prop/slice_len/32bit/rustc.main.ConstProp.diff4
-rw-r--r--src/test/mir-opt/const_prop/slice_len/64bit/rustc.main.ConstProp.diff4
-rw-r--r--src/test/mir-opt/inline/inline-retag/rustc.bar.Inline.after.mir8
-rw-r--r--src/test/mir-opt/issue-73223/32bit/rustc.main.PreCodegen.diff8
-rw-r--r--src/test/mir-opt/issue-73223/32bit/rustc.main.SimplifyArmIdentity.diff8
-rw-r--r--src/test/mir-opt/issue-73223/64bit/rustc.main.PreCodegen.diff8
-rw-r--r--src/test/mir-opt/issue-73223/64bit/rustc.main.SimplifyArmIdentity.diff8
-rw-r--r--src/test/mir-opt/match_false_edges/rustc.full_tested_match.PromoteTemps.after.mir4
-rw-r--r--src/test/mir-opt/retag/rustc.main.SimplifyCfg-elaborate-drops.after.mir4
-rw-r--r--src/test/ui/const-generics/type-dependent/auxiliary/type_dependent_lib.rs36
-rw-r--r--src/test/ui/const-generics/type-dependent/const-arg-in-const-arg.rs26
-rw-r--r--src/test/ui/const-generics/type-dependent/issue-61936.rs49
-rw-r--r--src/test/ui/const-generics/type-dependent/issue-63695.rs17
-rw-r--r--src/test/ui/const-generics/type-dependent/issue-69816.rs20
-rw-r--r--src/test/ui/const-generics/type-dependent/issue-70507.rs47
-rw-r--r--src/test/ui/const-generics/type-dependent/issue-71382.rs24
-rw-r--r--src/test/ui/const-generics/type-dependent/issue-71382.stderr17
-rw-r--r--src/test/ui/const-generics/type-dependent/non-local.rs24
-rw-r--r--src/test/ui/const-generics/type-dependent/qpath.rs12
-rw-r--r--src/test/ui/const-generics/type-dependent/simple.rs12
-rw-r--r--src/test/ui/const-generics/type-dependent/type-mismatch.rs12
-rw-r--r--src/test/ui/const-generics/type-dependent/type-mismatch.stderr23
-rw-r--r--src/test/ui/const-generics/unknown_adt.rs7
-rw-r--r--src/test/ui/const-generics/unknown_adt.stderr9
-rw-r--r--src/tools/clippy/clippy_lints/src/consts.rs2
101 files changed, 1547 insertions, 622 deletions
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index e0910c693b1..3287e7b856a 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -248,9 +248,9 @@ fn exported_symbols_provider_local(
             }
 
             match *mono_item {
-                MonoItem::Fn(Instance { def: InstanceDef::Item(def_id), substs }) => {
+                MonoItem::Fn(Instance { def: InstanceDef::Item(def), substs }) => {
                     if substs.non_erasable_generics().next().is_some() {
-                        let symbol = ExportedSymbol::Generic(def_id, substs);
+                        let symbol = ExportedSymbol::Generic(def.did, substs);
                         symbols.push((symbol, SymbolExportLevel::Rust));
                     }
                 }
diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs
index 11ec62f96ed..4943e279c7e 100644
--- a/src/librustc_codegen_ssa/mir/constant.rs
+++ b/src/librustc_codegen_ssa/mir/constant.rs
@@ -25,10 +25,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         constant: &mir::Constant<'tcx>,
     ) -> Result<ConstValue<'tcx>, ErrorHandled> {
         match self.monomorphize(&constant.literal).val {
-            ty::ConstKind::Unevaluated(def_id, substs, promoted) => self
+            ty::ConstKind::Unevaluated(def, substs, promoted) => self
                 .cx
                 .tcx()
-                .const_eval_resolve(ty::ParamEnv::reveal_all(), def_id, substs, promoted, None)
+                .const_eval_resolve(ty::ParamEnv::reveal_all(), def, substs, promoted, None)
                 .map_err(|err| {
                     if promoted.is_none() {
                         self.cx
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index ddc1def6e93..0f558f59a12 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -64,8 +64,7 @@ const BASE_IMPL: &[&str] =
 
 /// DepNodes for mir_built/Optimized, which is relevant in "executable"
 /// code, i.e., functions+methods
-const BASE_MIR: &[&str] =
-    &[label_strs::optimized_mir, label_strs::promoted_mir, label_strs::mir_built];
+const BASE_MIR: &[&str] = &[label_strs::optimized_mir, label_strs::promoted_mir];
 
 /// Struct, Enum and Union DepNodes
 ///
@@ -376,7 +375,7 @@ impl DirtyCleanVisitor<'tcx> {
         let def_path_hash = self.tcx.def_path_hash(def_id);
         labels.iter().map(move |label| match DepNode::from_label_string(label, def_path_hash) {
             Ok(dep_node) => dep_node,
-            Err(()) => unreachable!(),
+            Err(()) => unreachable!("label: {}", label),
         })
     }
 
diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs
index 27da514a17f..00503a69928 100644
--- a/src/librustc_infer/infer/mod.rs
+++ b/src/librustc_infer/infer/mod.rs
@@ -1536,7 +1536,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn const_eval_resolve(
         &self,
         param_env: ty::ParamEnv<'tcx>,
-        def_id: DefId,
+        def: ty::WithOptConstParam<DefId>,
         substs: SubstsRef<'tcx>,
         promoted: Option<mir::Promoted>,
         span: Option<Span>,
@@ -1547,7 +1547,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         let (param_env, substs) = canonical.value;
         // The return value is the evaluated value which doesn't contain any reference to inference
         // variables, thus we don't need to substitute back the original values.
-        self.tcx.const_eval_resolve(param_env, def_id, substs, promoted, span)
+        self.tcx.const_eval_resolve(param_env, def, substs, promoted, span)
     }
 
     /// If `typ` is a type variable of some kind, resolve it one level
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 6d85c2f1825..533d0a6d383 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -891,7 +891,8 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
             mir::transform::check_unsafety::check_unsafety(tcx, def_id);
 
             if tcx.hir().body_const_context(def_id).is_some() {
-                tcx.ensure().mir_drops_elaborated_and_const_checked(def_id);
+                tcx.ensure()
+                    .mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(def_id));
             }
         }
     });
diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
index 201a32d3877..be153758a2a 100644
--- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
+++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
@@ -111,8 +111,8 @@ provide! { <'tcx> tcx, def_id, other, cdata,
             bug!("coerce_unsized_info: `{:?}` is missing its info", def_id);
         })
     }
-    optimized_mir => { cdata.get_optimized_mir(tcx, def_id.index) }
-    promoted_mir => { cdata.get_promoted_mir(tcx, def_id.index) }
+    optimized_mir => { tcx.arena.alloc(cdata.get_optimized_mir(tcx, def_id.index)) }
+    promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) }
     mir_const_qualif => { cdata.mir_const_qualif(def_id.index) }
     fn_sig => { cdata.fn_sig(def_id.index, tcx) }
     inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) }
diff --git a/src/librustc_middle/arena.rs b/src/librustc_middle/arena.rs
index 4f1889aeb16..c5b66c1b13b 100644
--- a/src/librustc_middle/arena.rs
+++ b/src/librustc_middle/arena.rs
@@ -14,7 +14,37 @@ macro_rules! arena_types {
             [] layouts: rustc_target::abi::Layout, rustc_target::abi::Layout;
             // AdtDef are interned and compared by address
             [] adt_def: rustc_middle::ty::AdtDef, rustc_middle::ty::AdtDef;
+            [] steal_mir:
+                rustc_middle::ty::steal::Steal<rustc_middle::mir::Body<$tcx>>,
+                rustc_middle::ty::steal::Steal<rustc_middle::mir::Body<$tcx>>;
+            [decode] mir: rustc_middle::mir::Body<$tcx>, rustc_middle::mir::Body<'_x>;
+            [] steal_promoted:
+                rustc_middle::ty::steal::Steal<
+                    rustc_index::vec::IndexVec<
+                        rustc_middle::mir::Promoted,
+                        rustc_middle::mir::Body<$tcx>
+                    >
+                >,
+                rustc_middle::ty::steal::Steal<
+                    rustc_index::vec::IndexVec<
+                        rustc_middle::mir::Promoted,
+                        rustc_middle::mir::Body<$tcx>
+                    >
+                >;
+            [decode] promoted:
+                rustc_index::vec::IndexVec<
+                    rustc_middle::mir::Promoted,
+                    rustc_middle::mir::Body<$tcx>
+                >,
+                rustc_index::vec::IndexVec<
+                    rustc_middle::mir::Promoted,
+                    rustc_middle::mir::Body<'_x>
+                >;
             [decode] tables: rustc_middle::ty::TypeckTables<$tcx>, rustc_middle::ty::TypeckTables<'_x>;
+            [decode] borrowck_result:
+                rustc_middle::mir::BorrowCheckResult<$tcx>,
+                rustc_middle::mir::BorrowCheckResult<'_x>;
+            [decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult, rustc_middle::mir::UnsafetyCheckResult;
             [] const_allocs: rustc_middle::mir::interpret::Allocation, rustc_middle::mir::interpret::Allocation;
             // Required for the incremental on-disk cache
             [few, decode] mir_keys: rustc_hir::def_id::DefIdSet, rustc_hir::def_id::DefIdSet;
diff --git a/src/librustc_middle/mir/interpret/queries.rs b/src/librustc_middle/mir/interpret/queries.rs
index a7953f0f900..d7c0be05859 100644
--- a/src/librustc_middle/mir/interpret/queries.rs
+++ b/src/librustc_middle/mir/interpret/queries.rs
@@ -34,12 +34,12 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn const_eval_resolve(
         self,
         param_env: ty::ParamEnv<'tcx>,
-        def_id: DefId,
+        def: ty::WithOptConstParam<DefId>,
         substs: SubstsRef<'tcx>,
         promoted: Option<mir::Promoted>,
         span: Option<Span>,
     ) -> ConstEvalResult<'tcx> {
-        match ty::Instance::resolve(self, param_env, def_id, substs) {
+        match ty::Instance::resolve_opt_const_arg(self, param_env, def, substs) {
             Ok(Some(instance)) => {
                 let cid = GlobalId { instance, promoted };
                 self.const_eval_global_id(param_env, cid, span)
diff --git a/src/librustc_middle/mir/mono.rs b/src/librustc_middle/mir/mono.rs
index 474552d68b9..d22bde2ff8b 100644
--- a/src/librustc_middle/mir/mono.rs
+++ b/src/librustc_middle/mir/mono.rs
@@ -346,8 +346,8 @@ impl<'tcx> CodegenUnit<'tcx> {
                             // instances into account. The others don't matter for
                             // the codegen tests and can even make item order
                             // unstable.
-                            InstanceDef::Item(def_id) => {
-                                def_id.as_local().map(|def_id| tcx.hir().as_local_hir_id(def_id))
+                            InstanceDef::Item(def) => {
+                                def.did.as_local().map(|def_id| tcx.hir().as_local_hir_id(def_id))
                             }
                             InstanceDef::VtableShim(..)
                             | InstanceDef::ReifyShim(..)
diff --git a/src/librustc_middle/mir/query.rs b/src/librustc_middle/mir/query.rs
index 8dddaf40c82..560a8421c17 100644
--- a/src/librustc_middle/mir/query.rs
+++ b/src/librustc_middle/mir/query.rs
@@ -1,10 +1,11 @@
 //! Values computed by queries that use MIR.
 
-use crate::ty::{self, Ty};
+use crate::mir::{Body, Promoted};
+use crate::ty::{self, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_index::bit_set::BitMatrix;
 use rustc_index::vec::IndexVec;
 use rustc_span::{Span, Symbol};
@@ -323,3 +324,38 @@ pub struct CoverageInfo {
     /// The total number of coverage region counters added to the MIR `Body`.
     pub num_counters: u32,
 }
+
+impl<'tcx> TyCtxt<'tcx> {
+    pub fn mir_borrowck_opt_const_arg(
+        self,
+        def: ty::WithOptConstParam<LocalDefId>,
+    ) -> &'tcx BorrowCheckResult<'tcx> {
+        if let Some(param_did) = def.const_param_did {
+            self.mir_borrowck_const_arg((def.did, param_did))
+        } else {
+            self.mir_borrowck(def.did)
+        }
+    }
+
+    pub fn mir_const_qualif_opt_const_arg(
+        self,
+        def: ty::WithOptConstParam<LocalDefId>,
+    ) -> ConstQualifs {
+        if let Some(param_did) = def.const_param_did {
+            self.mir_const_qualif_const_arg((def.did, param_did))
+        } else {
+            self.mir_const_qualif(def.did)
+        }
+    }
+
+    pub fn promoted_mir_of_opt_const_arg(
+        self,
+        def: ty::WithOptConstParam<DefId>,
+    ) -> &'tcx IndexVec<Promoted, Body<'tcx>> {
+        if let Some((did, param_did)) = def.as_const_arg() {
+            self.promoted_mir_of_const_arg((did, param_did))
+        } else {
+            self.promoted_mir(def.did)
+        }
+    }
+}
diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs
index 942fba478f1..40ff25cf3b1 100644
--- a/src/librustc_middle/query/mod.rs
+++ b/src/librustc_middle/query/mod.rs
@@ -89,6 +89,25 @@ rustc_queries! {
             desc { |tcx| "HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) }
         }
 
+        /// Computes the `DefId` of the corresponding const parameter in case the `key` is a
+        /// const argument and returns `None` otherwise.
+        ///
+        /// ```rust
+        /// let a = foo::<7>();
+        /// //            ^ Calling `opt_const_param_of` for this argument,
+        ///
+        /// fn foo<const N: usize>()
+        /// //           ^ returns this `DefId`.
+        ///
+        /// fn bar() {
+        /// // ^ While calling `opt_const_param_of` for other bodies returns `None`.
+        /// }
+        /// ```
+        query opt_const_param_of(key: LocalDefId) -> Option<DefId> {
+            desc { |tcx| "computing the optional const parameter of `{}`", tcx.def_path_str(key.to_def_id()) }
+            // FIXME(#74113): consider storing this query on disk.
+        }
+
         /// Records the type of every item.
         query type_of(key: DefId) -> Ty<'tcx> {
             desc { |tcx| "computing type of `{}`", tcx.def_path_str(key) }
@@ -189,47 +208,66 @@ rustc_queries! {
             desc { |tcx| "const checking `{}`", tcx.def_path_str(key) }
             cache_on_disk_if { key.is_local() }
         }
+        query mir_const_qualif_const_arg(
+            key: (LocalDefId, DefId)
+        ) -> mir::ConstQualifs {
+            desc {
+                |tcx| "const checking the const argument `{}`",
+                tcx.def_path_str(key.0.to_def_id())
+            }
+        }
 
         /// Fetch the MIR for a given `DefId` right after it's built - this includes
         /// unreachable code.
-        query mir_built(key: LocalDefId) -> Steal<mir::Body<'tcx>> {
-            storage(ArenaCacheSelector<'tcx>)
-            desc { |tcx| "building MIR for `{}`", tcx.def_path_str(key.to_def_id()) }
+        query mir_built(key: ty::WithOptConstParam<LocalDefId>) -> &'tcx Steal<mir::Body<'tcx>> {
+            desc { |tcx| "building MIR for `{}`", tcx.def_path_str(key.did.to_def_id()) }
         }
 
         /// Fetch the MIR for a given `DefId` up till the point where it is
         /// ready for const qualification.
         ///
         /// See the README for the `mir` module for details.
-        query mir_const(key: DefId) -> Steal<mir::Body<'tcx>> {
-            desc { |tcx| "processing MIR for `{}`", tcx.def_path_str(key)  }
-            storage(ArenaCacheSelector<'tcx>)
+        query mir_const(key: ty::WithOptConstParam<LocalDefId>) -> &'tcx Steal<mir::Body<'tcx>> {
+            desc {
+                |tcx| "processing MIR for {}`{}`",
+                if key.const_param_did.is_some() { "the const argument " } else { "" },
+                tcx.def_path_str(key.did.to_def_id()),
+            }
             no_hash
         }
 
-        query mir_drops_elaborated_and_const_checked(key: LocalDefId) -> Steal<mir::Body<'tcx>> {
-            storage(ArenaCacheSelector<'tcx>)
+        query mir_drops_elaborated_and_const_checked(
+            key: ty::WithOptConstParam<LocalDefId>
+        ) -> &'tcx Steal<mir::Body<'tcx>> {
             no_hash
-            desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key.to_def_id()) }
+            desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key.did.to_def_id()) }
         }
 
-        query mir_validated(key: LocalDefId) ->
+        query mir_validated(key: ty::WithOptConstParam<LocalDefId>) ->
             (
-                Steal<mir::Body<'tcx>>,
-                Steal<IndexVec<mir::Promoted, mir::Body<'tcx>>>
+                &'tcx Steal<mir::Body<'tcx>>,
+                &'tcx Steal<IndexVec<mir::Promoted, mir::Body<'tcx>>>
             ) {
-            storage(ArenaCacheSelector<'tcx>)
             no_hash
-            desc { |tcx| "processing `{}`", tcx.def_path_str(key.to_def_id()) }
+            desc {
+                |tcx| "processing {}`{}`",
+                if key.const_param_did.is_some() { "the const argument " } else { "" },
+                tcx.def_path_str(key.did.to_def_id()),
+            }
         }
 
         /// MIR after our optimization passes have run. This is MIR that is ready
         /// for codegen. This is also the only query that can fetch non-local MIR, at present.
-        query optimized_mir(key: DefId) -> mir::Body<'tcx> {
+        query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> {
             desc { |tcx| "optimizing MIR for `{}`", tcx.def_path_str(key) }
-            storage(ArenaCacheSelector<'tcx>)
             cache_on_disk_if { key.is_local() }
         }
+        query optimized_mir_of_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::Body<'tcx> {
+            desc {
+                |tcx| "optimizing MIR for the const argument `{}`",
+                tcx.def_path_str(key.0.to_def_id())
+            }
+        }
 
         /// Returns coverage summary info for a function, after executing the `InstrumentCoverage`
         /// MIR pass (assuming the -Zinstrument-coverage option is enabled).
@@ -239,11 +277,18 @@ rustc_queries! {
             cache_on_disk_if { key.is_local() }
         }
 
-        query promoted_mir(key: DefId) -> IndexVec<mir::Promoted, mir::Body<'tcx>> {
+        query promoted_mir(key: DefId) -> &'tcx IndexVec<mir::Promoted, mir::Body<'tcx>> {
             desc { |tcx| "optimizing promoted MIR for `{}`", tcx.def_path_str(key) }
-            storage(ArenaCacheSelector<'tcx>)
             cache_on_disk_if { key.is_local() }
         }
+        query promoted_mir_of_const_arg(
+            key: (LocalDefId, DefId)
+        ) -> &'tcx IndexVec<mir::Promoted, mir::Body<'tcx>> {
+            desc {
+                |tcx| "optimizing promoted MIR for the const argument `{}`",
+                tcx.def_path_str(key.0.to_def_id()),
+            }
+        }
     }
 
     TypeChecking {
@@ -451,11 +496,16 @@ rustc_queries! {
     }
 
     TypeChecking {
-        /// The result of unsafety-checking this `DefId`.
-        query unsafety_check_result(key: LocalDefId) -> mir::UnsafetyCheckResult {
+        /// The result of unsafety-checking this `LocalDefId`.
+        query unsafety_check_result(key: LocalDefId) -> &'tcx mir::UnsafetyCheckResult {
             desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key.to_def_id()) }
             cache_on_disk_if { true }
-            storage(ArenaCacheSelector<'tcx>)
+        }
+        query unsafety_check_result_for_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::UnsafetyCheckResult {
+            desc {
+                |tcx| "unsafety-checking the const argument `{}`",
+                tcx.def_path_str(key.0.to_def_id())
+            }
         }
 
         /// HACK: when evaluated, this reports a "unsafe derive on repr(packed)" error.
@@ -537,6 +587,14 @@ rustc_queries! {
             desc { |tcx| "type-checking `{}`", tcx.def_path_str(key.to_def_id()) }
             cache_on_disk_if { true }
         }
+        query typeck_tables_of_const_arg(
+            key: (LocalDefId, DefId)
+        ) -> &'tcx ty::TypeckTables<'tcx> {
+            desc {
+                |tcx| "type-checking the const argument `{}`",
+                tcx.def_path_str(key.0.to_def_id()),
+            }
+        }
         query diagnostic_only_typeck_tables_of(key: LocalDefId) -> &'tcx ty::TypeckTables<'tcx> {
             desc { |tcx| "type-checking `{}`", tcx.def_path_str(key.to_def_id()) }
             cache_on_disk_if { true }
@@ -570,14 +628,19 @@ rustc_queries! {
     BorrowChecking {
         /// Borrow-checks the function body. If this is a closure, returns
         /// additional requirements that the closure's creator must verify.
-        query mir_borrowck(key: LocalDefId) -> mir::BorrowCheckResult<'tcx> {
-            storage(ArenaCacheSelector<'tcx>)
+        query mir_borrowck(key: LocalDefId) -> &'tcx mir::BorrowCheckResult<'tcx> {
             desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key.to_def_id()) }
             cache_on_disk_if(tcx, opt_result) {
                 tcx.is_closure(key.to_def_id())
                     || opt_result.map_or(false, |r| !r.concrete_opaque_types.is_empty())
             }
         }
+        query mir_borrowck_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::BorrowCheckResult<'tcx> {
+            desc {
+                |tcx| "borrow-checking the const argument`{}`",
+                tcx.def_path_str(key.0.to_def_id())
+            }
+        }
     }
 
     TypeChecking {
@@ -1444,5 +1507,14 @@ rustc_queries! {
         ) -> Result<Option<ty::Instance<'tcx>>, ErrorReported> {
             desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) }
         }
+
+        query resolve_instance_of_const_arg(
+            key: ty::ParamEnvAnd<'tcx, (LocalDefId, DefId, SubstsRef<'tcx>)>
+        ) -> Result<Option<ty::Instance<'tcx>>, ErrorReported> {
+            desc {
+                "resolving instance of the const argument `{}`",
+                ty::Instance::new(key.value.0.to_def_id(), key.value.2),
+            }
+        }
     }
 }
diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs
index c4a5bc30222..bb5dd53a7e6 100644
--- a/src/librustc_middle/ty/context.rs
+++ b/src/librustc_middle/ty/context.rs
@@ -980,15 +980,26 @@ pub struct GlobalCtxt<'tcx> {
 }
 
 impl<'tcx> TyCtxt<'tcx> {
-    pub fn alloc_steal_mir(self, mir: Body<'tcx>) -> Steal<Body<'tcx>> {
-        Steal::new(mir)
+    pub fn typeck_tables_of_opt_const_arg(
+        self,
+        def: ty::WithOptConstParam<LocalDefId>,
+    ) -> &'tcx TypeckTables<'tcx> {
+        if let Some(param_did) = def.const_param_did {
+            self.typeck_tables_of_const_arg((def.did, param_did))
+        } else {
+            self.typeck_tables_of(def.did)
+        }
+    }
+
+    pub fn alloc_steal_mir(self, mir: Body<'tcx>) -> &'tcx Steal<Body<'tcx>> {
+        self.arena.alloc(Steal::new(mir))
     }
 
     pub fn alloc_steal_promoted(
         self,
         promoted: IndexVec<Promoted, Body<'tcx>>,
-    ) -> Steal<IndexVec<Promoted, Body<'tcx>>> {
-        Steal::new(promoted)
+    ) -> &'tcx Steal<IndexVec<Promoted, Body<'tcx>>> {
+        self.arena.alloc(Steal::new(promoted))
     }
 
     pub fn alloc_adt_def(
diff --git a/src/librustc_middle/ty/instance.rs b/src/librustc_middle/ty/instance.rs
index d628d6783d5..f627d05d3e9 100644
--- a/src/librustc_middle/ty/instance.rs
+++ b/src/librustc_middle/ty/instance.rs
@@ -29,7 +29,7 @@ pub enum InstanceDef<'tcx> {
     /// - `fn` items
     /// - closures
     /// - generators
-    Item(DefId),
+    Item(ty::WithOptConstParam<DefId>),
 
     /// An intrinsic `fn` item (with `"rust-intrinsic"` or `"platform-intrinsic"` ABI).
     ///
@@ -160,8 +160,8 @@ impl<'tcx> Instance<'tcx> {
         self.substs.non_erasable_generics().next()?;
 
         match self.def {
-            InstanceDef::Item(def_id) => tcx
-                .upstream_monomorphizations_for(def_id)
+            InstanceDef::Item(def) => tcx
+                .upstream_monomorphizations_for(def.did)
                 .and_then(|monos| monos.get(&self.substs).cloned()),
             InstanceDef::DropGlue(_, Some(_)) => tcx.upstream_drop_glue_for(self.substs),
             _ => None,
@@ -171,10 +171,10 @@ impl<'tcx> Instance<'tcx> {
 
 impl<'tcx> InstanceDef<'tcx> {
     #[inline]
-    pub fn def_id(&self) -> DefId {
-        match *self {
-            InstanceDef::Item(def_id)
-            | InstanceDef::VtableShim(def_id)
+    pub fn def_id(self) -> DefId {
+        match self {
+            InstanceDef::Item(def) => def.did,
+            InstanceDef::VtableShim(def_id)
             | InstanceDef::ReifyShim(def_id)
             | InstanceDef::FnPtrShim(def_id, _)
             | InstanceDef::Virtual(def_id, _)
@@ -186,6 +186,21 @@ impl<'tcx> InstanceDef<'tcx> {
     }
 
     #[inline]
+    pub fn with_opt_param(self) -> ty::WithOptConstParam<DefId> {
+        match self {
+            InstanceDef::Item(def) => def,
+            InstanceDef::VtableShim(def_id)
+            | InstanceDef::ReifyShim(def_id)
+            | InstanceDef::FnPtrShim(def_id, _)
+            | InstanceDef::Virtual(def_id, _)
+            | InstanceDef::Intrinsic(def_id)
+            | InstanceDef::ClosureOnceShim { call_once: def_id }
+            | InstanceDef::DropGlue(def_id, _)
+            | InstanceDef::CloneShim(def_id, _) => ty::WithOptConstParam::unknown(def_id),
+        }
+    }
+
+    #[inline]
     pub fn attrs(&self, tcx: TyCtxt<'tcx>) -> ty::Attributes<'tcx> {
         tcx.get_attrs(self.def_id())
     }
@@ -198,7 +213,7 @@ impl<'tcx> InstanceDef<'tcx> {
     pub fn requires_inline(&self, tcx: TyCtxt<'tcx>) -> bool {
         use rustc_hir::definitions::DefPathData;
         let def_id = match *self {
-            ty::InstanceDef::Item(def_id) => def_id,
+            ty::InstanceDef::Item(def) => def.did,
             ty::InstanceDef::DropGlue(_, Some(_)) => return false,
             _ => return true,
         };
@@ -244,8 +259,8 @@ impl<'tcx> InstanceDef<'tcx> {
 
     pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
         match *self {
-            InstanceDef::Item(def_id) => {
-                tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
+            InstanceDef::Item(def) => {
+                tcx.codegen_fn_attrs(def.did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
             }
             _ => false,
         }
@@ -283,7 +298,7 @@ impl<'tcx> Instance<'tcx> {
             def_id,
             substs
         );
-        Instance { def: InstanceDef::Item(def_id), substs }
+        Instance { def: InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)), substs }
     }
 
     pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
@@ -324,6 +339,21 @@ impl<'tcx> Instance<'tcx> {
         def_id: DefId,
         substs: SubstsRef<'tcx>,
     ) -> Result<Option<Instance<'tcx>>, ErrorReported> {
+        Instance::resolve_opt_const_arg(
+            tcx,
+            param_env,
+            ty::WithOptConstParam::unknown(def_id),
+            substs,
+        )
+    }
+
+    // This should be kept up to date with `resolve`.
+    pub fn resolve_opt_const_arg(
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        def: ty::WithOptConstParam<DefId>,
+        substs: SubstsRef<'tcx>,
+    ) -> Result<Option<Instance<'tcx>>, ErrorReported> {
         // All regions in the result of this query are erased, so it's
         // fine to erase all of the input regions.
 
@@ -333,7 +363,13 @@ impl<'tcx> Instance<'tcx> {
         let substs = tcx.erase_regions(&substs);
 
         // FIXME(eddyb) should this always use `param_env.with_reveal_all()`?
-        tcx.resolve_instance(tcx.erase_regions(&param_env.and((def_id, substs))))
+        if let Some((did, param_did)) = def.as_const_arg() {
+            tcx.resolve_instance_of_const_arg(
+                tcx.erase_regions(&param_env.and((did, param_did, substs))),
+            )
+        } else {
+            tcx.resolve_instance(tcx.erase_regions(&param_env.and((def.did, substs))))
+        }
     }
 
     pub fn resolve_for_fn_ptr(
@@ -345,9 +381,9 @@ impl<'tcx> Instance<'tcx> {
         debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
         Instance::resolve(tcx, param_env, def_id, substs).ok().flatten().map(|mut resolved| {
             match resolved.def {
-                InstanceDef::Item(def_id) if resolved.def.requires_caller_location(tcx) => {
+                InstanceDef::Item(def) if resolved.def.requires_caller_location(tcx) => {
                     debug!(" => fn pointer created for function with #[track_caller]");
-                    resolved.def = InstanceDef::ReifyShim(def_id);
+                    resolved.def = InstanceDef::ReifyShim(def.did);
                 }
                 InstanceDef::Virtual(def_id, _) => {
                     debug!(" => fn pointer created for virtual call");
diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs
index f352f3a397d..fe2a60401b4 100644
--- a/src/librustc_middle/ty/mod.rs
+++ b/src/librustc_middle/ty/mod.rs
@@ -1,5 +1,4 @@
 // ignore-tidy-filelength
-
 pub use self::fold::{TypeFoldable, TypeVisitor};
 pub use self::AssocItemContainer::*;
 pub use self::BorrowKind::*;
@@ -1101,7 +1100,7 @@ pub enum PredicateKind<'tcx> {
     Subtype(PolySubtypePredicate<'tcx>),
 
     /// Constant initializer must evaluate successfully.
-    ConstEvaluatable(DefId, SubstsRef<'tcx>),
+    ConstEvaluatable(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
 
     /// Constants must be equal. The first component is the const that is expected.
     ConstEquate(&'tcx Const<'tcx>, &'tcx Const<'tcx>),
@@ -1572,6 +1571,95 @@ pub type PlaceholderType = Placeholder<BoundVar>;
 
 pub type PlaceholderConst = Placeholder<BoundVar>;
 
+/// A `DefId` which is potentially bundled with its corresponding generic parameter
+/// in case `did` is a const argument.
+///
+/// This is used to prevent cycle errors during typeck
+/// as `type_of(const_arg)` depends on `typeck_tables_of(owning_body)`
+/// which once again requires the type of its generic arguments.
+///
+/// Luckily we only need to deal with const arguments once we
+/// know their corresponding parameters. We (ab)use this by
+/// calling `type_of(param_did)` for these arguments.
+///
+/// ```rust
+/// #![feature(const_generics)]
+///
+/// struct A;
+/// impl A {
+///     fn foo<const N: usize>(&self) -> usize { N }
+/// }
+/// struct B;
+/// impl B {
+///     fn foo<const N: u8>(&self) -> usize { 42 }
+/// }
+///
+/// fn main() {
+///     let a = A;
+///     a.foo::<7>();
+/// }
+/// ```
+#[derive(Copy, Clone, Debug, TypeFoldable, Lift, RustcEncodable, RustcDecodable)]
+#[derive(PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Hash, HashStable)]
+pub struct WithOptConstParam<T> {
+    pub did: T,
+    /// The `DefId` of the corresponding generic paramter in case `did` is
+    /// a const argument.
+    ///
+    /// Note that even if `did` is a const argument, this may still be `None`.
+    /// All queries taking `WithOptConstParam` start by calling `tcx.opt_const_param_of(def.did)`
+    /// to potentially update `param_did` in case it `None`.
+    pub const_param_did: Option<DefId>,
+}
+
+impl<T> WithOptConstParam<T> {
+    /// Creates a new `WithOptConstParam` setting `const_param_did` to `None`.
+    pub fn unknown(did: T) -> WithOptConstParam<T> {
+        WithOptConstParam { did, const_param_did: None }
+    }
+}
+
+impl WithOptConstParam<LocalDefId> {
+    pub fn to_global(self) -> WithOptConstParam<DefId> {
+        WithOptConstParam { did: self.did.to_def_id(), const_param_did: self.const_param_did }
+    }
+
+    pub fn def_id_for_type_of(self) -> DefId {
+        if let Some(did) = self.const_param_did { did } else { self.did.to_def_id() }
+    }
+}
+
+impl WithOptConstParam<DefId> {
+    pub fn as_local(self) -> Option<WithOptConstParam<LocalDefId>> {
+        self.did
+            .as_local()
+            .map(|did| WithOptConstParam { did, const_param_did: self.const_param_did })
+    }
+
+    pub fn as_const_arg(self) -> Option<(LocalDefId, DefId)> {
+        if let Some(param_did) = self.const_param_did {
+            if let Some(did) = self.did.as_local() {
+                return Some((did, param_did));
+            }
+        }
+
+        None
+    }
+
+    pub fn expect_local(self) -> WithOptConstParam<LocalDefId> {
+        self.as_local().unwrap()
+    }
+
+    pub fn is_local(self) -> bool {
+        self.did.is_local()
+    }
+
+    pub fn def_id_for_type_of(self) -> DefId {
+        self.const_param_did.unwrap_or(self.did)
+    }
+}
+
 /// When type checking, we use the `ParamEnv` to track
 /// details about the set of where-clauses that are in scope at this
 /// particular point.
@@ -2843,7 +2931,13 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair.
     pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
         match instance {
-            ty::InstanceDef::Item(did) => self.optimized_mir(did),
+            ty::InstanceDef::Item(def) => {
+                if let Some((did, param_did)) = def.as_const_arg() {
+                    self.optimized_mir_of_const_arg((did, param_did))
+                } else {
+                    self.optimized_mir(def.did)
+                }
+            }
             ty::InstanceDef::VtableShim(..)
             | ty::InstanceDef::ReifyShim(..)
             | ty::InstanceDef::Intrinsic(..)
diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs
index 3809c8d245b..b50d2852c1c 100644
--- a/src/librustc_middle/ty/print/pretty.rs
+++ b/src/librustc_middle/ty/print/pretty.rs
@@ -883,18 +883,18 @@ pub trait PrettyPrinter<'tcx>:
         }
 
         match ct.val {
-            ty::ConstKind::Unevaluated(did, substs, promoted) => {
+            ty::ConstKind::Unevaluated(def, substs, promoted) => {
                 if let Some(promoted) = promoted {
-                    p!(print_value_path(did, substs));
+                    p!(print_value_path(def.did, substs));
                     p!(write("::{:?}", promoted));
                 } else {
-                    match self.tcx().def_kind(did) {
+                    match self.tcx().def_kind(def.did) {
                         DefKind::Static | DefKind::Const | DefKind::AssocConst => {
-                            p!(print_value_path(did, substs))
+                            p!(print_value_path(def.did, substs))
                         }
                         _ => {
-                            if did.is_local() {
-                                let span = self.tcx().def_span(did);
+                            if def.is_local() {
+                                let span = self.tcx().def_span(def.did);
                                 if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span)
                                 {
                                     p!(write("{}", snip))
@@ -2027,9 +2027,9 @@ define_print_and_forward_display! {
                    print_value_path(closure_def_id, &[]),
                    write("` implements the trait `{}`", kind))
             }
-            &ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
+            &ty::PredicateKind::ConstEvaluatable(def, substs) => {
                 p!(write("the constant `"),
-                   print_value_path(def_id, substs),
+                   print_value_path(def.did, substs),
                    write("` can be evaluated"))
             }
             ty::PredicateKind::ConstEquate(c1, c2) => {
diff --git a/src/librustc_middle/ty/query/keys.rs b/src/librustc_middle/ty/query/keys.rs
index 4acf766f033..cb2b7a662cb 100644
--- a/src/librustc_middle/ty/query/keys.rs
+++ b/src/librustc_middle/ty/query/keys.rs
@@ -105,6 +105,17 @@ impl Key for DefId {
     }
 }
 
+impl Key for ty::WithOptConstParam<LocalDefId> {
+    type CacheSelector = DefaultCacheSelector;
+
+    fn query_crate(&self) -> CrateNum {
+        self.did.query_crate()
+    }
+    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+        self.did.default_span(tcx)
+    }
+}
+
 impl Key for (DefId, DefId) {
     type CacheSelector = DefaultCacheSelector;
 
@@ -127,6 +138,17 @@ impl Key for (DefId, LocalDefId) {
     }
 }
 
+impl Key for (LocalDefId, DefId) {
+    type CacheSelector = DefaultCacheSelector;
+
+    fn query_crate(&self) -> CrateNum {
+        LOCAL_CRATE
+    }
+    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+        self.0.default_span(tcx)
+    }
+}
+
 impl Key for (CrateNum, DefId) {
     type CacheSelector = DefaultCacheSelector;
 
@@ -171,6 +193,17 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
     }
 }
 
+impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) {
+    type CacheSelector = DefaultCacheSelector;
+
+    fn query_crate(&self) -> CrateNum {
+        LOCAL_CRATE
+    }
+    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+        self.0.default_span(tcx)
+    }
+}
+
 impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
     type CacheSelector = DefaultCacheSelector;
 
diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs
index 7946a27b4d9..ae2820b460f 100644
--- a/src/librustc_middle/ty/relate.rs
+++ b/src/librustc_middle/ty/relate.rs
@@ -578,12 +578,12 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
 
         // FIXME(const_generics): this is wrong, as it is a projection
         (
-            ty::ConstKind::Unevaluated(a_def_id, a_substs, a_promoted),
-            ty::ConstKind::Unevaluated(b_def_id, b_substs, b_promoted),
-        ) if a_def_id == b_def_id && a_promoted == b_promoted => {
+            ty::ConstKind::Unevaluated(a_def, a_substs, a_promoted),
+            ty::ConstKind::Unevaluated(b_def, b_substs, b_promoted),
+        ) if a_def == b_def && a_promoted == b_promoted => {
             let substs =
                 relation.relate_with_variance(ty::Variance::Invariant, a_substs, b_substs)?;
-            Ok(ty::ConstKind::Unevaluated(a_def_id, substs, a_promoted))
+            Ok(ty::ConstKind::Unevaluated(a_def, substs, a_promoted))
         }
         _ => Err(TypeError::ConstMismatch(expected_found(relation, a, b))),
     };
diff --git a/src/librustc_middle/ty/structural_impls.rs b/src/librustc_middle/ty/structural_impls.rs
index 159af277d24..f04bfe648fb 100644
--- a/src/librustc_middle/ty/structural_impls.rs
+++ b/src/librustc_middle/ty/structural_impls.rs
@@ -272,6 +272,7 @@ CloneTypeFoldableAndLiftImpls! {
     ::rustc_span::symbol::Symbol,
     ::rustc_hir::def::Res,
     ::rustc_hir::def_id::DefId,
+    ::rustc_hir::def_id::LocalDefId,
     ::rustc_hir::LlvmInlineAsmInner,
     ::rustc_hir::MatchSource,
     ::rustc_hir::Mutability,
@@ -719,6 +720,18 @@ impl<'tcx, T: TypeFoldable<'tcx>, U: TypeFoldable<'tcx>> TypeFoldable<'tcx> for
     }
 }
 
+impl<'tcx, A: TypeFoldable<'tcx>, B: TypeFoldable<'tcx>, C: TypeFoldable<'tcx>> TypeFoldable<'tcx>
+    for (A, B, C)
+{
+    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> (A, B, C) {
+        (self.0.fold_with(folder), self.1.fold_with(folder), self.2.fold_with(folder))
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.0.visit_with(visitor) || self.1.visit_with(visitor) || self.2.visit_with(visitor)
+    }
+}
+
 EnumTypeFoldableImpl! {
     impl<'tcx, T> TypeFoldable<'tcx> for Option<T> {
         (Some)(a),
@@ -838,7 +851,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
         Self {
             substs: self.substs.fold_with(folder),
             def: match self.def {
-                Item(did) => Item(did.fold_with(folder)),
+                Item(def) => Item(def.fold_with(folder)),
                 VtableShim(did) => VtableShim(did.fold_with(folder)),
                 ReifyShim(did) => ReifyShim(did.fold_with(folder)),
                 Intrinsic(did) => Intrinsic(did.fold_with(folder)),
@@ -857,7 +870,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
         use crate::ty::InstanceDef::*;
         self.substs.visit_with(visitor)
             || match self.def {
-                Item(did) | VtableShim(did) | ReifyShim(did) | Intrinsic(did) | Virtual(did, _) => {
+                Item(def) => def.visit_with(visitor),
+                VtableShim(did) | ReifyShim(did) | Intrinsic(did) | Virtual(did, _) => {
                     did.visit_with(visitor)
                 }
                 FnPtrShim(did, ty) | CloneShim(did, ty) => {
diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs
index c7683cefd82..3104d2ee36a 100644
--- a/src/librustc_middle/ty/sty.rs
+++ b/src/librustc_middle/ty/sty.rs
@@ -2210,21 +2210,28 @@ impl<'tcx> Const<'tcx> {
     /// Literals and const generic parameters are eagerly converted to a constant, everything else
     /// becomes `Unevaluated`.
     pub fn from_anon_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx Self {
-        debug!("Const::from_anon_const(id={:?})", def_id);
+        Self::from_opt_const_arg_anon_const(tcx, ty::WithOptConstParam::unknown(def_id))
+    }
+
+    pub fn from_opt_const_arg_anon_const(
+        tcx: TyCtxt<'tcx>,
+        def: ty::WithOptConstParam<LocalDefId>,
+    ) -> &'tcx Self {
+        debug!("Const::from_anon_const(def={:?})", def);
 
-        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+        let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
 
         let body_id = match tcx.hir().get(hir_id) {
             hir::Node::AnonConst(ac) => ac.body,
             _ => span_bug!(
-                tcx.def_span(def_id.to_def_id()),
+                tcx.def_span(def.did.to_def_id()),
                 "from_anon_const can only process anonymous constants"
             ),
         };
 
         let expr = &tcx.hir().body(body_id).value;
 
-        let ty = tcx.type_of(def_id.to_def_id());
+        let ty = tcx.type_of(def.def_id_for_type_of());
 
         let lit_input = match expr.kind {
             hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
@@ -2271,8 +2278,8 @@ impl<'tcx> Const<'tcx> {
                 ty::ConstKind::Param(ty::ParamConst::new(index, name))
             }
             _ => ty::ConstKind::Unevaluated(
-                def_id.to_def_id(),
-                InternalSubsts::identity_for_item(tcx, def_id.to_def_id()),
+                def.to_global(),
+                InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
                 None,
             ),
         };
@@ -2340,7 +2347,7 @@ impl<'tcx> Const<'tcx> {
     /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
     /// unevaluated constant.
     pub fn eval(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> &Const<'tcx> {
-        if let ConstKind::Unevaluated(did, substs, promoted) = self.val {
+        if let ConstKind::Unevaluated(def, substs, promoted) = self.val {
             use crate::mir::interpret::ErrorHandled;
 
             let param_env_and_substs = param_env.with_reveal_all().and(substs);
@@ -2356,7 +2363,7 @@ impl<'tcx> Const<'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_substs = if param_env_and_substs.needs_infer() {
-                tcx.param_env(did).and(InternalSubsts::identity_for_item(tcx, did))
+                tcx.param_env(def.did).and(InternalSubsts::identity_for_item(tcx, def.did))
             } else {
                 param_env_and_substs
             };
@@ -2366,7 +2373,7 @@ impl<'tcx> Const<'tcx> {
             let (param_env, substs) = param_env_and_substs.into_parts();
             // try to resolve e.g. associated constants to their definition on an impl, and then
             // evaluate the const.
-            match tcx.const_eval_resolve(param_env, did, substs, promoted, None) {
+            match tcx.const_eval_resolve(param_env, def, substs, promoted, None) {
                 // NOTE(eddyb) `val` contains no lifetimes/types/consts,
                 // and we use the original type, so nothing from `substs`
                 // (which may be identity substs, see above),
@@ -2426,7 +2433,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(DefId, SubstsRef<'tcx>, Option<Promoted>),
+    Unevaluated(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>, Option<Promoted>),
 
     /// Used to hold computed value.
     Value(ConstValue<'tcx>),
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index beb5f1fe924..d8d988717b8 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -17,7 +17,7 @@ use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind
 use rustc_middle::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
 use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, RegionVid, TyCtxt};
+use rustc_middle::ty::{self, InstanceDef, RegionVid, TyCtxt};
 use rustc_session::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT, UNUSED_MUT};
 use rustc_span::{Span, Symbol, DUMMY_SP};
 
@@ -87,34 +87,49 @@ crate struct Upvar {
 const DEREF_PROJECTION: &[PlaceElem<'_>; 1] = &[ProjectionElem::Deref];
 
 pub fn provide(providers: &mut Providers) {
-    *providers = Providers { mir_borrowck, ..*providers };
+    *providers = Providers {
+        mir_borrowck: |tcx, did| mir_borrowck(tcx, ty::WithOptConstParam::unknown(did)),
+        mir_borrowck_const_arg: |tcx, (did, param_did)| {
+            mir_borrowck(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
+        },
+        ..*providers
+    };
 }
 
-fn mir_borrowck(tcx: TyCtxt<'_>, def_id: LocalDefId) -> BorrowCheckResult<'_> {
-    let (input_body, promoted) = tcx.mir_validated(def_id);
-    debug!("run query mir_borrowck: {}", tcx.def_path_str(def_id.to_def_id()));
+fn mir_borrowck<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def: ty::WithOptConstParam<LocalDefId>,
+) -> &'tcx BorrowCheckResult<'tcx> {
+    if def.const_param_did.is_none() {
+        if let Some(param_did) = tcx.opt_const_param_of(def.did) {
+            return tcx.mir_borrowck_const_arg((def.did, param_did));
+        }
+    }
+
+    let (input_body, promoted) = tcx.mir_validated(def);
+    debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
 
     let opt_closure_req = tcx.infer_ctxt().enter(|infcx| {
         let input_body: &Body<'_> = &input_body.borrow();
         let promoted: &IndexVec<_, _> = &promoted.borrow();
-        do_mir_borrowck(&infcx, input_body, promoted, def_id)
+        do_mir_borrowck(&infcx, input_body, promoted, def)
     });
     debug!("mir_borrowck done");
 
-    opt_closure_req
+    tcx.arena.alloc(opt_closure_req)
 }
 
 fn do_mir_borrowck<'a, 'tcx>(
     infcx: &InferCtxt<'a, 'tcx>,
     input_body: &Body<'tcx>,
     input_promoted: &IndexVec<Promoted, Body<'tcx>>,
-    def_id: LocalDefId,
+    def: ty::WithOptConstParam<LocalDefId>,
 ) -> BorrowCheckResult<'tcx> {
-    debug!("do_mir_borrowck(def_id = {:?})", def_id);
+    debug!("do_mir_borrowck(def = {:?})", def);
 
     let tcx = infcx.tcx;
-    let param_env = tcx.param_env(def_id);
-    let id = tcx.hir().as_local_hir_id(def_id);
+    let param_env = tcx.param_env(def.did);
+    let id = tcx.hir().as_local_hir_id(def.did);
 
     let mut local_names = IndexVec::from_elem(None, &input_body.local_decls);
     for var_debug_info in &input_body.var_debug_info {
@@ -135,13 +150,13 @@ fn do_mir_borrowck<'a, 'tcx>(
     }
 
     // Gather the upvars of a closure, if any.
-    let tables = tcx.typeck_tables_of(def_id);
+    let tables = tcx.typeck_tables_of_opt_const_arg(def);
     if let Some(ErrorReported) = tables.tainted_by_errors {
         infcx.set_tainted_by_errors();
     }
     let upvars: Vec<_> = tables
         .closure_captures
-        .get(&def_id.to_def_id())
+        .get(&def.did.to_def_id())
         .into_iter()
         .flat_map(|v| v.values())
         .map(|upvar_id| {
@@ -171,8 +186,7 @@ fn do_mir_borrowck<'a, 'tcx>(
     // will have a lifetime tied to the inference context.
     let mut body = input_body.clone();
     let mut promoted = input_promoted.clone();
-    let free_regions =
-        nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body, &mut promoted);
+    let free_regions = nll::replace_regions_in_mir(infcx, def, param_env, &mut body, &mut promoted);
     let body = &body; // no further changes
 
     let location_table = &LocationTable::new(&body);
@@ -190,7 +204,7 @@ fn do_mir_borrowck<'a, 'tcx>(
     let mdpe = MoveDataParamEnv { move_data, param_env };
 
     let mut flow_inits = MaybeInitializedPlaces::new(tcx, &body, &mdpe)
-        .into_engine(tcx, &body, def_id.to_def_id())
+        .into_engine(tcx, &body, def.did.to_def_id())
         .iterate_to_fixpoint()
         .into_results_cursor(&body);
 
@@ -207,7 +221,7 @@ fn do_mir_borrowck<'a, 'tcx>(
         nll_errors,
     } = nll::compute_regions(
         infcx,
-        def_id,
+        def.did,
         free_regions,
         body,
         &promoted,
@@ -223,7 +237,7 @@ fn do_mir_borrowck<'a, 'tcx>(
     // write unit-tests, as well as helping with debugging.
     nll::dump_mir_results(
         infcx,
-        MirSource::item(def_id.to_def_id()),
+        MirSource { instance: InstanceDef::Item(def.to_global()), promoted: None },
         &body,
         &regioncx,
         &opt_closure_req,
@@ -234,7 +248,7 @@ fn do_mir_borrowck<'a, 'tcx>(
     nll::dump_annotation(
         infcx,
         &body,
-        def_id.to_def_id(),
+        def.did.to_def_id(),
         &regioncx,
         &opt_closure_req,
         &opaque_type_values,
@@ -249,13 +263,13 @@ fn do_mir_borrowck<'a, 'tcx>(
     let regioncx = Rc::new(regioncx);
 
     let flow_borrows = Borrows::new(tcx, &body, regioncx.clone(), &borrow_set)
-        .into_engine(tcx, &body, def_id.to_def_id())
+        .into_engine(tcx, &body, def.did.to_def_id())
         .iterate_to_fixpoint();
     let flow_uninits = MaybeUninitializedPlaces::new(tcx, &body, &mdpe)
-        .into_engine(tcx, &body, def_id.to_def_id())
+        .into_engine(tcx, &body, def.did.to_def_id())
         .iterate_to_fixpoint();
     let flow_ever_inits = EverInitializedPlaces::new(tcx, &body, &mdpe)
-        .into_engine(tcx, &body, def_id.to_def_id())
+        .into_engine(tcx, &body, def.did.to_def_id())
         .iterate_to_fixpoint();
 
     let movable_generator = match tcx.hir().get(id) {
@@ -274,7 +288,7 @@ fn do_mir_borrowck<'a, 'tcx>(
             let mut promoted_mbcx = MirBorrowckCtxt {
                 infcx,
                 body: promoted_body,
-                mir_def_id: def_id,
+                mir_def_id: def.did,
                 move_data: &move_data,
                 location_table: &LocationTable::new(promoted_body),
                 movable_generator,
@@ -307,7 +321,7 @@ fn do_mir_borrowck<'a, 'tcx>(
     let mut mbcx = MirBorrowckCtxt {
         infcx,
         body,
-        mir_def_id: def_id,
+        mir_def_id: def.did,
         move_data: &mdpe.move_data,
         location_table,
         movable_generator,
diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs
index ea68364be37..f6b3be59d95 100644
--- a/src/librustc_mir/borrow_check/nll.rs
+++ b/src/librustc_mir/borrow_check/nll.rs
@@ -9,7 +9,7 @@ use rustc_middle::mir::{
     BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
     Promoted,
 };
-use rustc_middle::ty::{self, RegionKind, RegionVid};
+use rustc_middle::ty::{self, InstanceDef, RegionKind, RegionVid};
 use rustc_span::symbol::sym;
 use std::env;
 use std::fmt::Debug;
@@ -59,20 +59,20 @@ crate struct NllOutput<'tcx> {
 /// `compute_regions`.
 pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>(
     infcx: &InferCtxt<'cx, 'tcx>,
-    def_id: LocalDefId,
+    def: ty::WithOptConstParam<LocalDefId>,
     param_env: ty::ParamEnv<'tcx>,
     body: &mut Body<'tcx>,
     promoted: &mut IndexVec<Promoted, Body<'tcx>>,
 ) -> UniversalRegions<'tcx> {
-    debug!("replace_regions_in_mir(def_id={:?})", def_id);
+    debug!("replace_regions_in_mir(def={:?})", def);
 
     // Compute named region information. This also renumbers the inputs/outputs.
-    let universal_regions = UniversalRegions::new(infcx, def_id, param_env);
+    let universal_regions = UniversalRegions::new(infcx, def, param_env);
 
     // Replace all remaining regions with fresh inference variables.
     renumber::renumber_mir(infcx, body, promoted);
 
-    let source = MirSource::item(def_id.to_def_id());
+    let source = MirSource { instance: InstanceDef::Item(def.to_global()), promoted: None };
     mir_util::dump_mir(infcx.tcx, None, "renumber", &0, source, body, |_, _| Ok(()));
 
     universal_regions
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index 3532b6de003..7b84737fa77 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -321,7 +321,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
             }
         } else {
             let tcx = self.tcx();
-            if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = constant.literal.val {
+            if let ty::ConstKind::Unevaluated(def, substs, promoted) = constant.literal.val {
                 if let Some(promoted) = promoted {
                     let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
                                      promoted: &Body<'tcx>,
@@ -357,7 +357,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
                         ConstraintCategory::Boring,
                         self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
                             constant.literal.ty,
-                            def_id,
+                            def.did,
                             UserSubsts { substs, user_self_ty: None },
                         )),
                     ) {
diff --git a/src/librustc_mir/borrow_check/universal_regions.rs b/src/librustc_mir/borrow_check/universal_regions.rs
index 7b292ee71f9..55d817b3f1c 100644
--- a/src/librustc_mir/borrow_check/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/universal_regions.rs
@@ -227,12 +227,12 @@ impl<'tcx> UniversalRegions<'tcx> {
     /// known between those regions.
     pub fn new(
         infcx: &InferCtxt<'_, 'tcx>,
-        mir_def_id: LocalDefId,
+        mir_def: ty::WithOptConstParam<LocalDefId>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> Self {
         let tcx = infcx.tcx;
-        let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id);
-        UniversalRegionsBuilder { infcx, mir_def_id, mir_hir_id, param_env }.build()
+        let mir_hir_id = tcx.hir().as_local_hir_id(mir_def.did);
+        UniversalRegionsBuilder { infcx, mir_def, mir_hir_id, param_env }.build()
     }
 
     /// Given a reference to a closure type, extracts all the values
@@ -388,7 +388,7 @@ impl<'tcx> UniversalRegions<'tcx> {
 
 struct UniversalRegionsBuilder<'cx, 'tcx> {
     infcx: &'cx InferCtxt<'cx, 'tcx>,
-    mir_def_id: LocalDefId,
+    mir_def: ty::WithOptConstParam<LocalDefId>,
     mir_hir_id: HirId,
     param_env: ty::ParamEnv<'tcx>,
 }
@@ -397,7 +397,7 @@ const FR: NLLRegionVariableOrigin = NLLRegionVariableOrigin::FreeRegion;
 
 impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
     fn build(self) -> UniversalRegions<'tcx> {
-        debug!("build(mir_def_id={:?})", self.mir_def_id);
+        debug!("build(mir_def={:?})", self.mir_def);
 
         let param_env = self.param_env;
         debug!("build: param_env={:?}", param_env);
@@ -417,7 +417,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
         let mut indices = self.compute_indices(fr_static, defining_ty);
         debug!("build: indices={:?}", indices);
 
-        let closure_base_def_id = self.infcx.tcx.closure_base_def_id(self.mir_def_id.to_def_id());
+        let closure_base_def_id = self.infcx.tcx.closure_base_def_id(self.mir_def.did.to_def_id());
 
         // If this is a closure or generator, then the late-bound regions from the enclosing
         // function are actually external regions to us. For example, here, 'a is not local
@@ -425,8 +425,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
         // fn foo<'a>() {
         //     let c = || { let x: &'a u32 = ...; }
         // }
-        if self.mir_def_id.to_def_id() != closure_base_def_id {
-            self.infcx.replace_late_bound_regions_with_nll_infer_vars(self.mir_def_id, &mut indices)
+        if self.mir_def.did.to_def_id() != closure_base_def_id {
+            self.infcx
+                .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices)
         }
 
         let bound_inputs_and_output = self.compute_inputs_and_output(&indices, defining_ty);
@@ -436,15 +437,15 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
         let first_local_index = self.infcx.num_region_vars();
         let inputs_and_output = self.infcx.replace_bound_regions_with_nll_infer_vars(
             FR,
-            self.mir_def_id,
+            self.mir_def.did,
             &bound_inputs_and_output,
             &mut indices,
         );
         // Converse of above, if this is a function then the late-bound regions declared on its
         // signature are local to the fn.
-        if self.mir_def_id.to_def_id() == closure_base_def_id {
+        if self.mir_def.did.to_def_id() == closure_base_def_id {
             self.infcx
-                .replace_late_bound_regions_with_nll_infer_vars(self.mir_def_id, &mut indices);
+                .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices);
         }
 
         let (unnormalized_output_ty, mut unnormalized_input_tys) =
@@ -456,7 +457,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
             if self.infcx.tcx.fn_sig(def_id).c_variadic() {
                 let va_list_did = self.infcx.tcx.require_lang_item(
                     lang_items::VaListTypeLangItem,
-                    Some(self.infcx.tcx.def_span(self.mir_def_id)),
+                    Some(self.infcx.tcx.def_span(self.mir_def.did)),
                 );
                 let region = self
                     .infcx
@@ -507,14 +508,14 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
     /// see `DefiningTy` for details.
     fn defining_ty(&self) -> DefiningTy<'tcx> {
         let tcx = self.infcx.tcx;
-        let closure_base_def_id = tcx.closure_base_def_id(self.mir_def_id.to_def_id());
+        let closure_base_def_id = tcx.closure_base_def_id(self.mir_def.did.to_def_id());
 
         match tcx.hir().body_owner_kind(self.mir_hir_id) {
             BodyOwnerKind::Closure | BodyOwnerKind::Fn => {
-                let defining_ty = if self.mir_def_id.to_def_id() == closure_base_def_id {
+                let defining_ty = if self.mir_def.did.to_def_id() == closure_base_def_id {
                     tcx.type_of(closure_base_def_id)
                 } else {
-                    let tables = tcx.typeck_tables_of(self.mir_def_id);
+                    let tables = tcx.typeck_tables_of(self.mir_def.did);
                     tables.node_type(self.mir_hir_id)
                 };
 
@@ -530,20 +531,20 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                     }
                     ty::FnDef(def_id, substs) => DefiningTy::FnDef(def_id, substs),
                     _ => span_bug!(
-                        tcx.def_span(self.mir_def_id),
+                        tcx.def_span(self.mir_def.did),
                         "expected defining type for `{:?}`: `{:?}`",
-                        self.mir_def_id,
+                        self.mir_def.did,
                         defining_ty
                     ),
                 }
             }
 
             BodyOwnerKind::Const | BodyOwnerKind::Static(..) => {
-                assert_eq!(self.mir_def_id.to_def_id(), closure_base_def_id);
+                assert_eq!(self.mir_def.did.to_def_id(), closure_base_def_id);
                 let identity_substs = InternalSubsts::identity_for_item(tcx, closure_base_def_id);
                 let substs =
                     self.infcx.replace_free_regions_with_nll_infer_vars(FR, &identity_substs);
-                DefiningTy::Const(self.mir_def_id.to_def_id(), substs)
+                DefiningTy::Const(self.mir_def.did.to_def_id(), substs)
             }
         }
     }
@@ -558,7 +559,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
         defining_ty: DefiningTy<'tcx>,
     ) -> UniversalRegionIndices<'tcx> {
         let tcx = self.infcx.tcx;
-        let closure_base_def_id = tcx.closure_base_def_id(self.mir_def_id.to_def_id());
+        let closure_base_def_id = tcx.closure_base_def_id(self.mir_def.did.to_def_id());
         let identity_substs = InternalSubsts::identity_for_item(tcx, closure_base_def_id);
         let fr_substs = match defining_ty {
             DefiningTy::Closure(_, ref substs) | DefiningTy::Generator(_, ref substs, _) => {
@@ -592,7 +593,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
         let tcx = self.infcx.tcx;
         match defining_ty {
             DefiningTy::Closure(def_id, substs) => {
-                assert_eq!(self.mir_def_id.to_def_id(), def_id);
+                assert_eq!(self.mir_def.did.to_def_id(), def_id);
                 let closure_sig = substs.as_closure().sig();
                 let inputs_and_output = closure_sig.inputs_and_output();
                 let closure_ty = tcx.closure_env_ty(def_id, substs).unwrap();
@@ -616,7 +617,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
             }
 
             DefiningTy::Generator(def_id, substs, movability) => {
-                assert_eq!(self.mir_def_id.to_def_id(), def_id);
+                assert_eq!(self.mir_def.did.to_def_id(), def_id);
                 let resume_ty = substs.as_generator().resume_ty();
                 let output = substs.as_generator().return_ty();
                 let generator_ty = tcx.mk_generator(def_id, substs, movability);
@@ -634,8 +635,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
             DefiningTy::Const(def_id, _) => {
                 // For a constant body, there are no inputs, and one
                 // "output" (the type of the constant).
-                assert_eq!(self.mir_def_id.to_def_id(), def_id);
-                let ty = tcx.type_of(def_id);
+                assert_eq!(self.mir_def.did.to_def_id(), def_id);
+                let ty = tcx.type_of(self.mir_def.def_id_for_type_of());
                 let ty = indices.fold_to_region_vids(tcx, &ty);
                 ty::Binder::dummy(tcx.intern_type_list(&[ty]))
             }
diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs
index 24a0107ab96..cec7f1bcb9d 100644
--- a/src/librustc_mir/const_eval/eval_queries.rs
+++ b/src/librustc_mir/const_eval/eval_queries.rs
@@ -288,21 +288,22 @@ pub fn const_eval_raw_provider<'tcx>(
     }
 
     let cid = key.value;
-    let def_id = cid.instance.def.def_id();
+    let def = cid.instance.def.with_opt_param();
 
-    if let Some(def_id) = def_id.as_local() {
-        if tcx.has_typeck_tables(def_id) {
-            if let Some(error_reported) = tcx.typeck_tables_of(def_id).tainted_by_errors {
+    if let Some(def) = def.as_local() {
+        if tcx.has_typeck_tables(def.did) {
+            if let Some(error_reported) = tcx.typeck_tables_of_opt_const_arg(def).tainted_by_errors
+            {
                 return Err(ErrorHandled::Reported(error_reported));
             }
         }
     }
 
-    let is_static = tcx.is_static(def_id);
+    let is_static = tcx.is_static(def.did);
 
     let mut ecx = InterpCx::new(
         tcx,
-        tcx.def_span(cid.instance.def_id()),
+        tcx.def_span(def.did),
         key.param_env,
         CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
         MemoryExtra { can_access_statics: is_static },
@@ -334,9 +335,9 @@ pub fn const_eval_raw_provider<'tcx>(
                 }
 
                 v
-            } else if let Some(def_id) = def_id.as_local() {
+            } else if let Some(def) = def.as_local() {
                 // constant defined in this crate, we can figure out a lint level!
-                match tcx.def_kind(def_id.to_def_id()) {
+                match tcx.def_kind(def.did.to_def_id()) {
                     // constants never produce a hard error at the definition site. Anything else is
                     // a backwards compatibility hazard (and will break old versions of winapi for
                     // sure)
@@ -346,9 +347,9 @@ pub fn const_eval_raw_provider<'tcx>(
                     // validation thus preventing such a hard error from being a backwards
                     // compatibility hazard
                     DefKind::Const | DefKind::AssocConst => {
-                        let hir_id = tcx.hir().as_local_hir_id(def_id);
+                        let hir_id = tcx.hir().as_local_hir_id(def.did);
                         err.report_as_lint(
-                            tcx.at(tcx.def_span(def_id)),
+                            tcx.at(tcx.def_span(def.did)),
                             "any use of this value will cause an error",
                             hir_id,
                             Some(err.span),
@@ -359,7 +360,7 @@ pub fn const_eval_raw_provider<'tcx>(
                     // deny-by-default lint
                     _ => {
                         if let Some(p) = cid.promoted {
-                            let span = tcx.promoted_mir(def_id)[p].span;
+                            let span = tcx.promoted_mir_of_opt_const_arg(def.to_global())[p].span;
                             if let err_inval!(ReferencedConstant) = err.error {
                                 err.report_as_error(
                                     tcx.at(span),
@@ -369,7 +370,7 @@ pub fn const_eval_raw_provider<'tcx>(
                                 err.report_as_lint(
                                     tcx.at(span),
                                     "reaching this expression at runtime will panic or abort",
-                                    tcx.hir().as_local_hir_id(def_id),
+                                    tcx.hir().as_local_hir_id(def.did),
                                     Some(err.span),
                                 )
                             }
diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs
index 8be0ab9019f..6453630bb92 100644
--- a/src/librustc_mir/const_eval/machine.rs
+++ b/src/librustc_mir/const_eval/machine.rs
@@ -191,11 +191,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         debug!("find_mir_or_eval_fn: {:?}", instance);
 
         // Only check non-glue functions
-        if let ty::InstanceDef::Item(def_id) = instance.def {
+        if let ty::InstanceDef::Item(def) = instance.def {
             // Execution might have wandered off into other crates, so we cannot do a stability-
             // sensitive check here.  But we can at least rule out functions that are not const
             // at all.
-            if ecx.tcx.is_const_fn_raw(def_id) {
+            if ecx.tcx.is_const_fn_raw(def.did) {
                 // If this function is a `const fn` then under certain circumstances we
                 // can evaluate call via the query system, thus memoizing all future calls.
                 if ecx.try_eval_const_fn_call(instance, ret, args)? {
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 602876e3de1..c59b7c98e98 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -394,24 +394,30 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         promoted: Option<mir::Promoted>,
     ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
         // do not continue if typeck errors occurred (can only occur in local crate)
-        let did = instance.def_id();
-        if let Some(did) = did.as_local() {
-            if self.tcx.has_typeck_tables(did) {
-                if let Some(error_reported) = self.tcx.typeck_tables_of(did).tainted_by_errors {
+        let def = instance.with_opt_param();
+        if let Some(def) = def.as_local() {
+            if self.tcx.has_typeck_tables(def.did) {
+                if let Some(error_reported) =
+                    self.tcx.typeck_tables_of_opt_const_arg(def).tainted_by_errors
+                {
                     throw_inval!(TypeckError(error_reported))
                 }
             }
         }
         trace!("load mir(instance={:?}, promoted={:?})", instance, promoted);
         if let Some(promoted) = promoted {
-            return Ok(&self.tcx.promoted_mir(did)[promoted]);
+            return Ok(&self.tcx.promoted_mir_of_opt_const_arg(def)[promoted]);
         }
         match instance {
-            ty::InstanceDef::Item(def_id) => {
-                if self.tcx.is_mir_available(did) {
-                    Ok(self.tcx.optimized_mir(did))
+            ty::InstanceDef::Item(def) => {
+                if self.tcx.is_mir_available(def.did) {
+                    if let Some((did, param_did)) = def.as_const_arg() {
+                        Ok(self.tcx.optimized_mir_of_const_arg((did, param_did)))
+                    } else {
+                        Ok(self.tcx.optimized_mir(def.did))
+                    }
                 } else {
-                    throw_unsup!(NoMirFor(def_id))
+                    throw_unsup!(NoMirFor(def.did))
                 }
             }
             _ => Ok(self.tcx.instance_mir(instance)),
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index b02b5219ba1..face72d70ce 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -549,8 +549,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let val_val = match val.val {
             ty::ConstKind::Param(_) => throw_inval!(TooGeneric),
             ty::ConstKind::Error(_) => throw_inval!(TypeckError(ErrorReported)),
-            ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
-                let instance = self.resolve(def_id, substs)?;
+            ty::ConstKind::Unevaluated(def, substs, promoted) => {
+                let instance = self.resolve(def.did, substs)?;
                 // We use `const_eval` here and `const_eval_raw` elsewhere in mir interpretation.
                 // The reason we use `const_eval_raw` everywhere else is to prevent cycles during
                 // validation, because validation automatically reads through any references, thus
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index f9b3c319c1f..35fb950ce66 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -622,12 +622,12 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
 
         match substituted_constant.val {
             ty::ConstKind::Value(val) => collect_const_value(self.tcx, val, self.output),
-            ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
-                match self.tcx.const_eval_resolve(param_env, def_id, substs, promoted, None) {
+            ty::ConstKind::Unevaluated(def, substs, promoted) => {
+                match self.tcx.const_eval_resolve(param_env, def, substs, promoted, None) {
                     Ok(val) => collect_const_value(self.tcx, val, self.output),
                     Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted) => {}
                     Err(ErrorHandled::TooGeneric) => span_bug!(
-                        self.tcx.def_span(def_id),
+                        self.tcx.def_span(def.did),
                         "collection encountered polymorphic constant",
                     ),
                 }
@@ -768,8 +768,8 @@ fn visit_instance_use<'tcx>(
 // need a mono item.
 fn should_monomorphize_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> bool {
     let def_id = match instance.def {
-        ty::InstanceDef::Item(def_id) | ty::InstanceDef::DropGlue(def_id, Some(_)) => def_id,
-
+        ty::InstanceDef::Item(def) => def.did,
+        ty::InstanceDef::DropGlue(def_id, Some(_)) => def_id,
         ty::InstanceDef::VtableShim(..)
         | ty::InstanceDef::ReifyShim(..)
         | ty::InstanceDef::ClosureOnceShim { .. }
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index 65ed76c558c..410ed66e008 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -314,7 +314,8 @@ fn mono_item_visibility(
     };
 
     let def_id = match instance.def {
-        InstanceDef::Item(def_id) | InstanceDef::DropGlue(def_id, Some(_)) => def_id,
+        InstanceDef::Item(def) => def.did,
+        InstanceDef::DropGlue(def_id, Some(_)) => def_id,
 
         // These are all compiler glue and such, never exported, always hidden.
         InstanceDef::VtableShim(..)
@@ -704,7 +705,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
     match mono_item {
         MonoItem::Fn(instance) => {
             let def_id = match instance.def {
-                ty::InstanceDef::Item(def_id) => def_id,
+                ty::InstanceDef::Item(def) => def.did,
                 ty::InstanceDef::VtableShim(..)
                 | ty::InstanceDef::ReifyShim(..)
                 | ty::InstanceDef::FnPtrShim(..)
diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs
index 3dddd9c1c17..445a0230afd 100644
--- a/src/librustc_mir/transform/check_consts/qualifs.rs
+++ b/src/librustc_mir/transform/check_consts/qualifs.rs
@@ -244,11 +244,16 @@ where
     };
 
     // Check the qualifs of the value of `const` items.
-    if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val {
+    if let ty::ConstKind::Unevaluated(def, _, promoted) = constant.literal.val {
         assert!(promoted.is_none());
         // Don't peek inside trait associated constants.
-        if cx.tcx.trait_of_item(def_id).is_none() {
-            let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def_id);
+        if cx.tcx.trait_of_item(def.did).is_none() {
+            let qualifs = if let Some((did, param_did)) = def.as_const_arg() {
+                cx.tcx.at(constant.span).mir_const_qualif_const_arg((did, param_did))
+            } else {
+                cx.tcx.at(constant.span).mir_const_qualif(def.did)
+            };
+
             if !Q::in_qualifs(&qualifs) {
                 return false;
             }
diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs
index 5cb161ebcfb..f64c72e7b36 100644
--- a/src/librustc_mir/transform/check_consts/validation.rs
+++ b/src/librustc_mir/transform/check_consts/validation.rs
@@ -520,8 +520,8 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
                     let instance = Instance::resolve(self.tcx, self.param_env, def_id, substs);
                     debug!("Resolving ({:?}) -> {:?}", def_id, instance);
                     if let Ok(Some(func)) = instance {
-                        if let InstanceDef::Item(def_id) = func.def {
-                            if is_const_fn(self.tcx, def_id) {
+                        if let InstanceDef::Item(def) = func.def {
+                            if is_const_fn(self.tcx, def.did) {
                                 return;
                             }
                         }
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index f218dd397c0..2605d45f810 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -489,7 +489,19 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
 }
 
 pub(crate) fn provide(providers: &mut Providers) {
-    *providers = Providers { unsafety_check_result, unsafe_derive_on_repr_packed, ..*providers };
+    *providers = Providers {
+        unsafety_check_result: |tcx, def_id| {
+            unsafety_check_result(tcx, ty::WithOptConstParam::unknown(def_id))
+        },
+        unsafety_check_result_for_const_arg: |tcx, (did, param_did)| {
+            unsafety_check_result(
+                tcx,
+                ty::WithOptConstParam { did, const_param_did: Some(param_did) },
+            )
+        },
+        unsafe_derive_on_repr_packed,
+        ..*providers
+    };
 }
 
 struct UnusedUnsafeVisitor<'a> {
@@ -535,32 +547,42 @@ fn check_unused_unsafe(
     intravisit::Visitor::visit_body(&mut visitor, body);
 }
 
-fn unsafety_check_result(tcx: TyCtxt<'_>, def_id: LocalDefId) -> UnsafetyCheckResult {
-    debug!("unsafety_violations({:?})", def_id);
+fn unsafety_check_result<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def: ty::WithOptConstParam<LocalDefId>,
+) -> &'tcx UnsafetyCheckResult {
+    if def.const_param_did.is_none() {
+        if let Some(param_did) = tcx.opt_const_param_of(def.did) {
+            return tcx.unsafety_check_result_for_const_arg((def.did, param_did));
+        }
+    }
+
+    debug!("unsafety_violations({:?})", def);
 
     // N.B., this borrow is valid because all the consumers of
     // `mir_built` force this.
-    let body = &tcx.mir_built(def_id).borrow();
+    let body = &tcx.mir_built(def).borrow();
 
-    let param_env = tcx.param_env(def_id);
+    let param_env = tcx.param_env(def.did);
 
-    let id = tcx.hir().as_local_hir_id(def_id);
+    let id = tcx.hir().as_local_hir_id(def.did);
     let (const_context, min_const_fn) = match tcx.hir().body_owner_kind(id) {
         hir::BodyOwnerKind::Closure => (false, false),
         hir::BodyOwnerKind::Fn => {
-            (tcx.is_const_fn_raw(def_id.to_def_id()), is_min_const_fn(tcx, def_id.to_def_id()))
+            (tcx.is_const_fn_raw(def.did.to_def_id()), is_min_const_fn(tcx, def.did.to_def_id()))
         }
         hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => (true, false),
     };
     let mut checker =
-        UnsafetyChecker::new(const_context, min_const_fn, body, def_id, tcx, param_env);
+        UnsafetyChecker::new(const_context, min_const_fn, body, def.did, tcx, param_env);
     checker.visit_body(&body);
 
-    check_unused_unsafe(tcx, def_id, &checker.used_unsafe, &mut checker.inherited_blocks);
-    UnsafetyCheckResult {
+    check_unused_unsafe(tcx, def.did, &checker.used_unsafe, &mut checker.inherited_blocks);
+
+    tcx.arena.alloc(UnsafetyCheckResult {
         violations: checker.violations.into(),
         unsafe_blocks: checker.inherited_blocks.into(),
-    }
+    })
 }
 
 fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 816cf08a6da..51a9e76e762 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -9,7 +9,7 @@ use rustc_middle::mir::visit::Visitor as _;
 use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPhase, Promoted};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::steal::Steal;
-use rustc_middle::ty::{InstanceDef, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, InstanceDef, TyCtxt, TypeFoldable};
 use rustc_span::{Span, Symbol};
 use std::borrow::Cow;
 
@@ -48,12 +48,23 @@ pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers {
         mir_keys,
         mir_const,
-        mir_const_qualif,
+        mir_const_qualif: |tcx, did| {
+            mir_const_qualif(tcx, ty::WithOptConstParam::unknown(did.expect_local()))
+        },
+        mir_const_qualif_const_arg: |tcx, (did, param_did)| {
+            mir_const_qualif(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
+        },
         mir_validated,
         mir_drops_elaborated_and_const_checked,
         optimized_mir,
+        optimized_mir_of_const_arg,
         is_mir_available,
-        promoted_mir,
+        promoted_mir: |tcx, def_id| {
+            promoted_mir(tcx, ty::WithOptConstParam::unknown(def_id.expect_local()))
+        },
+        promoted_mir_of_const_arg: |tcx, (did, param_did)| {
+            promoted_mir(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
+        },
         ..*providers
     };
     instrument_coverage::provide(providers);
@@ -116,7 +127,14 @@ pub struct MirSource<'tcx> {
 
 impl<'tcx> MirSource<'tcx> {
     pub fn item(def_id: DefId) -> Self {
-        MirSource { instance: InstanceDef::Item(def_id), promoted: None }
+        MirSource {
+            instance: InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
+            promoted: None,
+        }
+    }
+
+    pub fn with_opt_param(self) -> ty::WithOptConstParam<DefId> {
+        self.instance.with_opt_param()
     }
 
     #[inline]
@@ -202,9 +220,14 @@ pub fn run_passes(
     }
 }
 
-fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> ConstQualifs {
-    let def_id = def_id.expect_local();
-    let const_kind = tcx.hir().body_const_context(def_id);
+fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> ConstQualifs {
+    if def.const_param_did.is_none() {
+        if let Some(param_did) = tcx.opt_const_param_of(def.did) {
+            return tcx.mir_const_qualif_const_arg((def.did, param_did));
+        }
+    }
+
+    let const_kind = tcx.hir().body_const_context(def.did);
 
     // No need to const-check a non-const `fn`.
     if const_kind.is_none() {
@@ -215,15 +238,20 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> ConstQualifs {
     // cannot yet be stolen), because `mir_validated()`, which steals
     // from `mir_const(), forces this query to execute before
     // performing the steal.
-    let body = &tcx.mir_const(def_id.to_def_id()).borrow();
+    let body = &tcx.mir_const(def).borrow();
 
     if body.return_ty().references_error() {
         tcx.sess.delay_span_bug(body.span, "mir_const_qualif: MIR had errors");
         return Default::default();
     }
 
-    let ccx =
-        check_consts::ConstCx { body, tcx, def_id, const_kind, param_env: tcx.param_env(def_id) };
+    let ccx = check_consts::ConstCx {
+        body,
+        tcx,
+        def_id: def.did,
+        const_kind,
+        param_env: tcx.param_env(def.did),
+    };
 
     let mut validator = check_consts::validation::Validator::new(&ccx);
     validator.check_body();
@@ -234,22 +262,39 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> ConstQualifs {
 }
 
 /// Make MIR ready for const evaluation. This is run on all MIR, not just on consts!
-fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> Steal<Body<'_>> {
-    let def_id = def_id.expect_local();
+fn mir_const<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def: ty::WithOptConstParam<LocalDefId>,
+) -> &'tcx Steal<Body<'tcx>> {
+    if def.const_param_did.is_none() {
+        if let const_param_did @ Some(_) = tcx.opt_const_param_of(def.did) {
+            return tcx.mir_const(ty::WithOptConstParam { const_param_did, ..def });
+        }
+    }
 
     // Unsafety check uses the raw mir, so make sure it is run.
-    let _ = tcx.unsafety_check_result(def_id);
+    if let Some(param_did) = def.const_param_did {
+        tcx.ensure().unsafety_check_result_for_const_arg((def.did, param_did));
+    } else {
+        tcx.ensure().unsafety_check_result(def.did);
+    }
 
-    let mut body = tcx.mir_built(def_id).steal();
+    let mut body = tcx.mir_built(def).steal();
 
-    util::dump_mir(tcx, None, "mir_map", &0, MirSource::item(def_id.to_def_id()), &body, |_, _| {
-        Ok(())
-    });
+    util::dump_mir(
+        tcx,
+        None,
+        "mir_map",
+        &0,
+        MirSource { instance: InstanceDef::Item(def.to_global()), promoted: None },
+        &body,
+        |_, _| Ok(()),
+    );
 
     run_passes(
         tcx,
         &mut body,
-        InstanceDef::Item(def_id.to_def_id()),
+        InstanceDef::Item(def.to_global()),
         None,
         MirPhase::Const,
         &[&[
@@ -265,13 +310,19 @@ fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> Steal<Body<'_>> {
 
 fn mir_validated(
     tcx: TyCtxt<'tcx>,
-    def_id: LocalDefId,
-) -> (Steal<Body<'tcx>>, Steal<IndexVec<Promoted, Body<'tcx>>>) {
+    def: ty::WithOptConstParam<LocalDefId>,
+) -> (&'tcx Steal<Body<'tcx>>, &'tcx Steal<IndexVec<Promoted, Body<'tcx>>>) {
+    if def.const_param_did.is_none() {
+        if let const_param_did @ Some(_) = tcx.opt_const_param_of(def.did) {
+            return tcx.mir_validated(ty::WithOptConstParam { const_param_did, ..def });
+        }
+    }
+
     // Ensure that we compute the `mir_const_qualif` for constants at
     // this point, before we steal the mir-const result.
-    let _ = tcx.mir_const_qualif(def_id.to_def_id());
+    let _ = tcx.mir_const_qualif_opt_const_arg(def);
 
-    let mut body = tcx.mir_const(def_id.to_def_id()).steal();
+    let mut body = tcx.mir_const(def).steal();
 
     let mut required_consts = Vec::new();
     let mut required_consts_visitor = RequiredConstsVisitor::new(&mut required_consts);
@@ -284,7 +335,7 @@ fn mir_validated(
     run_passes(
         tcx,
         &mut body,
-        InstanceDef::Item(def_id.to_def_id()),
+        InstanceDef::Item(def.to_global()),
         None,
         MirPhase::Validated,
         &[&[
@@ -304,17 +355,30 @@ fn mir_validated(
 
 fn mir_drops_elaborated_and_const_checked<'tcx>(
     tcx: TyCtxt<'tcx>,
-    def_id: LocalDefId,
-) -> Steal<Body<'tcx>> {
+    def: ty::WithOptConstParam<LocalDefId>,
+) -> &'tcx Steal<Body<'tcx>> {
+    if def.const_param_did.is_none() {
+        if let const_param_did @ Some(_) = tcx.opt_const_param_of(def.did) {
+            return tcx.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam {
+                const_param_did,
+                ..def
+            });
+        }
+    }
+
     // (Mir-)Borrowck uses `mir_validated`, so we have to force it to
     // execute before we can steal.
-    tcx.ensure().mir_borrowck(def_id);
+    if let Some(param_did) = def.const_param_did {
+        tcx.ensure().mir_borrowck_const_arg((def.did, param_did));
+    } else {
+        tcx.ensure().mir_borrowck(def.did);
+    }
 
-    let (body, _) = tcx.mir_validated(def_id);
+    let (body, _) = tcx.mir_validated(def);
     let mut body = body.steal();
 
-    run_post_borrowck_cleanup_passes(tcx, &mut body, def_id, None);
-    check_consts::post_drop_elaboration::check_live_drops(tcx, def_id, &body);
+    run_post_borrowck_cleanup_passes(tcx, &mut body, def.did, None);
+    check_consts::post_drop_elaboration::check_live_drops(tcx, def.did, &body);
     tcx.alloc_steal_mir(body)
 }
 
@@ -350,7 +414,7 @@ fn run_post_borrowck_cleanup_passes<'tcx>(
     run_passes(
         tcx,
         body,
-        InstanceDef::Item(def_id.to_def_id()),
+        InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id())),
         promoted,
         MirPhase::DropElab,
         &[post_borrowck_cleanup],
@@ -414,7 +478,7 @@ fn run_optimization_passes<'tcx>(
     run_passes(
         tcx,
         body,
-        InstanceDef::Item(def_id.to_def_id()),
+        InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id())),
         promoted,
         MirPhase::Optimized,
         &[
@@ -424,42 +488,70 @@ fn run_optimization_passes<'tcx>(
     );
 }
 
-fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> {
-    if tcx.is_constructor(def_id) {
+fn optimized_mir<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx Body<'tcx> {
+    let did = did.expect_local();
+    if let Some(param_did) = tcx.opt_const_param_of(did) {
+        tcx.optimized_mir_of_const_arg((did, param_did))
+    } else {
+        tcx.arena.alloc(inner_optimized_mir(tcx, ty::WithOptConstParam::unknown(did)))
+    }
+}
+
+fn optimized_mir_of_const_arg<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    (did, param_did): (LocalDefId, DefId),
+) -> &'tcx Body<'tcx> {
+    tcx.arena.alloc(inner_optimized_mir(
+        tcx,
+        ty::WithOptConstParam { did, const_param_did: Some(param_did) },
+    ))
+}
+
+fn inner_optimized_mir(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> {
+    if tcx.is_constructor(def.did.to_def_id()) {
         // There's no reason to run all of the MIR passes on constructors when
         // we can just output the MIR we want directly. This also saves const
         // qualification and borrow checking the trouble of special casing
         // constructors.
-        return shim::build_adt_ctor(tcx, def_id);
+        return shim::build_adt_ctor(tcx, def.did.to_def_id());
     }
 
-    let def_id = def_id.expect_local();
-
-    let mut body = tcx.mir_drops_elaborated_and_const_checked(def_id).steal();
-    run_optimization_passes(tcx, &mut body, def_id, None);
+    let mut body = tcx.mir_drops_elaborated_and_const_checked(def).steal();
+    run_optimization_passes(tcx, &mut body, def.did, None);
 
     debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR");
 
     body
 }
 
-fn promoted_mir(tcx: TyCtxt<'_>, def_id: DefId) -> IndexVec<Promoted, Body<'_>> {
-    if tcx.is_constructor(def_id) {
-        return IndexVec::new();
+fn promoted_mir<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def: ty::WithOptConstParam<LocalDefId>,
+) -> &'tcx IndexVec<Promoted, Body<'tcx>> {
+    if def.const_param_did.is_none() {
+        if let Some(param_did) = tcx.opt_const_param_of(def.did) {
+            return tcx.promoted_mir_of_const_arg((def.did, param_did));
+        }
     }
 
-    let def_id = def_id.expect_local();
+    if tcx.is_constructor(def.did.to_def_id()) {
+        return tcx.arena.alloc(IndexVec::new());
+    }
 
-    tcx.ensure().mir_borrowck(def_id);
-    let (_, promoted) = tcx.mir_validated(def_id);
+    if let Some(param_did) = def.const_param_did {
+        tcx.ensure().mir_borrowck_const_arg((def.did, param_did));
+    } else {
+        tcx.ensure().mir_borrowck(def.did);
+    }
+    let (_, promoted) = tcx.mir_validated(def);
     let mut promoted = promoted.steal();
 
     for (p, mut body) in promoted.iter_enumerated_mut() {
-        run_post_borrowck_cleanup_passes(tcx, &mut body, def_id, Some(p));
-        run_optimization_passes(tcx, &mut body, def_id, Some(p));
+        run_post_borrowck_cleanup_passes(tcx, &mut body, def.did, Some(p));
+        run_optimization_passes(tcx, &mut body, def.did, Some(p));
     }
 
     debug_assert!(!promoted.has_free_regions(), "Free regions in promoted MIR");
 
-    promoted
+    tcx.arena.alloc(promoted)
 }
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index 5aa67227994..59a8415ef96 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -60,16 +60,15 @@ impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> {
             return;
         }
 
-        let def_id = src.def_id().expect_local();
+        let def = src.with_opt_param().expect_local();
 
         let mut rpo = traversal::reverse_postorder(body);
-        let ccx = ConstCx::new(tcx, def_id, body);
+        let ccx = ConstCx::new(tcx, def.did, body);
         let (temps, all_candidates) = collect_temps_and_candidates(&ccx, &mut rpo);
 
         let promotable_candidates = validate_candidates(&ccx, &temps, &all_candidates);
 
-        let promoted =
-            promote_candidates(def_id.to_def_id(), body, tcx, temps, promotable_candidates);
+        let promoted = promote_candidates(def.to_global(), body, tcx, temps, promotable_candidates);
         self.promoted_fragments.set(promoted);
     }
 }
@@ -937,7 +936,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
 
     fn promote_candidate(
         mut self,
-        def_id: DefId,
+        def: ty::WithOptConstParam<DefId>,
         candidate: Candidate,
         next_promoted_id: usize,
     ) -> Option<Body<'tcx>> {
@@ -955,8 +954,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                     literal: tcx.mk_const(ty::Const {
                         ty,
                         val: ty::ConstKind::Unevaluated(
-                            def_id,
-                            InternalSubsts::for_item(tcx, def_id, |param, _| {
+                            def,
+                            InternalSubsts::for_item(tcx, def.did, |param, _| {
                                 if let ty::GenericParamDefKind::Lifetime = param.kind {
                                     tcx.lifetimes.re_erased.into()
                                 } else {
@@ -1100,7 +1099,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> {
 }
 
 pub fn promote_candidates<'tcx>(
-    def_id: DefId,
+    def: ty::WithOptConstParam<DefId>,
     body: &mut Body<'tcx>,
     tcx: TyCtxt<'tcx>,
     mut temps: IndexVec<Local, TempState>,
@@ -1157,7 +1156,7 @@ pub fn promote_candidates<'tcx>(
         };
 
         //FIXME(oli-obk): having a `maybe_push()` method on `IndexVec` might be nice
-        if let Some(promoted) = promoter.promote_candidate(def_id, candidate, promotions.len()) {
+        if let Some(promoted) = promoter.promote_candidate(def, candidate, promotions.len()) {
             promotions.push(promoted);
         }
     }
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index db45481e4fd..990bfc064c2 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -248,7 +248,10 @@ pub fn write_mir_pretty<'tcx>(
 
         for (i, body) in tcx.promoted_mir(def_id).iter_enumerated() {
             writeln!(w)?;
-            let src = MirSource { instance: ty::InstanceDef::Item(def_id), promoted: Some(i) };
+            let src = MirSource {
+                instance: ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
+                promoted: Some(i),
+            };
             write_mir_fn(tcx, src, body, &mut |_, _| Ok(()), w)?;
         }
     }
diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs
index e69f6b30abd..21a5ea0aae3 100644
--- a/src/librustc_mir_build/build/mod.rs
+++ b/src/librustc_mir_build/build/mod.rs
@@ -21,13 +21,19 @@ use rustc_target::spec::PanicStrategy;
 
 use super::lints;
 
-crate fn mir_built(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::steal::Steal<Body<'_>> {
-    tcx.alloc_steal_mir(mir_build(tcx, def_id))
+crate fn mir_built<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>) -> &'tcx ty::steal::Steal<Body<'tcx>> {
+    if def.const_param_did.is_none() {
+        if let const_param_did @ Some(_) = tcx.opt_const_param_of(def.did) {
+            return tcx.mir_built(ty::WithOptConstParam { const_param_did, ..def });
+        }
+    }
+
+    tcx.alloc_steal_mir(mir_build(tcx, def))
 }
 
 /// Construct the MIR for a given `DefId`.
-fn mir_build(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Body<'_> {
-    let id = tcx.hir().as_local_hir_id(def_id);
+fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> {
+    let id = tcx.hir().as_local_hir_id(def.did);
 
     // Figure out what primary body this item has.
     let (body_id, return_ty_span) = match tcx.hir().get(id) {
@@ -57,11 +63,11 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Body<'_> {
         }) => (*body_id, ty.span),
         Node::AnonConst(hir::AnonConst { body, hir_id, .. }) => (*body, tcx.hir().span(*hir_id)),
 
-        _ => span_bug!(tcx.hir().span(id), "can't build MIR for {:?}", def_id),
+        _ => span_bug!(tcx.hir().span(id), "can't build MIR for {:?}", def.did),
     };
 
     tcx.infer_ctxt().enter(|infcx| {
-        let cx = Cx::new(&infcx, id);
+        let cx = Cx::new(&infcx, def, id);
         let body = if let Some(ErrorReported) = cx.tables().tainted_by_errors {
             build::construct_error(cx, body_id)
         } else if cx.body_owner_kind.is_fn_or_closure() {
@@ -181,7 +187,7 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Body<'_> {
             build::construct_const(cx, body_id, return_ty, return_ty_span)
         };
 
-        lints::check(tcx, &body, def_id);
+        lints::check(tcx, &body, def.did);
 
         // The borrow checker will replace all the regions here with its own
         // inference variables. There's no point having non-erased regions here.
diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs
index d36990684e0..89ad8a1b337 100644
--- a/src/librustc_mir_build/hair/cx/expr.rs
+++ b/src/librustc_mir_build/hair/cx/expr.rs
@@ -600,7 +600,11 @@ fn make_mirror_unadjusted<'a, 'tcx>(
                             // and not the beginning of discriminants (which is always `0`)
                             let substs = InternalSubsts::identity_for_item(cx.tcx(), did);
                             let lhs = mk_const(cx.tcx().mk_const(ty::Const {
-                                val: ty::ConstKind::Unevaluated(did, substs, None),
+                                val: ty::ConstKind::Unevaluated(
+                                    ty::WithOptConstParam::unknown(did),
+                                    substs,
+                                    None,
+                                ),
                                 ty: var_ty,
                             }));
                             let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset };
@@ -796,7 +800,11 @@ fn convert_path_expr<'a, 'tcx>(
             debug!("convert_path_expr: (const) user_ty={:?}", user_ty);
             ExprKind::Literal {
                 literal: cx.tcx.mk_const(ty::Const {
-                    val: ty::ConstKind::Unevaluated(def_id, substs, None),
+                    val: ty::ConstKind::Unevaluated(
+                        ty::WithOptConstParam::unknown(def_id),
+                        substs,
+                        None,
+                    ),
                     ty: cx.tables().node_type(expr.hir_id),
                 }),
                 user_ty,
diff --git a/src/librustc_mir_build/hair/cx/mod.rs b/src/librustc_mir_build/hair/cx/mod.rs
index d8b3ac79e6b..12d1c637fb0 100644
--- a/src/librustc_mir_build/hair/cx/mod.rs
+++ b/src/librustc_mir_build/hair/cx/mod.rs
@@ -1,4 +1,4 @@
-//! This module contains the fcuntaiontliy to convert from the wacky tcx data
+//! This module contains the functionality to convert from the wacky tcx data
 //! structures into the HAIR. The `builder` is generally ignorant of the tcx,
 //! etc., and instead goes through the `Cx` for most of its work.
 
@@ -8,7 +8,7 @@ use crate::hair::*;
 use rustc_ast::ast;
 use rustc_ast::attr;
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::Node;
 use rustc_index::vec::Idx;
 use rustc_infer::infer::InferCtxt;
@@ -50,10 +50,13 @@ crate struct Cx<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Cx<'a, 'tcx> {
-    crate fn new(infcx: &'a InferCtxt<'a, 'tcx>, src_id: hir::HirId) -> Cx<'a, 'tcx> {
+    crate fn new(
+        infcx: &'a InferCtxt<'a, 'tcx>,
+        def: ty::WithOptConstParam<LocalDefId>,
+        src_id: hir::HirId,
+    ) -> Cx<'a, 'tcx> {
         let tcx = infcx.tcx;
-        let src_def_id = tcx.hir().local_def_id(src_id);
-        let tables = tcx.typeck_tables_of(src_def_id);
+        let tables = tcx.typeck_tables_of_opt_const_arg(def);
         let body_owner_kind = tcx.hir().body_owner_kind(src_id);
 
         let constness = match body_owner_kind {
@@ -78,12 +81,12 @@ impl<'a, 'tcx> Cx<'a, 'tcx> {
             tcx,
             infcx,
             root_lint_level: src_id,
-            param_env: tcx.param_env(src_def_id),
-            identity_substs: InternalSubsts::identity_for_item(tcx, src_def_id.to_def_id()),
-            region_scope_tree: tcx.region_scope_tree(src_def_id),
+            param_env: tcx.param_env(def.did),
+            identity_substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
+            region_scope_tree: tcx.region_scope_tree(def.did),
             tables,
             constness,
-            body_owner: src_def_id.to_def_id(),
+            body_owner: def.did.to_def_id(),
             body_owner_kind,
             check_overflow,
         }
diff --git a/src/librustc_trait_selection/traits/fulfill.rs b/src/librustc_trait_selection/traits/fulfill.rs
index 800aef7284f..c6c76028f85 100644
--- a/src/librustc_trait_selection/traits/fulfill.rs
+++ b/src/librustc_trait_selection/traits/fulfill.rs
@@ -524,10 +524,10 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
                 let stalled_on = &mut pending_obligation.stalled_on;
 
                 let mut evaluate = |c: &'tcx Const<'tcx>| {
-                    if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = c.val {
+                    if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val {
                         match self.selcx.infcx().const_eval_resolve(
                             obligation.param_env,
-                            def_id,
+                            def,
                             substs,
                             promoted,
                             Some(obligation.cause.span),
diff --git a/src/librustc_trait_selection/traits/select/mod.rs b/src/librustc_trait_selection/traits/select/mod.rs
index ba5e60012da..5dc5fb797ff 100644
--- a/src/librustc_trait_selection/traits/select/mod.rs
+++ b/src/librustc_trait_selection/traits/select/mod.rs
@@ -507,11 +507,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 debug!("evaluate_predicate_recursively: equating consts c1={:?} c2={:?}", c1, c2);
 
                 let evaluate = |c: &'tcx ty::Const<'tcx>| {
-                    if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = c.val {
+                    if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val {
                         self.infcx
                             .const_eval_resolve(
                                 obligation.param_env,
-                                def_id,
+                                def,
                                 substs,
                                 promoted,
                                 Some(obligation.cause.span),
diff --git a/src/librustc_trait_selection/traits/wf.rs b/src/librustc_trait_selection/traits/wf.rs
index ebff2dd9b23..b8446fa0012 100644
--- a/src/librustc_trait_selection/traits/wf.rs
+++ b/src/librustc_trait_selection/traits/wf.rs
@@ -116,8 +116,8 @@ pub fn predicate_obligations<'a, 'tcx>(
             wf.compute(data.skip_binder().a.into()); // (*)
             wf.compute(data.skip_binder().b.into()); // (*)
         }
-        &ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
-            let obligations = wf.nominal_obligations(def_id, substs);
+        &ty::PredicateKind::ConstEvaluatable(def, substs) => {
+            let obligations = wf.nominal_obligations(def.did, substs);
             wf.out.extend(obligations);
 
             for arg in substs.iter() {
@@ -359,13 +359,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
 
                 GenericArgKind::Const(constant) => {
                     match constant.val {
-                        ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
+                        ty::ConstKind::Unevaluated(def, substs, promoted) => {
                             assert!(promoted.is_none());
 
-                            let obligations = self.nominal_obligations(def_id, substs);
+                            let obligations = self.nominal_obligations(def.did, substs);
                             self.out.extend(obligations);
 
-                            let predicate = ty::PredicateKind::ConstEvaluatable(def_id, substs)
+                            let predicate = ty::PredicateKind::ConstEvaluatable(def, substs)
                                 .to_predicate(self.tcx());
                             let cause = self.cause(traits::MiscObligation);
                             self.out.push(traits::Obligation::new(
diff --git a/src/librustc_ty/instance.rs b/src/librustc_ty/instance.rs
index 9f5ab7f8e4a..0bc6c470978 100644
--- a/src/librustc_ty/instance.rs
+++ b/src/librustc_ty/instance.rs
@@ -1,5 +1,5 @@
 use rustc_errors::ErrorReported;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, Instance, TyCtxt, TypeFoldable};
@@ -14,15 +14,43 @@ fn resolve_instance<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
 ) -> Result<Option<Instance<'tcx>>, ErrorReported> {
-    let (param_env, (def_id, substs)) = key.into_parts();
+    let (param_env, (did, substs)) = key.into_parts();
+    if let Some(did) = did.as_local() {
+        if let Some(param_did) = tcx.opt_const_param_of(did) {
+            return tcx.resolve_instance_of_const_arg(param_env.and((did, param_did, substs)));
+        }
+    }
+
+    inner_resolve_instance(tcx, param_env.and((ty::WithOptConstParam::unknown(did), substs)))
+}
+
+fn resolve_instance_of_const_arg<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    key: ty::ParamEnvAnd<'tcx, (LocalDefId, DefId, SubstsRef<'tcx>)>,
+) -> Result<Option<Instance<'tcx>>, ErrorReported> {
+    let (param_env, (did, const_param_did, substs)) = key.into_parts();
+    inner_resolve_instance(
+        tcx,
+        param_env.and((
+            ty::WithOptConstParam { did: did.to_def_id(), const_param_did: Some(const_param_did) },
+            substs,
+        )),
+    )
+}
+
+fn inner_resolve_instance<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    key: ty::ParamEnvAnd<'tcx, (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>)>,
+) -> Result<Option<Instance<'tcx>>, ErrorReported> {
+    let (param_env, (def, substs)) = key.into_parts();
 
-    debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
-    let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) {
+    debug!("resolve(def={:?}, substs={:?})", def.did, substs);
+    let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) {
         debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
-        let item = tcx.associated_item(def_id);
+        let item = tcx.associated_item(def.did);
         resolve_associated_item(tcx, &item, param_env, trait_def_id, substs)
     } else {
-        let ty = tcx.type_of(def_id);
+        let ty = tcx.type_of(def.def_id_for_type_of());
         let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, &ty);
 
         let def = match item_type.kind {
@@ -33,7 +61,7 @@ fn resolve_instance<'tcx>(
                 } =>
             {
                 debug!(" => intrinsic");
-                ty::InstanceDef::Intrinsic(def_id)
+                ty::InstanceDef::Intrinsic(def.did)
             }
             ty::FnDef(def_id, substs) if Some(def_id) == tcx.lang_items().drop_in_place_fn() => {
                 let ty = substs.type_at(0);
@@ -53,12 +81,12 @@ fn resolve_instance<'tcx>(
             }
             _ => {
                 debug!(" => free item");
-                ty::InstanceDef::Item(def_id)
+                ty::InstanceDef::Item(def)
             }
         };
         Ok(Some(Instance { def, substs }))
     };
-    debug!("resolve(def_id={:?}, substs={:?}) = {:?}", def_id, substs, result);
+    debug!("resolve(def.did={:?}, substs={:?}) = {:?}", def.did, substs, result);
     result
 }
 
@@ -182,7 +210,9 @@ fn resolve_associated_item<'tcx>(
             Some(ty::Instance::new(leaf_def.item.def_id, substs))
         }
         traits::ImplSourceGenerator(generator_data) => Some(Instance {
-            def: ty::InstanceDef::Item(generator_data.generator_def_id),
+            def: ty::InstanceDef::Item(ty::WithOptConstParam::unknown(
+                generator_data.generator_def_id,
+            )),
             substs: generator_data.substs,
         }),
         traits::ImplSourceClosure(closure_data) => {
@@ -244,5 +274,6 @@ fn resolve_associated_item<'tcx>(
 }
 
 pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { resolve_instance, ..*providers };
+    *providers =
+        ty::query::Providers { resolve_instance, resolve_instance_of_const_arg, ..*providers };
 }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 616f5d90395..37f48f82ea6 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -886,8 +886,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     }
                 }
                 (GenericParamDefKind::Const, GenericArg::Const(ct)) => {
-                    let ct_def_id = tcx.hir().local_def_id(ct.value.hir_id);
-                    ty::Const::from_anon_const(tcx, ct_def_id).into()
+                    ty::Const::from_opt_const_arg_anon_const(
+                        tcx,
+                        ty::WithOptConstParam {
+                            did: tcx.hir().local_def_id(ct.value.hir_id),
+                            const_param_did: Some(param.def_id),
+                        },
+                    )
+                    .into()
                 }
                 _ => unreachable!(),
             },
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 1c3d23a3a24..0ca85b5165e 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -325,7 +325,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                 }
                 (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => self.to_ty(ty).into(),
                 (GenericParamDefKind::Const, GenericArg::Const(ct)) => {
-                    self.to_const(&ct.value).into()
+                    self.const_arg_to_const(&ct.value, param.def_id).into()
                 }
                 _ => unreachable!(),
             },
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index bc01da324b6..9a8d78940ba 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -764,6 +764,7 @@ pub fn provide(providers: &mut Providers) {
     method::provide(providers);
     *providers = Providers {
         typeck_item_bodies,
+        typeck_tables_of_const_arg,
         typeck_tables_of,
         diagnostic_only_typeck_tables_of,
         has_typeck_tables,
@@ -955,9 +956,21 @@ where
     val.fold_with(&mut FixupFolder { tcx })
 }
 
+fn typeck_tables_of_const_arg<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    (did, param_did): (LocalDefId, DefId),
+) -> &ty::TypeckTables<'tcx> {
+    let fallback = move || tcx.type_of(param_did);
+    typeck_tables_of_with_fallback(tcx, did, fallback)
+}
+
 fn typeck_tables_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckTables<'tcx> {
-    let fallback = move || tcx.type_of(def_id.to_def_id());
-    typeck_tables_of_with_fallback(tcx, def_id, fallback)
+    if let Some(param_did) = tcx.opt_const_param_of(def_id) {
+        tcx.typeck_tables_of_const_arg((def_id, param_did))
+    } else {
+        let fallback = move || tcx.type_of(def_id.to_def_id());
+        typeck_tables_of_with_fallback(tcx, def_id, fallback)
+    }
 }
 
 /// Used only to get `TypeckTables` for type inference during error recovery.
@@ -3542,6 +3555,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         c
     }
 
+    pub fn const_arg_to_const(
+        &self,
+        ast_c: &hir::AnonConst,
+        param_def_id: DefId,
+    ) -> &'tcx ty::Const<'tcx> {
+        let const_def = ty::WithOptConstParam {
+            did: self.tcx.hir().local_def_id(ast_c.hir_id),
+            const_param_did: Some(param_def_id),
+        };
+        let c = ty::Const::from_opt_const_arg_anon_const(self.tcx, const_def);
+        self.register_wf_obligation(
+            c.into(),
+            self.tcx.hir().span(ast_c.hir_id),
+            ObligationCauseCode::MiscObligation,
+        );
+        c
+    }
+
     // If the type given by the user has free regions, save it for later, since
     // NLL would like to enforce those. Also pass in types that involve
     // projections, since those can resolve to `'static` bounds (modulo #54940,
@@ -5655,7 +5686,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         self.to_ty(ty).into()
                     }
                     (GenericParamDefKind::Const, GenericArg::Const(ct)) => {
-                        self.to_const(&ct.value).into()
+                        self.const_arg_to_const(&ct.value, param.def_id).into()
                     }
                     _ => unreachable!(),
                 },
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 19c556942af..845a4fcafc2 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -423,8 +423,11 @@ fn check_type_defn<'tcx, F>(
                 fcx.register_predicate(traits::Obligation::new(
                     cause,
                     fcx.param_env,
-                    ty::PredicateKind::ConstEvaluatable(discr_def_id.to_def_id(), discr_substs)
-                        .to_predicate(fcx.tcx),
+                    ty::PredicateKind::ConstEvaluatable(
+                        ty::WithOptConstParam::unknown(discr_def_id.to_def_id()),
+                        discr_substs,
+                    )
+                    .to_predicate(fcx.tcx),
                 ));
             }
         }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 625b72091a6..4354996614b 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -64,6 +64,7 @@ fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
 
 pub fn provide(providers: &mut Providers) {
     *providers = Providers {
+        opt_const_param_of: type_of::opt_const_param_of,
         type_of: type_of::type_of,
         generics_of,
         predicates_of,
diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs
index 3dd9c9c5c39..c265fadb82f 100644
--- a/src/librustc_typeck/collect/type_of.rs
+++ b/src/librustc_typeck/collect/type_of.rs
@@ -17,29 +17,141 @@ use rustc_trait_selection::traits;
 use super::ItemCtxt;
 use super::{bad_placeholder_type, is_suggestable_infer_ty};
 
+/// Computes the relevant generic parameter for a potential generic const argument.
+///
+/// This should be called using the query `tcx.opt_const_param_of`.
+pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
+    use hir::*;
+
+    let hir_id = tcx.hir().as_local_hir_id(def_id);
+
+    if let Node::AnonConst(_) = tcx.hir().get(hir_id) {
+        let parent_node_id = tcx.hir().get_parent_node(hir_id);
+        let parent_node = tcx.hir().get(parent_node_id);
+
+        match parent_node {
+            Node::Expr(&Expr {
+                kind:
+                    ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)),
+                ..
+            }) => {
+                let body_owner = tcx.hir().local_def_id(tcx.hir().enclosing_body_owner(hir_id));
+                let tables = tcx.typeck_tables_of(body_owner);
+                // This may fail in case the method/path does not actually exist.
+                // As there is no relevant param for `def_id`, we simply return
+                // `None` here.
+                let type_dependent_def = tables.type_dependent_def_id(parent_node_id)?;
+                let idx = segment
+                    .args
+                    .and_then(|args| {
+                        args.args
+                            .iter()
+                            .filter(|arg| arg.is_const())
+                            .position(|arg| arg.id() == hir_id)
+                    })
+                    .unwrap_or_else(|| {
+                        bug!("no arg matching AnonConst in segment");
+                    });
+
+                tcx.generics_of(type_dependent_def)
+                    .params
+                    .iter()
+                    .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const))
+                    .nth(idx)
+                    .map(|param| param.def_id)
+            }
+
+            Node::Ty(&Ty { kind: TyKind::Path(_), .. })
+            | Node::Expr(&Expr { kind: ExprKind::Struct(..), .. })
+            | Node::Expr(&Expr { kind: ExprKind::Path(_), .. })
+            | Node::TraitRef(..) => {
+                let path = match parent_node {
+                    Node::Ty(&Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. })
+                    | Node::TraitRef(&TraitRef { path, .. }) => &*path,
+                    Node::Expr(&Expr {
+                        kind:
+                            ExprKind::Path(QPath::Resolved(_, path))
+                            | ExprKind::Struct(&QPath::Resolved(_, path), ..),
+                        ..
+                    }) => {
+                        let body_owner =
+                            tcx.hir().local_def_id(tcx.hir().enclosing_body_owner(hir_id));
+                        let _tables = tcx.typeck_tables_of(body_owner);
+                        &*path
+                    }
+                    _ => span_bug!(DUMMY_SP, "unexpected const parent path {:?}", parent_node),
+                };
+
+                // We've encountered an `AnonConst` in some path, so we need to
+                // figure out which generic parameter it corresponds to and return
+                // the relevant type.
+
+                let (arg_index, segment) = path
+                    .segments
+                    .iter()
+                    .filter_map(|seg| seg.args.map(|args| (args.args, seg)))
+                    .find_map(|(args, seg)| {
+                        args.iter()
+                            .filter(|arg| arg.is_const())
+                            .position(|arg| arg.id() == hir_id)
+                            .map(|index| (index, seg))
+                    })
+                    .unwrap_or_else(|| {
+                        bug!("no arg matching AnonConst in path");
+                    });
+
+                // Try to use the segment resolution if it is valid, otherwise we
+                // default to the path resolution.
+                let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res);
+                let generics = match res {
+                    Res::Def(DefKind::Ctor(..), def_id) => {
+                        tcx.generics_of(tcx.parent(def_id).unwrap())
+                    }
+                    Res::Def(_, def_id) => tcx.generics_of(def_id),
+                    Res::Err => {
+                        tcx.sess.delay_span_bug(tcx.def_span(def_id), "anon const with Res::Err");
+                        return None;
+                    }
+                    _ => span_bug!(
+                        DUMMY_SP,
+                        "unexpected anon const res {:?} in path: {:?}",
+                        res,
+                        path,
+                    ),
+                };
+
+                generics
+                    .params
+                    .iter()
+                    .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const))
+                    .nth(arg_index)
+                    .map(|param| param.def_id)
+            }
+            _ => None,
+        }
+    } else {
+        None
+    }
+}
+
 pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
+    let def_id = def_id.expect_local();
     use rustc_hir::*;
 
-    let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+    let hir_id = tcx.hir().as_local_hir_id(def_id);
 
-    let icx = ItemCtxt::new(tcx, def_id);
+    let icx = ItemCtxt::new(tcx, def_id.to_def_id());
 
     match tcx.hir().get(hir_id) {
         Node::TraitItem(item) => match item.kind {
             TraitItemKind::Fn(..) => {
-                let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                tcx.mk_fn_def(def_id, substs)
+                let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+                tcx.mk_fn_def(def_id.to_def_id(), substs)
             }
             TraitItemKind::Const(ref ty, body_id) => body_id
                 .and_then(|body_id| {
                     if is_suggestable_infer_ty(ty) {
-                        Some(infer_placeholder_type(
-                            tcx,
-                            def_id.expect_local(),
-                            body_id,
-                            ty.span,
-                            item.ident,
-                        ))
+                        Some(infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident))
                     } else {
                         None
                     }
@@ -53,12 +165,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
 
         Node::ImplItem(item) => match item.kind {
             ImplItemKind::Fn(..) => {
-                let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                tcx.mk_fn_def(def_id, substs)
+                let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+                tcx.mk_fn_def(def_id.to_def_id(), substs)
             }
             ImplItemKind::Const(ref ty, body_id) => {
                 if is_suggestable_infer_ty(ty) {
-                    infer_placeholder_type(tcx, def_id.expect_local(), body_id, ty.span, item.ident)
+                    infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)
                 } else {
                     icx.to_ty(ty)
                 }
@@ -76,13 +188,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
             match item.kind {
                 ItemKind::Static(ref ty, .., body_id) | ItemKind::Const(ref ty, body_id) => {
                     if is_suggestable_infer_ty(ty) {
-                        infer_placeholder_type(
-                            tcx,
-                            def_id.expect_local(),
-                            body_id,
-                            ty.span,
-                            item.ident,
-                        )
+                        infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)
                     } else {
                         icx.to_ty(ty)
                     }
@@ -91,26 +197,26 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     icx.to_ty(self_ty)
                 }
                 ItemKind::Fn(..) => {
-                    let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                    tcx.mk_fn_def(def_id, substs)
+                    let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+                    tcx.mk_fn_def(def_id.to_def_id(), substs)
                 }
                 ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
                     let def = tcx.adt_def(def_id);
-                    let substs = InternalSubsts::identity_for_item(tcx, def_id);
+                    let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
                     tcx.mk_adt(def, substs)
                 }
                 ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::Binding, .. }) => {
-                    let_position_impl_trait_type(tcx, def_id.expect_local())
+                    let_position_impl_trait_type(tcx, def_id)
                 }
                 ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => {
-                    find_opaque_ty_constraints(tcx, def_id.expect_local())
+                    find_opaque_ty_constraints(tcx, def_id)
                 }
                 // Opaque types desugared from `impl Trait`.
                 ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: Some(owner), .. }) => {
                     let concrete_ty = tcx
                         .mir_borrowck(owner.expect_local())
                         .concrete_opaque_types
-                        .get(&def_id)
+                        .get(&def_id.to_def_id())
                         .map(|opaque| opaque.concrete_type)
                         .unwrap_or_else(|| {
                             tcx.sess.delay_span_bug(
@@ -132,8 +238,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                                 // resolves to itself. Return the non-revealed
                                 // type, which should result in E0720.
                                 tcx.mk_opaque(
-                                    def_id,
-                                    InternalSubsts::identity_for_item(tcx, def_id),
+                                    def_id.to_def_id(),
+                                    InternalSubsts::identity_for_item(tcx, def_id.to_def_id()),
                                 )
                             }
                         });
@@ -158,11 +264,11 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
 
         Node::ForeignItem(foreign_item) => match foreign_item.kind {
             ForeignItemKind::Fn(..) => {
-                let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                tcx.mk_fn_def(def_id, substs)
+                let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+                tcx.mk_fn_def(def_id.to_def_id(), substs)
             }
             ForeignItemKind::Static(ref t, _) => icx.to_ty(t),
-            ForeignItemKind::Type => tcx.mk_foreign(def_id),
+            ForeignItemKind::Type => tcx.mk_foreign(def_id.to_def_id()),
         },
 
         Node::Ctor(&ref def) | Node::Variant(Variant { data: ref def, .. }) => match *def {
@@ -170,23 +276,29 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                 tcx.type_of(tcx.hir().get_parent_did(hir_id).to_def_id())
             }
             VariantData::Tuple(..) => {
-                let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                tcx.mk_fn_def(def_id, substs)
+                let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+                tcx.mk_fn_def(def_id.to_def_id(), substs)
             }
         },
 
         Node::Field(field) => icx.to_ty(&field.ty),
 
         Node::Expr(&Expr { kind: ExprKind::Closure(.., gen), .. }) => {
-            let substs = InternalSubsts::identity_for_item(tcx, def_id);
+            let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
             if let Some(movability) = gen {
-                tcx.mk_generator(def_id, substs, movability)
+                tcx.mk_generator(def_id.to_def_id(), substs, movability)
             } else {
-                tcx.mk_closure(def_id, substs)
+                tcx.mk_closure(def_id.to_def_id(), substs)
             }
         }
 
         Node::AnonConst(_) => {
+            if let Some(param) = tcx.opt_const_param_of(def_id) {
+                // We defer to `type_of` of the corresponding parameter
+                // for generic arguments.
+                return tcx.type_of(param);
+            }
+
             let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
             match parent_node {
                 Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. })
@@ -203,94 +315,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     .discr_type()
                     .to_ty(tcx),
 
-                Node::Ty(&Ty { kind: TyKind::Path(_), .. })
-                | Node::Expr(&Expr { kind: ExprKind::Struct(..) | ExprKind::Path(_), .. })
-                | Node::TraitRef(..) => {
-                    let path = match parent_node {
-                        Node::Ty(&Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. })
-                        | Node::Expr(&Expr {
-                            kind:
-                                ExprKind::Path(QPath::Resolved(_, path))
-                                | ExprKind::Struct(&QPath::Resolved(_, path), ..),
-                            ..
-                        })
-                        | Node::TraitRef(&TraitRef { path, .. }) => &*path,
-                        _ => {
-                            return tcx.ty_error_with_message(
-                                DUMMY_SP,
-                                &format!("unexpected const parent path {:?}", parent_node),
-                            );
-                        }
-                    };
-
-                    // We've encountered an `AnonConst` in some path, so we need to
-                    // figure out which generic parameter it corresponds to and return
-                    // the relevant type.
-
-                    let (arg_index, segment) = path
-                        .segments
-                        .iter()
-                        .filter_map(|seg| seg.args.as_ref().map(|args| (args.args, seg)))
-                        .find_map(|(args, seg)| {
-                            args.iter()
-                                .filter(|arg| arg.is_const())
-                                .enumerate()
-                                .filter(|(_, arg)| arg.id() == hir_id)
-                                .map(|(index, _)| (index, seg))
-                                .next()
-                        })
-                        .unwrap_or_else(|| {
-                            bug!("no arg matching AnonConst in path");
-                        });
-
-                    // Try to use the segment resolution if it is valid, otherwise we
-                    // default to the path resolution.
-                    let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res);
-                    let generics = match res {
-                        Res::Def(DefKind::Ctor(..), def_id) => {
-                            tcx.generics_of(tcx.parent(def_id).unwrap())
-                        }
-                        Res::Def(_, def_id) => tcx.generics_of(def_id),
-                        res => {
-                            return tcx.ty_error_with_message(
-                                DUMMY_SP,
-                                &format!(
-                                    "unexpected anon const res {:?} in path: {:?}",
-                                    res, path,
-                                ),
-                                );
-                        }
-                    };
-
-                    let ty = generics
-                        .params
-                        .iter()
-                        .filter(|param| {
-                            if let ty::GenericParamDefKind::Const = param.kind {
-                                true
-                            } else {
-                                false
-                            }
-                        })
-                        .nth(arg_index)
-                        .map(|param| tcx.type_of(param.def_id));
-
-                    if let Some(ty) = ty {
-                        ty
-                    } else {
-                        // This is no generic parameter associated with the arg. This is
-                        // probably from an extra arg where one is not needed.
-                        tcx.ty_error_with_message(
-                            DUMMY_SP,
-                            &format!(
-                                "missing generic parameter for `AnonConst`, \
-                                 parent: {:?}, res: {:?}",
-                                parent_node, res
-                            ),
-                        )
-                    }
-                }
-
                 x => tcx.ty_error_with_message(
                     DUMMY_SP,
                     &format!("unexpected const parent in type_of_def_id(): {:?}", x),
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 832b2420c23..52c30668826 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -466,12 +466,12 @@ pub fn name_from_pat(p: &hir::Pat<'_>) -> String {
 
 pub fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String {
     match n.val {
-        ty::ConstKind::Unevaluated(def_id, _, promoted) => {
-            let mut s = if let Some(def_id) = def_id.as_local() {
-                let hir_id = cx.tcx.hir().as_local_hir_id(def_id);
+        ty::ConstKind::Unevaluated(def, _, promoted) => {
+            let mut s = if let Some(def) = def.as_local() {
+                let hir_id = cx.tcx.hir().as_local_hir_id(def.did);
                 print_const_expr(cx, cx.tcx.hir().body_owned_by(hir_id))
             } else {
-                inline::print_inlined_const(cx, def_id)
+                inline::print_inlined_const(cx, def.did)
             };
             if let Some(promoted) = promoted {
                 s.push_str(&format!("::{:?}", promoted))
diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs
index 3706ab4a020..73d5bcf21a2 100644
--- a/src/test/incremental/hashes/call_expressions.rs
+++ b/src/test/incremental/hashes/call_expressions.rs
@@ -25,7 +25,7 @@ pub fn change_callee_function() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_callee_function() {
     callee2(1, 2)
@@ -40,7 +40,7 @@ pub fn change_argument_function() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_argument_function() {
     callee1(1, 3)
@@ -81,7 +81,7 @@ pub fn change_callee_method() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_callee_method() {
     let s = Struct;
@@ -98,7 +98,7 @@ pub fn change_argument_method() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_argument_method() {
     let s = Struct;
@@ -115,7 +115,7 @@ pub fn change_ufcs_callee_method() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_ufcs_callee_method() {
     let s = Struct;
@@ -132,7 +132,7 @@ pub fn change_argument_method_ufcs() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_argument_method_ufcs() {
     let s = Struct;
@@ -149,7 +149,7 @@ pub fn change_to_ufcs() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 // One might think this would be expanded in the hir_owner_nodes/Mir, but it actually
 // results in slightly different hir_owner/Mir.
@@ -171,7 +171,7 @@ pub mod change_ufcs_callee_indirectly {
     #[cfg(not(cfail1))]
     use super::Struct2 as Struct;
 
-    #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
 
 
diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs
index b1e9ed678c4..a4a3ba779c0 100644
--- a/src/test/incremental/hashes/closure_expressions.rs
+++ b/src/test/incremental/hashes/closure_expressions.rs
@@ -37,7 +37,7 @@ pub fn add_parameter() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_parameter() {
     let x = 0u32;
@@ -53,7 +53,7 @@ pub fn change_parameter_pattern() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_parameter_pattern() {
     let _ = |(x,): (u32,)| x;
@@ -101,7 +101,7 @@ pub fn change_parameter_type() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_parameter_type() {
     let closure = |x: u16| (x as u64) + 1;
diff --git a/src/test/incremental/hashes/enum_constructors.rs b/src/test/incremental/hashes/enum_constructors.rs
index 2c07cbcb205..398866bef79 100644
--- a/src/test/incremental/hashes/enum_constructors.rs
+++ b/src/test/incremental/hashes/enum_constructors.rs
@@ -34,7 +34,7 @@ pub fn change_field_value_struct_like() -> Enum {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_value_struct_like() -> Enum {
     Enum::Struct {
@@ -96,7 +96,7 @@ pub fn change_constructor_path_struct_like() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_struct_like() {
     let _ = Enum2::Struct {
@@ -119,7 +119,7 @@ pub fn change_constructor_variant_struct_like() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_variant_struct_like() {
     let _ = Enum2::Struct2 {
@@ -139,7 +139,7 @@ pub mod change_constructor_path_indirectly_struct_like {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,mir_built,\
+        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\
                 typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
@@ -161,7 +161,7 @@ pub mod change_constructor_variant_indirectly_struct_like {
     #[cfg(not(cfail1))]
     use super::Enum2::Struct2 as Variant;
 
-    #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Enum2 {
         Variant {
@@ -180,7 +180,7 @@ pub fn change_field_value_tuple_like() -> Enum {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_value_tuple_like() -> Enum {
     Enum::Tuple(0, 1, 3)
@@ -197,7 +197,7 @@ pub fn change_constructor_path_tuple_like() {
 #[cfg(not(cfail1))]
 #[rustc_clean(
     cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of"
+    except="hir_owner_nodes,optimized_mir,typeck_tables_of"
 )]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_tuple_like() {
@@ -215,7 +215,7 @@ pub fn change_constructor_variant_tuple_like() {
 #[cfg(not(cfail1))]
 #[rustc_clean(
     cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of"
+    except="hir_owner_nodes,optimized_mir,typeck_tables_of"
 )]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_variant_tuple_like() {
@@ -232,7 +232,7 @@ pub mod change_constructor_path_indirectly_tuple_like {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,mir_built,\
+        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\
                 typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
@@ -251,7 +251,7 @@ pub mod change_constructor_variant_indirectly_tuple_like {
     #[cfg(not(cfail1))]
     use super::Enum2::Tuple2 as Variant;
 
-    #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Enum2 {
         Variant(0, 1, 2)
@@ -278,7 +278,7 @@ pub fn change_constructor_path_c_like() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_c_like() {
     let _x = Clike2::B;
@@ -293,7 +293,7 @@ pub fn change_constructor_variant_c_like() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_variant_c_like() {
     let _x = Clike::C;
@@ -309,7 +309,7 @@ pub mod change_constructor_path_indirectly_c_like {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,mir_built,\
+        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\
                 typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
@@ -328,7 +328,7 @@ pub mod change_constructor_variant_indirectly_c_like {
     #[cfg(not(cfail1))]
     use super::Clike::B as Variant;
 
-    #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Clike {
         Variant
diff --git a/src/test/incremental/hashes/exported_vs_not.rs b/src/test/incremental/hashes/exported_vs_not.rs
index 4ea58705017..40b6925bc72 100644
--- a/src/test/incremental/hashes/exported_vs_not.rs
+++ b/src/test/incremental/hashes/exported_vs_not.rs
@@ -16,7 +16,7 @@ pub fn body_not_exported_to_metadata() -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn body_not_exported_to_metadata() -> u32 {
     2
@@ -35,7 +35,7 @@ pub fn body_exported_to_metadata_because_of_inline() -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[inline]
 pub fn body_exported_to_metadata_because_of_inline() -> u32 {
@@ -55,7 +55,7 @@ pub fn body_exported_to_metadata_because_of_generic() -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[inline]
 pub fn body_exported_to_metadata_because_of_generic() -> u32 {
diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs
index d3d5a69c171..18ba48e7b4b 100644
--- a/src/test/incremental/hashes/for_loops.rs
+++ b/src/test/incremental/hashes/for_loops.rs
@@ -25,7 +25,7 @@ pub fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_body() {
     let mut _x = 0;
@@ -48,7 +48,7 @@ pub fn change_iteration_variable_name() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_iteration_variable_name() {
     let mut _x = 0;
@@ -71,7 +71,7 @@ pub fn change_iteration_variable_pattern() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_iteration_variable_pattern() {
     let mut _x = 0;
@@ -94,7 +94,7 @@ pub fn change_iterable() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, promoted_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, promoted_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_iterable() {
     let mut _x = 0;
@@ -116,7 +116,7 @@ pub fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_break() {
     let mut _x = 0;
@@ -187,7 +187,7 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -237,7 +237,7 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_label() {
     let mut _x = 0;
@@ -262,7 +262,7 @@ pub fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs
index a6b936fcbcf..2690b0bd6ed 100644
--- a/src/test/incremental/hashes/function_interfaces.rs
+++ b/src/test/incremental/hashes/function_interfaces.rs
@@ -22,7 +22,7 @@ pub fn add_parameter() {}
 #[cfg(not(cfail1))]
 #[rustc_clean(
     cfg = "cfail2",
-    except = "hir_owner, hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+    except = "hir_owner, hir_owner_nodes, optimized_mir, typeck_tables_of, fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
 pub fn add_parameter(p: i32) {}
@@ -45,7 +45,7 @@ pub fn type_of_parameter(p: i32) {}
 #[cfg(not(cfail1))]
 #[rustc_clean(
     cfg = "cfail2",
-    except = "hir_owner, hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+    except = "hir_owner, hir_owner_nodes, optimized_mir, typeck_tables_of, fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
 pub fn type_of_parameter(p: i64) {}
@@ -58,7 +58,7 @@ pub fn type_of_parameter_ref(p: &i32) {}
 #[cfg(not(cfail1))]
 #[rustc_clean(
     cfg = "cfail2",
-    except = "hir_owner, hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+    except = "hir_owner, hir_owner_nodes, optimized_mir, typeck_tables_of, fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
 pub fn type_of_parameter_ref(p: &mut i32) {}
@@ -71,7 +71,7 @@ pub fn order_of_parameters(p1: i32, p2: i64) {}
 #[cfg(not(cfail1))]
 #[rustc_clean(
     cfg = "cfail2",
-    except = "hir_owner, hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+    except = "hir_owner, hir_owner_nodes, optimized_mir, typeck_tables_of, fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
 pub fn order_of_parameters(p2: i64, p1: i32) {}
@@ -84,7 +84,7 @@ pub fn make_unsafe() {}
 #[cfg(not(cfail1))]
 #[rustc_clean(
     cfg = "cfail2",
-    except = "hir_owner, hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+    except = "hir_owner, hir_owner_nodes, optimized_mir, typeck_tables_of, fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
 pub unsafe fn make_unsafe() {}
@@ -274,7 +274,7 @@ pub mod change_return_type_indirectly {
 
     #[rustc_clean(
         cfg = "cfail2",
-        except = "hir_owner, hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+        except = "hir_owner, hir_owner_nodes, optimized_mir, typeck_tables_of, fn_sig"
     )]
     #[rustc_clean(cfg = "cfail3")]
     pub fn indirect_return_type() -> ReturnType {
@@ -292,7 +292,7 @@ pub mod change_parameter_type_indirectly {
 
     #[rustc_clean(
         cfg = "cfail2",
-        except = "hir_owner, hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+        except = "hir_owner, hir_owner_nodes, optimized_mir, typeck_tables_of, fn_sig"
     )]
     #[rustc_clean(cfg = "cfail3")]
     pub fn indirect_parameter_type(p: ParameterType) {}
diff --git a/src/test/incremental/hashes/if_expressions.rs b/src/test/incremental/hashes/if_expressions.rs
index 29b3f1f5b1d..8faa91e465b 100644
--- a/src/test/incremental/hashes/if_expressions.rs
+++ b/src/test/incremental/hashes/if_expressions.rs
@@ -25,7 +25,7 @@ pub fn change_condition(x: bool) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_condition(x: bool) -> u32 {
     if !x {
@@ -46,7 +46,7 @@ pub fn change_then_branch(x: bool) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_then_branch(x: bool) -> u32 {
     if x {
@@ -69,7 +69,7 @@ pub fn change_else_branch(x: bool) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_else_branch(x: bool) -> u32 {
     if x {
@@ -120,7 +120,7 @@ pub fn change_condition_if_let(x: Option<u32>) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_condition_if_let(x: Option<u32>) -> u32 {
     if let Some(_) = x {
@@ -143,7 +143,7 @@ pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
     if let Some(x) = x {
@@ -166,7 +166,7 @@ pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
     if let Some(x) = x {
diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs
index a9c8457f7f2..4244e0c2386 100644
--- a/src/test/incremental/hashes/inherent_impls.rs
+++ b/src/test/incremental/hashes/inherent_impls.rs
@@ -44,7 +44,7 @@ impl Foo {
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="hir_owner_nodes,optimized_mir,promoted_mir,mir_built,typeck_tables_of"
+        except="hir_owner_nodes,optimized_mir,promoted_mir,typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn method_body() {
@@ -68,7 +68,7 @@ impl Foo {
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="hir_owner_nodes,optimized_mir,promoted_mir,mir_built,typeck_tables_of"
+        except="hir_owner_nodes,optimized_mir,promoted_mir,typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     #[inline]
@@ -120,7 +120,7 @@ impl Foo {
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="hir_owner,hir_owner_nodes,fn_sig,typeck_tables_of,optimized_mir,mir_built"
+        except="hir_owner,hir_owner_nodes,fn_sig,typeck_tables_of,optimized_mir"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn method_selfmutness(&mut self) { }
@@ -160,7 +160,7 @@ impl Foo {
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="hir_owner,hir_owner_nodes,fn_sig,typeck_tables_of,optimized_mir,mir_built"
+        except="hir_owner,hir_owner_nodes,fn_sig,typeck_tables_of,optimized_mir"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_method_parameter(&self, _: i32) { }
@@ -178,7 +178,7 @@ impl Foo {
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
     #[rustc_clean(cfg="cfail3")]
     pub fn change_method_parameter_name(&self, b: i64) { }
 }
@@ -197,7 +197,7 @@ impl Foo {
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,mir_built,typeck_tables_of")]
+        except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
     pub fn change_method_return_type(&self) -> u8 { 0 }
 }
@@ -232,7 +232,7 @@ impl Foo {
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
     #[rustc_clean(cfg="cfail3")]
     pub fn change_method_parameter_order(&self, b: i64, a: i64) { }
 }
@@ -251,7 +251,7 @@ impl Foo {
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="hir_owner,hir_owner_nodes,fn_sig,typeck_tables_of,optimized_mir,mir_built"
+        except="hir_owner,hir_owner_nodes,fn_sig,typeck_tables_of,optimized_mir"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub unsafe fn make_method_unsafe(&self) { }
@@ -453,7 +453,7 @@ impl Bar<u32> {
 impl<T> Bar<T> {
     #[rustc_clean(
         cfg="cfail2",
-        except="generics_of,fn_sig,typeck_tables_of,type_of,optimized_mir,mir_built"
+        except="generics_of,fn_sig,typeck_tables_of,type_of,optimized_mir"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_type_parameter_to_impl(&self) { }
@@ -471,7 +471,7 @@ impl Bar<u32> {
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
 impl Bar<u64> {
-    #[rustc_clean(cfg="cfail2", except="fn_sig,optimized_mir,mir_built,typeck_tables_of")]
+    #[rustc_clean(cfg="cfail2", except="fn_sig,optimized_mir,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
     pub fn change_impl_self_type(&self) { }
 }
diff --git a/src/test/incremental/hashes/inline_asm.rs b/src/test/incremental/hashes/inline_asm.rs
index 3eaffc44061..7fd9975bc22 100644
--- a/src/test/incremental/hashes/inline_asm.rs
+++ b/src/test/incremental/hashes/inline_asm.rs
@@ -33,7 +33,7 @@ pub fn change_template(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_template(a: i32) -> i32 {
@@ -69,7 +69,7 @@ pub fn change_output(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_output(a: i32) -> i32 {
@@ -105,7 +105,7 @@ pub fn change_input(_a: i32, _b: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_input(_a: i32, _b: i32) -> i32 {
@@ -140,7 +140,7 @@ pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
@@ -175,7 +175,7 @@ pub fn change_clobber(_a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_clobber(_a: i32) -> i32 {
@@ -210,7 +210,7 @@ pub fn change_options(_a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_options(_a: i32) -> i32 {
diff --git a/src/test/incremental/hashes/let_expressions.rs b/src/test/incremental/hashes/let_expressions.rs
index 846bfc6d0e4..b833e621a91 100644
--- a/src/test/incremental/hashes/let_expressions.rs
+++ b/src/test/incremental/hashes/let_expressions.rs
@@ -22,7 +22,7 @@ pub fn change_name() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,mir_built,optimized_mir")]
+    except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_name() {
     let _y = 2u64;
@@ -38,7 +38,7 @@ pub fn add_type() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck_tables_of,mir_built")]
+    except="hir_owner_nodes,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_type() {
     let _x: u32 = 2u32;
@@ -54,7 +54,7 @@ pub fn change_type() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_nodes,typeck_tables_of,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_type() {
     let _x: u8 = 2;
@@ -70,7 +70,7 @@ pub fn change_mutability_of_reference_type() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_nodes,typeck_tables_of,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_mutability_of_reference_type() {
     let _x: &mut u64;
@@ -86,7 +86,7 @@ pub fn change_mutability_of_slot() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_nodes,typeck_tables_of,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_mutability_of_slot() {
     let _x: u64 = 0;
@@ -102,7 +102,7 @@ pub fn change_simple_binding_to_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_nodes,typeck_tables_of,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_simple_binding_to_pattern() {
     let (_a, _b) = (0u8, 'x');
@@ -118,7 +118,7 @@ pub fn change_name_in_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,mir_built,optimized_mir")]
+    except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_name_in_pattern() {
     let (_a, _c) = (1u8, 'y');
@@ -134,7 +134,7 @@ pub fn add_ref_in_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_nodes,typeck_tables_of,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_ref_in_pattern() {
     let (ref _a, _b) = (1u8, 'y');
@@ -150,7 +150,7 @@ pub fn add_amp_in_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_nodes,typeck_tables_of,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_amp_in_pattern() {
     let (&_a, _b) = (&1u8, 'y');
@@ -166,7 +166,7 @@ pub fn change_mutability_of_binding_in_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_nodes,typeck_tables_of,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_mutability_of_binding_in_pattern() {
     let (mut _a, _b) = (99u8, 'q');
@@ -182,7 +182,7 @@ pub fn add_initializer() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_nodes,typeck_tables_of,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_initializer() {
     let _x: i16 = 3i16;
@@ -198,7 +198,7 @@ pub fn change_initializer() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,mir_built,optimized_mir")]
+    except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_initializer() {
     let _x = 5u16;
diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs
index 65db89eb976..4196fd68cb0 100644
--- a/src/test/incremental/hashes/loop_expressions.rs
+++ b/src/test/incremental/hashes/loop_expressions.rs
@@ -25,7 +25,7 @@ pub fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_body() {
     let mut _x = 0;
@@ -47,7 +47,7 @@ pub fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_break() {
     let mut _x = 0;
@@ -118,7 +118,7 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -168,7 +168,7 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_label() {
     let mut _x = 0;
@@ -193,7 +193,7 @@ pub fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
diff --git a/src/test/incremental/hashes/match_expressions.rs b/src/test/incremental/hashes/match_expressions.rs
index 033723a4c77..1e194014796 100644
--- a/src/test/incremental/hashes/match_expressions.rs
+++ b/src/test/incremental/hashes/match_expressions.rs
@@ -26,7 +26,7 @@ pub fn add_arm(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_arm(x: u32) -> u32 {
     match x {
@@ -51,7 +51,7 @@ pub fn change_order_of_arms(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,mir_built,optimized_mir")]
+    except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_order_of_arms(x: u32) -> u32 {
     match x {
@@ -75,7 +75,7 @@ pub fn add_guard_clause(x: u32, y: bool) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_guard_clause(x: u32, y: bool) -> u32 {
     match x {
@@ -99,7 +99,7 @@ pub fn change_guard_clause(x: u32, y: bool) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_guard_clause(x: u32, y: bool) -> u32 {
     match x {
@@ -123,7 +123,7 @@ pub fn add_at_binding(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_at_binding(x: u32) -> u32 {
     match x {
@@ -147,7 +147,7 @@ pub fn change_name_of_at_binding(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,mir_built,optimized_mir")]
+    except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_name_of_at_binding(x: u32) -> u32 {
     match x {
@@ -170,7 +170,7 @@ pub fn change_simple_name_to_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_simple_name_to_pattern(x: u32) -> u32 {
     match (x, x & 1) {
@@ -193,7 +193,7 @@ pub fn change_name_in_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,mir_built,optimized_mir")]
+    except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_name_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
@@ -216,7 +216,7 @@ pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
@@ -238,7 +238,7 @@ pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
@@ -260,7 +260,7 @@ pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")]
+except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 {
     match (&x, x & 1) {
@@ -283,7 +283,7 @@ pub fn change_rhs_of_arm(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,mir_built,optimized_mir")]
+    except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_rhs_of_arm(x: u32) -> u32 {
     match x {
@@ -307,7 +307,7 @@ pub fn add_alternative_to_arm(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_alternative_to_arm(x: u32) -> u32 {
     match x {
diff --git a/src/test/incremental/hashes/panic_exprs.rs b/src/test/incremental/hashes/panic_exprs.rs
index 9de2aaa1bfd..cc0bd45a4b4 100644
--- a/src/test/incremental/hashes/panic_exprs.rs
+++ b/src/test/incremental/hashes/panic_exprs.rs
@@ -18,7 +18,7 @@
 
 
 // Indexing expression
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn indexing(slice: &[u8]) -> u8 {
     #[cfg(cfail1)]
@@ -33,7 +33,7 @@ pub fn indexing(slice: &[u8]) -> u8 {
 
 
 // Arithmetic overflow plus
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_plus(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -48,7 +48,7 @@ pub fn arithmetic_overflow_plus(val: i32) -> i32 {
 
 
 // Arithmetic overflow minus
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_minus(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -63,7 +63,7 @@ pub fn arithmetic_overflow_minus(val: i32) -> i32 {
 
 
 // Arithmetic overflow mult
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_mult(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -78,7 +78,7 @@ pub fn arithmetic_overflow_mult(val: i32) -> i32 {
 
 
 // Arithmetic overflow negation
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_negation(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -93,7 +93,7 @@ pub fn arithmetic_overflow_negation(val: i32) -> i32 {
 
 
 // Division by zero
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn division_by_zero(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -107,7 +107,7 @@ pub fn division_by_zero(val: i32) -> i32 {
 }
 
 // Division by zero
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn mod_by_zero(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -122,7 +122,7 @@ pub fn mod_by_zero(val: i32) -> i32 {
 
 
 // shift left
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn shift_left(val: i32, shift: usize) -> i32 {
     #[cfg(cfail1)]
@@ -137,7 +137,7 @@ pub fn shift_left(val: i32, shift: usize) -> i32 {
 
 
 // shift right
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn shift_right(val: i32, shift: usize) -> i32 {
     #[cfg(cfail1)]
diff --git a/src/test/incremental/hashes/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs
index 006b712923b..9e8f5ce77bc 100644
--- a/src/test/incremental/hashes/struct_constructors.rs
+++ b/src/test/incremental/hashes/struct_constructors.rs
@@ -31,7 +31,7 @@ pub fn change_field_value_regular_struct() -> RegularStruct {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_value_regular_struct() -> RegularStruct {
     RegularStruct {
@@ -82,7 +82,7 @@ pub fn add_field_regular_struct() -> RegularStruct {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_field_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
@@ -117,7 +117,7 @@ pub fn change_field_label_regular_struct() -> RegularStruct {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_label_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
@@ -152,7 +152,7 @@ pub fn change_constructor_path_regular_struct() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_regular_struct() {
     let _ = RegularStruct2 {
@@ -173,7 +173,7 @@ pub mod change_constructor_path_indirectly_regular_struct {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of"
+        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Struct {
@@ -196,7 +196,7 @@ pub fn change_field_value_tuple_struct() -> TupleStruct {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_value_tuple_struct() -> TupleStruct {
     TupleStruct(0, 1, 3)
@@ -213,7 +213,7 @@ pub fn change_constructor_path_tuple_struct() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_tuple_struct() {
     let _ = TupleStruct2(0, 1, 2);
@@ -230,7 +230,7 @@ pub mod change_constructor_path_indirectly_tuple_struct {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of"
+        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Struct {
diff --git a/src/test/incremental/hashes/unary_and_binary_exprs.rs b/src/test/incremental/hashes/unary_and_binary_exprs.rs
index c8b53c27b02..325dd56b741 100644
--- a/src/test/incremental/hashes/unary_and_binary_exprs.rs
+++ b/src/test/incremental/hashes/unary_and_binary_exprs.rs
@@ -21,7 +21,7 @@ pub fn const_negation() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn const_negation() -> i32 {
     -1
@@ -36,7 +36,7 @@ pub fn const_bitwise_not() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn const_bitwise_not() -> i32 {
     !99
@@ -51,7 +51,7 @@ pub fn var_negation(x: i32, y: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn var_negation(x: i32, y: i32) -> i32 {
     -y
@@ -66,7 +66,7 @@ pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
     !y
@@ -81,7 +81,7 @@ pub fn var_deref(x: &i32, y: &i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn var_deref(x: &i32, y: &i32) -> i32 {
     *y
@@ -96,7 +96,7 @@ pub fn first_const_add() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn first_const_add() -> i32 {
     2 + 3
@@ -111,7 +111,7 @@ pub fn second_const_add() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn second_const_add() -> i32 {
     1 + 3
@@ -126,7 +126,7 @@ pub fn first_var_add(a: i32, b: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn first_var_add(a: i32, b: i32) -> i32 {
     b + 2
@@ -141,7 +141,7 @@ pub fn second_var_add(a: i32, b: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn second_var_add(a: i32, b: i32) -> i32 {
     1 + b
@@ -156,7 +156,7 @@ pub fn plus_to_minus(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn plus_to_minus(a: i32) -> i32 {
     1 - a
@@ -171,7 +171,7 @@ pub fn plus_to_mult(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn plus_to_mult(a: i32) -> i32 {
     1 * a
@@ -186,7 +186,7 @@ pub fn plus_to_div(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn plus_to_div(a: i32) -> i32 {
     1 / a
@@ -201,7 +201,7 @@ pub fn plus_to_mod(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn plus_to_mod(a: i32) -> i32 {
     1 % a
@@ -216,7 +216,7 @@ pub fn and_to_or(a: bool, b: bool) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn and_to_or(a: bool, b: bool) -> bool {
     a || b
@@ -231,7 +231,7 @@ pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
     1 | a
@@ -246,7 +246,7 @@ pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
     1 ^ a
@@ -261,7 +261,7 @@ pub fn bitwise_and_to_lshift(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn bitwise_and_to_lshift(a: i32) -> i32 {
     a << 1
@@ -276,7 +276,7 @@ pub fn bitwise_and_to_rshift(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn bitwise_and_to_rshift(a: i32) -> i32 {
     a >> 1
@@ -291,7 +291,7 @@ pub fn eq_to_uneq(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_uneq(a: i32) -> bool {
     a != 1
@@ -306,7 +306,7 @@ pub fn eq_to_lt(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_lt(a: i32) -> bool {
     a < 1
@@ -321,7 +321,7 @@ pub fn eq_to_gt(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_gt(a: i32) -> bool {
     a > 1
@@ -336,7 +336,7 @@ pub fn eq_to_le(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_le(a: i32) -> bool {
     a <= 1
@@ -351,7 +351,7 @@ pub fn eq_to_ge(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_ge(a: i32) -> bool {
     a >= 1
@@ -368,7 +368,7 @@ pub fn type_cast(a: u8) -> u64 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir,typeck_tables_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn type_cast(a: u8) -> u64 {
     let b = a as u32;
@@ -385,7 +385,7 @@ pub fn value_cast(a: u32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn value_cast(a: u32) -> i32 {
     2 as i32
@@ -403,7 +403,7 @@ pub fn place() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn place() -> i32 {
     let mut x = 10;
@@ -423,7 +423,7 @@ pub fn rvalue() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn rvalue() -> i32 {
     let mut x = 10;
@@ -440,7 +440,7 @@ pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 {
     s[j]
diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs
index 36e0fcdbe74..6608ad9c41a 100644
--- a/src/test/incremental/hashes/while_let_loops.rs
+++ b/src/test/incremental/hashes/while_let_loops.rs
@@ -25,7 +25,7 @@ pub fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_body() {
     let mut _x = 0;
@@ -48,7 +48,7 @@ pub fn change_loop_condition() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_condition() {
     let mut _x = 0;
@@ -70,7 +70,7 @@ pub fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_break() {
     let mut _x = 0;
@@ -141,7 +141,7 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -191,7 +191,7 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_label() {
     let mut _x = 0;
@@ -216,7 +216,7 @@ pub fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs
index 83f09bd7be6..0ecb0d79ae6 100644
--- a/src/test/incremental/hashes/while_loops.rs
+++ b/src/test/incremental/hashes/while_loops.rs
@@ -25,7 +25,7 @@ pub fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_body() {
     let mut _x = 0;
@@ -48,7 +48,7 @@ pub fn change_loop_condition() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_condition() {
     let mut _x = 0;
@@ -70,7 +70,7 @@ pub fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_break() {
     let mut _x = 0;
@@ -141,7 +141,7 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -191,7 +191,7 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_label() {
     let mut _x = 0;
@@ -216,7 +216,7 @@ pub fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
diff --git a/src/test/mir-opt/const-promotion-extern-static/rustc.BAR.PromoteTemps.diff b/src/test/mir-opt/const-promotion-extern-static/rustc.BAR.PromoteTemps.diff
index 5c192979a86..0e0d8ea9063 100644
--- a/src/test/mir-opt/const-promotion-extern-static/rustc.BAR.PromoteTemps.diff
+++ b/src/test/mir-opt/const-promotion-extern-static/rustc.BAR.PromoteTemps.diff
@@ -22,7 +22,7 @@
 -                                          // + ty: &i32
 -                                          // + val: Value(Scalar(alloc0))
 +                                          // + ty: &[&i32; 1]
-+                                          // + val: Unevaluated(DefId(0:6 ~ const_promotion_extern_static[317d]::BAR[0]), [], Some(promoted[0]))
++                                          // + val: Unevaluated(WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[317d]::BAR[0]), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
 -                                          // + span: $DIR/const-promotion-extern-static.rs:9:33: 9:34
 -                                          // + literal: Const { ty: &i32, val: Value(Scalar(alloc0)) }
@@ -30,7 +30,7 @@
 -         _3 = [move _4];                  // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
 -         _2 = &_3;                        // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
 +                                          // + span: $DIR/const-promotion-extern-static.rs:9:31: 9:35
-+                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(DefId(0:6 ~ const_promotion_extern_static[317d]::BAR[0]), [], Some(promoted[0])) }
++                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[317d]::BAR[0]), const_param_did: None }, [], Some(promoted[0])) }
 +         _2 = &(*_6);                     // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
           _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
           _0 = const core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44
diff --git a/src/test/mir-opt/const-promotion-extern-static/rustc.FOO.PromoteTemps.diff b/src/test/mir-opt/const-promotion-extern-static/rustc.FOO.PromoteTemps.diff
index 649cea6493e..a885b4d3bae 100644
--- a/src/test/mir-opt/const-promotion-extern-static/rustc.FOO.PromoteTemps.diff
+++ b/src/test/mir-opt/const-promotion-extern-static/rustc.FOO.PromoteTemps.diff
@@ -24,7 +24,7 @@
 -                                          // + ty: &i32
 -                                          // + val: Value(Scalar(alloc2))
 +                                          // + ty: &[&i32; 1]
-+                                          // + val: Unevaluated(DefId(0:7 ~ const_promotion_extern_static[317d]::FOO[0]), [], Some(promoted[0]))
++                                          // + val: Unevaluated(WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[317d]::FOO[0]), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
 -                                          // + span: $DIR/const-promotion-extern-static.rs:13:42: 13:43
 -                                          // + literal: Const { ty: &i32, val: Value(Scalar(alloc2)) }
@@ -32,7 +32,7 @@
 -         _3 = [move _4];                  // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
 -         _2 = &_3;                        // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
 +                                          // + span: $DIR/const-promotion-extern-static.rs:13:31: 13:46
-+                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(DefId(0:7 ~ const_promotion_extern_static[317d]::FOO[0]), [], Some(promoted[0])) }
++                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[317d]::FOO[0]), const_param_did: None }, [], Some(promoted[0])) }
 +         _2 = &(*_6);                     // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
           _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
           _0 = const core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55
diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff
index ee4d4c39f17..0f9c81943ed 100644
--- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff
@@ -28,10 +28,10 @@
           _9 = const main::promoted[0];    // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
                                            // ty::Const
                                            // + ty: &[i32; 3]
-                                           // + val: Unevaluated(DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main[0]), [], Some(promoted[0]))
+                                           // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main[0]), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
-                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main[0]), [], Some(promoted[0])) }
+                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) }
           _3 = _9;                         // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _2 = &raw const (*_3);           // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff
index 3626814fa97..da2c8dffb24 100644
--- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff
@@ -28,10 +28,10 @@
           _9 = const main::promoted[0];    // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
                                            // ty::Const
                                            // + ty: &[i32; 3]
-                                           // + val: Unevaluated(DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main[0]), [], Some(promoted[0]))
+                                           // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main[0]), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
-                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main[0]), [], Some(promoted[0])) }
+                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) }
           _3 = _9;                         // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _2 = &raw const (*_3);           // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/const_prop_fails_gracefully/rustc.main.ConstProp.diff
index 6c5fe7454b4..f3efef387a3 100644
--- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully/rustc.main.ConstProp.diff
@@ -19,10 +19,10 @@
           _3 = const main::FOO;            // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
                                            // ty::Const
                                            // + ty: &i32
-                                           // + val: Unevaluated(DefId(0:5 ~ const_prop_fails_gracefully[317d]::main[0]::FOO[0]), [], None)
+                                           // + val: Unevaluated(WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[317d]::main[0]::FOO[0]), const_param_did: None }, [], None)
                                            // mir::Constant
                                            // + span: $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
-                                           // + literal: Const { ty: &i32, val: Unevaluated(DefId(0:5 ~ const_prop_fails_gracefully[317d]::main[0]::FOO[0]), [], None) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[317d]::main[0]::FOO[0]), const_param_did: None }, [], None) }
           _2 = &raw const (*_3);           // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
           _1 = move _2 as usize (Misc);    // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:39
           StorageDead(_2);                 // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:38: 7:39
diff --git a/src/test/mir-opt/const_prop/control-flow-simplification/rustc.hello.ConstProp.diff b/src/test/mir-opt/const_prop/control-flow-simplification/rustc.hello.ConstProp.diff
index b4d1f087391..68527a86aeb 100644
--- a/src/test/mir-opt/const_prop/control-flow-simplification/rustc.hello.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/control-flow-simplification/rustc.hello.ConstProp.diff
@@ -12,11 +12,11 @@
 +         _1 = const false;                // scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:21
                                            // ty::Const
                                            // + ty: bool
--                                          // + val: Unevaluated(DefId(0:4 ~ control_flow_simplification[317d]::NeedsDrop[0]::NEEDS[0]), [bool], None)
+-                                          // + val: Unevaluated(WithOptConstParam { did: DefId(0:4 ~ control_flow_simplification[317d]::NeedsDrop[0]::NEEDS[0]), const_param_did: None }, [bool], None)
 +                                          // + val: Value(Scalar(0x00))
                                            // mir::Constant
                                            // + span: $DIR/control-flow-simplification.rs:12:8: 12:21
--                                          // + literal: Const { ty: bool, val: Unevaluated(DefId(0:4 ~ control_flow_simplification[317d]::NeedsDrop[0]::NEEDS[0]), [bool], None) }
+-                                          // + literal: Const { ty: bool, val: Unevaluated(WithOptConstParam { did: DefId(0:4 ~ control_flow_simplification[317d]::NeedsDrop[0]::NEEDS[0]), const_param_did: None }, [bool], None) }
 -         switchInt(_1) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/control-flow-simplification.rs:12:5: 14:6
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
 +         switchInt(const false) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/control-flow-simplification.rs:12:5: 14:6
diff --git a/src/test/mir-opt/const_prop/ref_deref/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref/rustc.main.ConstProp.diff
index 12e3a04d89b..ba5ac8d3ddf 100644
--- a/src/test/mir-opt/const_prop/ref_deref/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/ref_deref/rustc.main.ConstProp.diff
@@ -14,10 +14,10 @@
           _4 = const main::promoted[0];    // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
                                            // ty::Const
                                            // + ty: &i32
-                                           // + val: Unevaluated(DefId(0:3 ~ ref_deref[317d]::main[0]), [], Some(promoted[0]))
+                                           // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main[0]), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/ref_deref.rs:5:6: 5:10
-                                           // + literal: Const { ty: &i32, val: Unevaluated(DefId(0:3 ~ ref_deref[317d]::main[0]), [], Some(promoted[0])) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) }
           _2 = _4;                         // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
 -         _1 = (*_2);                      // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
 +         _1 = const 4_i32;                // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
diff --git a/src/test/mir-opt/const_prop/ref_deref/rustc.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref/rustc.main.PromoteTemps.diff
index d56f07e0f57..fa68eb34818 100644
--- a/src/test/mir-opt/const_prop/ref_deref/rustc.main.PromoteTemps.diff
+++ b/src/test/mir-opt/const_prop/ref_deref/rustc.main.PromoteTemps.diff
@@ -18,13 +18,13 @@
 -                                          // + ty: i32
 -                                          // + val: Value(Scalar(0x00000004))
 +                                          // + ty: &i32
-+                                          // + val: Unevaluated(DefId(0:3 ~ ref_deref[317d]::main[0]), [], Some(promoted[0]))
++                                          // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main[0]), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
 -                                          // + span: $DIR/ref_deref.rs:5:8: 5:9
 -                                          // + literal: Const { ty: i32, val: Value(Scalar(0x00000004)) }
 -         _2 = &_3;                        // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
 +                                          // + span: $DIR/ref_deref.rs:5:6: 5:10
-+                                          // + literal: Const { ty: &i32, val: Unevaluated(DefId(0:3 ~ ref_deref[317d]::main[0]), [], Some(promoted[0])) }
++                                          // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) }
 +         _2 = &(*_4);                     // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
 -         StorageDead(_3);                 // scope 0 at $DIR/ref_deref.rs:5:10: 5:11
diff --git a/src/test/mir-opt/const_prop/ref_deref_project/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref_project/rustc.main.ConstProp.diff
index dd2f5bd9064..483e5f1b9a4 100644
--- a/src/test/mir-opt/const_prop/ref_deref_project/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/ref_deref_project/rustc.main.ConstProp.diff
@@ -14,10 +14,10 @@
           _4 = const main::promoted[0];    // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
                                            // ty::Const
                                            // + ty: &(i32, i32)
-                                           // + val: Unevaluated(DefId(0:3 ~ ref_deref_project[317d]::main[0]), [], Some(promoted[0]))
+                                           // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main[0]), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/ref_deref_project.rs:5:6: 5:17
-                                           // + literal: Const { ty: &(i32, i32), val: Unevaluated(DefId(0:3 ~ ref_deref_project[317d]::main[0]), [], Some(promoted[0])) }
+                                           // + literal: Const { ty: &(i32, i32), val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) }
           _2 = &((*_4).1: i32);            // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17
           StorageDead(_2);                 // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18
diff --git a/src/test/mir-opt/const_prop/ref_deref_project/rustc.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref_project/rustc.main.PromoteTemps.diff
index 0b9c1caa6bd..86e6aacab45 100644
--- a/src/test/mir-opt/const_prop/ref_deref_project/rustc.main.PromoteTemps.diff
+++ b/src/test/mir-opt/const_prop/ref_deref_project/rustc.main.PromoteTemps.diff
@@ -18,7 +18,7 @@
 -                                          // + ty: i32
 -                                          // + val: Value(Scalar(0x00000004))
 +                                          // + ty: &(i32, i32)
-+                                          // + val: Unevaluated(DefId(0:3 ~ ref_deref_project[317d]::main[0]), [], Some(promoted[0]))
++                                          // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main[0]), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
 -                                          // + span: $DIR/ref_deref_project.rs:5:9: 5:10
 -                                          // + literal: Const { ty: i32, val: Value(Scalar(0x00000004)) }
@@ -30,7 +30,7 @@
 -                                          // + literal: Const { ty: i32, val: Value(Scalar(0x00000005)) }
 -         _2 = &(_3.1: i32);               // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
 +                                          // + span: $DIR/ref_deref_project.rs:5:6: 5:17
-+                                          // + literal: Const { ty: &(i32, i32), val: Unevaluated(DefId(0:3 ~ ref_deref_project[317d]::main[0]), [], Some(promoted[0])) }
++                                          // + literal: Const { ty: &(i32, i32), val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) }
 +         _2 = &((*_4).1: i32);            // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17
 -         StorageDead(_3);                 // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18
diff --git a/src/test/mir-opt/const_prop/slice_len/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/slice_len/32bit/rustc.main.ConstProp.diff
index 70c41564882..6eb64f75ef1 100644
--- a/src/test/mir-opt/const_prop/slice_len/32bit/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/slice_len/32bit/rustc.main.ConstProp.diff
@@ -21,10 +21,10 @@
           _9 = const main::promoted[0];    // scope 0 at $DIR/slice_len.rs:5:6: 5:19
                                            // ty::Const
                                            // + ty: &[u32; 3]
-                                           // + val: Unevaluated(DefId(0:3 ~ slice_len[317d]::main[0]), [], Some(promoted[0]))
+                                           // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main[0]), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/slice_len.rs:5:6: 5:19
-                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(DefId(0:3 ~ slice_len[317d]::main[0]), [], Some(promoted[0])) }
+                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) }
           _4 = _9;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _3 = _4;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:5:6: 5:19
diff --git a/src/test/mir-opt/const_prop/slice_len/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/slice_len/64bit/rustc.main.ConstProp.diff
index 885f28124c4..2b641bef1d8 100644
--- a/src/test/mir-opt/const_prop/slice_len/64bit/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/slice_len/64bit/rustc.main.ConstProp.diff
@@ -21,10 +21,10 @@
           _9 = const main::promoted[0];    // scope 0 at $DIR/slice_len.rs:5:6: 5:19
                                            // ty::Const
                                            // + ty: &[u32; 3]
-                                           // + val: Unevaluated(DefId(0:3 ~ slice_len[317d]::main[0]), [], Some(promoted[0]))
+                                           // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main[0]), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/slice_len.rs:5:6: 5:19
-                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(DefId(0:3 ~ slice_len[317d]::main[0]), [], Some(promoted[0])) }
+                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) }
           _4 = _9;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _3 = _4;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:5:6: 5:19
diff --git a/src/test/mir-opt/inline/inline-retag/rustc.bar.Inline.after.mir b/src/test/mir-opt/inline/inline-retag/rustc.bar.Inline.after.mir
index e83cc92eb43..d6ac1c57a63 100644
--- a/src/test/mir-opt/inline/inline-retag/rustc.bar.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline-retag/rustc.bar.Inline.after.mir
@@ -38,10 +38,10 @@ fn bar() -> bool {
         _10 = const bar::promoted[1];    // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
                                          // ty::Const
                                          // + ty: &i32
-                                         // + val: Unevaluated(DefId(0:4 ~ inline_retag[317d]::bar[0]), [], Some(promoted[1]))
+                                         // + val: Unevaluated(WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar[0]), const_param_did: None }, [], Some(promoted[1]))
                                          // mir::Constant
                                          // + span: $DIR/inline-retag.rs:12:7: 12:9
-                                         // + literal: Const { ty: &i32, val: Unevaluated(DefId(0:4 ~ inline_retag[317d]::bar[0]), [], Some(promoted[1])) }
+                                         // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar[0]), const_param_did: None }, [], Some(promoted[1])) }
         Retag(_10);                      // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
         _4 = &(*_10);                    // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
         Retag(_4);                       // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
@@ -52,10 +52,10 @@ fn bar() -> bool {
         _9 = const bar::promoted[0];     // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
                                          // ty::Const
                                          // + ty: &i32
-                                         // + val: Unevaluated(DefId(0:4 ~ inline_retag[317d]::bar[0]), [], Some(promoted[0]))
+                                         // + val: Unevaluated(WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar[0]), const_param_did: None }, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $DIR/inline-retag.rs:12:11: 12:14
-                                         // + literal: Const { ty: &i32, val: Unevaluated(DefId(0:4 ~ inline_retag[317d]::bar[0]), [], Some(promoted[0])) }
+                                         // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar[0]), const_param_did: None }, [], Some(promoted[0])) }
         Retag(_9);                       // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
         _7 = &(*_9);                     // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
         Retag(_7);                       // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
diff --git a/src/test/mir-opt/issue-73223/32bit/rustc.main.PreCodegen.diff b/src/test/mir-opt/issue-73223/32bit/rustc.main.PreCodegen.diff
index 59c00e1b96f..cf5d1f3f6c6 100644
--- a/src/test/mir-opt/issue-73223/32bit/rustc.main.PreCodegen.diff
+++ b/src/test/mir-opt/issue-73223/32bit/rustc.main.PreCodegen.diff
@@ -96,10 +96,10 @@
           (_5.1: &i32) = const main::promoted[1]; // scope 3 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &i32
-                                           // + val: Unevaluated(DefId(0:3 ~ issue_73223[317d]::main[0]), [], Some(promoted[1]))
+                                           // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[1]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/libcore/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(DefId(0:3 ~ issue_73223[317d]::main[0]), [], Some(promoted[1])) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[1])) }
           StorageDead(_6);                 // scope 3 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
           StorageLive(_7);                 // scope 3 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
           _7 = (_5.0: &i32);               // scope 3 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
@@ -140,10 +140,10 @@
           _15 = const main::promoted[0] as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &[&str; 3]
-                                           // + val: Unevaluated(DefId(0:3 ~ issue_73223[317d]::main[0]), [], Some(promoted[0]))
+                                           // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/libcore/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &[&str; 3], val: Unevaluated(DefId(0:3 ~ issue_73223[317d]::main[0]), [], Some(promoted[0])) }
+                                           // + literal: Const { ty: &[&str; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) }
           StorageLive(_18);                // scope 4 at $SRC_DIR/libstd/macros.rs:LL:COL
           StorageLive(_19);                // scope 4 at $SRC_DIR/libstd/macros.rs:LL:COL
           StorageLive(_20);                // scope 4 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
diff --git a/src/test/mir-opt/issue-73223/32bit/rustc.main.SimplifyArmIdentity.diff b/src/test/mir-opt/issue-73223/32bit/rustc.main.SimplifyArmIdentity.diff
index 1020fc965fe..91baac86112 100644
--- a/src/test/mir-opt/issue-73223/32bit/rustc.main.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/issue-73223/32bit/rustc.main.SimplifyArmIdentity.diff
@@ -153,10 +153,10 @@
           _51 = const main::promoted[1];   // scope 3 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &i32
-                                           // + val: Unevaluated(DefId(0:3 ~ issue_73223[317d]::main[0]), [], Some(promoted[1]))
+                                           // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[1]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/libcore/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(DefId(0:3 ~ issue_73223[317d]::main[0]), [], Some(promoted[1])) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[1])) }
           _11 = _51;                       // scope 3 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
           (_9.0: &i32) = move _10;         // scope 3 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
           (_9.1: &i32) = move _11;         // scope 3 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
@@ -220,10 +220,10 @@
           _50 = const main::promoted[0];   // scope 4 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &[&str; 3]
-                                           // + val: Unevaluated(DefId(0:3 ~ issue_73223[317d]::main[0]), [], Some(promoted[0]))
+                                           // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/libcore/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &[&str; 3], val: Unevaluated(DefId(0:3 ~ issue_73223[317d]::main[0]), [], Some(promoted[0])) }
+                                           // + literal: Const { ty: &[&str; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) }
           _25 = _50;                       // scope 4 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
           _24 = _25;                       // scope 4 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
           _23 = move _24 as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
diff --git a/src/test/mir-opt/issue-73223/64bit/rustc.main.PreCodegen.diff b/src/test/mir-opt/issue-73223/64bit/rustc.main.PreCodegen.diff
index 59c00e1b96f..cf5d1f3f6c6 100644
--- a/src/test/mir-opt/issue-73223/64bit/rustc.main.PreCodegen.diff
+++ b/src/test/mir-opt/issue-73223/64bit/rustc.main.PreCodegen.diff
@@ -96,10 +96,10 @@
           (_5.1: &i32) = const main::promoted[1]; // scope 3 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &i32
-                                           // + val: Unevaluated(DefId(0:3 ~ issue_73223[317d]::main[0]), [], Some(promoted[1]))
+                                           // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[1]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/libcore/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(DefId(0:3 ~ issue_73223[317d]::main[0]), [], Some(promoted[1])) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[1])) }
           StorageDead(_6);                 // scope 3 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
           StorageLive(_7);                 // scope 3 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
           _7 = (_5.0: &i32);               // scope 3 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
@@ -140,10 +140,10 @@
           _15 = const main::promoted[0] as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &[&str; 3]
-                                           // + val: Unevaluated(DefId(0:3 ~ issue_73223[317d]::main[0]), [], Some(promoted[0]))
+                                           // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/libcore/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &[&str; 3], val: Unevaluated(DefId(0:3 ~ issue_73223[317d]::main[0]), [], Some(promoted[0])) }
+                                           // + literal: Const { ty: &[&str; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) }
           StorageLive(_18);                // scope 4 at $SRC_DIR/libstd/macros.rs:LL:COL
           StorageLive(_19);                // scope 4 at $SRC_DIR/libstd/macros.rs:LL:COL
           StorageLive(_20);                // scope 4 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
diff --git a/src/test/mir-opt/issue-73223/64bit/rustc.main.SimplifyArmIdentity.diff b/src/test/mir-opt/issue-73223/64bit/rustc.main.SimplifyArmIdentity.diff
index aa606ed22b6..0da748d79eb 100644
--- a/src/test/mir-opt/issue-73223/64bit/rustc.main.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/issue-73223/64bit/rustc.main.SimplifyArmIdentity.diff
@@ -153,10 +153,10 @@
           _51 = const main::promoted[1];   // scope 3 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &i32
-                                           // + val: Unevaluated(DefId(0:3 ~ issue_73223[317d]::main[0]), [], Some(promoted[1]))
+                                           // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[1]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/libcore/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(DefId(0:3 ~ issue_73223[317d]::main[0]), [], Some(promoted[1])) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[1])) }
           _11 = _51;                       // scope 3 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
           (_9.0: &i32) = move _10;         // scope 3 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
           (_9.1: &i32) = move _11;         // scope 3 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
@@ -220,10 +220,10 @@
           _50 = const main::promoted[0];   // scope 4 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &[&str; 3]
-                                           // + val: Unevaluated(DefId(0:3 ~ issue_73223[317d]::main[0]), [], Some(promoted[0]))
+                                           // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/libcore/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &[&str; 3], val: Unevaluated(DefId(0:3 ~ issue_73223[317d]::main[0]), [], Some(promoted[0])) }
+                                           // + literal: Const { ty: &[&str; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) }
           _25 = _50;                       // scope 4 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
           _24 = _25;                       // scope 4 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
           _23 = move _24 as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/libcore/macros/mod.rs:LL:COL
diff --git a/src/test/mir-opt/match_false_edges/rustc.full_tested_match.PromoteTemps.after.mir b/src/test/mir-opt/match_false_edges/rustc.full_tested_match.PromoteTemps.after.mir
index 5ff4150d2ac..c53c9cf1db7 100644
--- a/src/test/mir-opt/match_false_edges/rustc.full_tested_match.PromoteTemps.after.mir
+++ b/src/test/mir-opt/match_false_edges/rustc.full_tested_match.PromoteTemps.after.mir
@@ -76,10 +76,10 @@ fn full_tested_match() -> () {
         _11 = const full_tested_match::promoted[0]; // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15
                                          // ty::Const
                                          // + ty: &std::option::Option<i32>
-                                         // + val: Unevaluated(DefId(0:5 ~ match_false_edges[317d]::full_tested_match[0]), [], Some(promoted[0]))
+                                         // + val: Unevaluated(WithOptConstParam { did: DefId(0:5 ~ match_false_edges[317d]::full_tested_match[0]), const_param_did: None }, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $DIR/match_false_edges.rs:16:14: 16:15
-                                         // + literal: Const { ty: &std::option::Option<i32>, val: Unevaluated(DefId(0:5 ~ match_false_edges[317d]::full_tested_match[0]), [], Some(promoted[0])) }
+                                         // + literal: Const { ty: &std::option::Option<i32>, val: Unevaluated(WithOptConstParam { did: DefId(0:5 ~ match_false_edges[317d]::full_tested_match[0]), const_param_did: None }, [], Some(promoted[0])) }
         _6 = &(((*_11) as Some).0: i32); // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15
         _4 = &shallow _2;                // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27
         StorageLive(_7);                 // scope 0 at $DIR/match_false_edges.rs:16:20: 16:27
diff --git a/src/test/mir-opt/retag/rustc.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag/rustc.main.SimplifyCfg-elaborate-drops.after.mir
index 14a7f2d5005..b61d9368375 100644
--- a/src/test/mir-opt/retag/rustc.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag/rustc.main.SimplifyCfg-elaborate-drops.after.mir
@@ -184,10 +184,10 @@ fn main() -> () {
         _27 = const main::promoted[0];   // scope 7 at $DIR/retag.rs:47:21: 47:23
                                          // ty::Const
                                          // + ty: &i32
-                                         // + val: Unevaluated(DefId(0:13 ~ retag[317d]::main[0]), [], Some(promoted[0]))
+                                         // + val: Unevaluated(WithOptConstParam { did: DefId(0:13 ~ retag[317d]::main[0]), const_param_did: None }, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $DIR/retag.rs:47:21: 47:23
-                                         // + literal: Const { ty: &i32, val: Unevaluated(DefId(0:13 ~ retag[317d]::main[0]), [], Some(promoted[0])) }
+                                         // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:13 ~ retag[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) }
         Retag(_27);                      // scope 7 at $DIR/retag.rs:47:21: 47:23
         _23 = &(*_27);                   // scope 7 at $DIR/retag.rs:47:21: 47:23
         Retag(_23);                      // scope 7 at $DIR/retag.rs:47:21: 47:23
diff --git a/src/test/ui/const-generics/type-dependent/auxiliary/type_dependent_lib.rs b/src/test/ui/const-generics/type-dependent/auxiliary/type_dependent_lib.rs
new file mode 100644
index 00000000000..c8db91b62b5
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/auxiliary/type_dependent_lib.rs
@@ -0,0 +1,36 @@
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+pub struct Struct<const N: usize>(());
+
+impl<const N: usize> Struct<N> {
+    pub fn new() -> Self {
+        Struct(())
+    }
+
+    pub fn same_ty<const M: usize>(&self) -> (usize, usize) {
+        (N, M)
+    }
+
+    pub fn different_ty<const M: u8>(&self) -> (usize, u8) {
+        (N, M)
+    }
+
+    pub fn containing_ty<T, const M: u8>(&self) -> (usize, u8) {
+        (std::mem::size_of::<T>() +  N, M)
+    }
+
+    pub fn we_have_to_go_deeper<const M: usize>(&self) -> Struct<M> {
+        Struct(())
+    }
+}
+
+pub trait Foo {
+    fn foo<const M: usize>(&self) -> usize;
+}
+
+impl Foo for Struct<7> {
+    fn foo<const M: usize>(&self) -> usize {
+        M
+    }
+}
diff --git a/src/test/ui/const-generics/type-dependent/const-arg-in-const-arg.rs b/src/test/ui/const-generics/type-dependent/const-arg-in-const-arg.rs
new file mode 100644
index 00000000000..ae50252facd
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/const-arg-in-const-arg.rs
@@ -0,0 +1,26 @@
+// run-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+#![feature(const_fn)]
+
+struct Foo;
+
+impl Foo {
+    fn foo<const N: usize>(&self) -> usize {
+        let f = self;
+        f.bar::<{
+            let f = Foo;
+            f.bar::<7>()
+        }>() + N
+    }
+
+    const fn bar<const M: usize>(&self) -> usize {
+        M
+    }
+}
+
+fn main() {
+    let f = Foo;
+
+    assert_eq!(f.foo::<13>(), 20)
+}
diff --git a/src/test/ui/const-generics/type-dependent/issue-61936.rs b/src/test/ui/const-generics/type-dependent/issue-61936.rs
new file mode 100644
index 00000000000..a7a923c6a59
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/issue-61936.rs
@@ -0,0 +1,49 @@
+// run-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+trait SliceExt<T: Clone> {
+    fn array_windows<'a, const N: usize>(&'a self) -> ArrayWindows<'a, T, N>;
+}
+
+impl <T: Clone> SliceExt<T> for [T] {
+   fn array_windows<'a, const N: usize>(&'a self) -> ArrayWindows<'a, T, N> {
+       ArrayWindows{ idx: 0, slice: &self }
+   }
+}
+
+struct ArrayWindows<'a, T, const N: usize> {
+    slice: &'a [T],
+    idx: usize,
+}
+
+impl <'a, T: Clone, const N: usize> Iterator for ArrayWindows<'a, T, N> {
+    type Item = [T; N];
+    fn next(&mut self) -> Option<Self::Item> {
+        // Note: this is unsound for some `T` and not meant as an example
+        // on how to implement `ArrayWindows`.
+        let mut res = unsafe{ std::mem::zeroed() };
+        let mut ptr = &mut res as *mut [T; N] as *mut T;
+
+        for i in 0..N {
+            match self.slice[self.idx..].get(i) {
+                None => return None,
+                Some(elem) => unsafe { std::ptr::write_volatile(ptr, elem.clone())},
+            };
+            ptr = ptr.wrapping_add(1);
+            self.idx += 1;
+        }
+
+        Some(res)
+    }
+}
+
+const FOUR: usize = 4;
+
+fn main() {
+    let v: Vec<usize> = vec![0; 100];
+
+    for array in v.as_slice().array_windows::<FOUR>() {
+        assert_eq!(array, [0, 0, 0, 0])
+    }
+}
diff --git a/src/test/ui/const-generics/type-dependent/issue-63695.rs b/src/test/ui/const-generics/type-dependent/issue-63695.rs
new file mode 100644
index 00000000000..f3c2e177594
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/issue-63695.rs
@@ -0,0 +1,17 @@
+// run-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+trait T {
+    fn test<const A: i32>(&self) -> i32 { A }
+}
+
+struct S();
+
+impl T for S {}
+
+fn main() {
+    let foo = S();
+    assert_eq!(foo.test::<8i32>(), 8);
+    assert_eq!(foo.test::<16i32>(), 16);
+}
diff --git a/src/test/ui/const-generics/type-dependent/issue-69816.rs b/src/test/ui/const-generics/type-dependent/issue-69816.rs
new file mode 100644
index 00000000000..cbe86cef323
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/issue-69816.rs
@@ -0,0 +1,20 @@
+// run-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+trait IterExt: Sized + Iterator {
+    fn default_for_size<const N: usize>(self) -> [Self::Item; N]
+    where
+        [Self::Item; N]: Default,
+    {
+        Default::default()
+    }
+}
+
+impl<T: Iterator> IterExt for T {}
+
+fn main(){
+    const N: usize = 10;
+    let arr = (0u32..10).default_for_size::<N>();
+    assert_eq!(arr, [0; 10]);
+}
diff --git a/src/test/ui/const-generics/type-dependent/issue-70507.rs b/src/test/ui/const-generics/type-dependent/issue-70507.rs
new file mode 100644
index 00000000000..6fcf4116d43
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/issue-70507.rs
@@ -0,0 +1,47 @@
+// run-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+trait ConstChunksExactTrait<T> {
+    fn const_chunks_exact<const N: usize>(&self) -> ConstChunksExact<'_, T, {N}>;
+}
+
+impl <T> ConstChunksExactTrait<T> for [T] {
+    fn const_chunks_exact<const N: usize>(&self) -> ConstChunksExact<'_, T, {N}> {
+        assert!(N != 0);
+        let rem = self.len() % N;
+        let len = self.len() - rem;
+        let (fst, _) = self.split_at(len);
+        ConstChunksExact { v: fst, }
+    }
+}
+
+struct ConstChunksExact<'a, T: 'a, const N: usize> {
+    v: &'a [T],
+}
+
+impl <'a, T: std::fmt::Debug, const N: usize> Iterator for ConstChunksExact<'a, T, {N}> {
+    type Item = &'a [T; N];
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.v.len() < N {
+            None
+        } else {
+            let (fst, snd) = self.v.split_at(N);
+
+            self.v = snd;
+            let ptr = fst.as_ptr() as *const _;
+            Some(unsafe { &*ptr})
+        }
+    }
+}
+
+fn main() {
+    let slice = &[1i32, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+
+    let mut iter = [[1, 2, 3], [4, 5, 6], [7, 8, 9]].iter();
+
+    for a in slice.const_chunks_exact::<3>() {
+        assert_eq!(a, iter.next().unwrap());
+    }
+}
diff --git a/src/test/ui/const-generics/type-dependent/issue-71382.rs b/src/test/ui/const-generics/type-dependent/issue-71382.rs
new file mode 100644
index 00000000000..05abd488816
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/issue-71382.rs
@@ -0,0 +1,24 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete
+
+struct Test;
+
+fn pass() -> u8 {
+    42
+}
+
+impl Test {
+    pub fn call_me(&self) -> u8 {
+        self.test::<pass>()
+    }
+
+    fn test<const FN: fn() -> u8>(&self) -> u8 {
+        //~^ ERROR using function pointers as const generic parameters is forbidden
+        FN()
+    }
+}
+
+fn main() {
+    let x = Test;
+    assert_eq!(x.call_me(), 42);
+}
diff --git a/src/test/ui/const-generics/type-dependent/issue-71382.stderr b/src/test/ui/const-generics/type-dependent/issue-71382.stderr
new file mode 100644
index 00000000000..f441b71031e
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/issue-71382.stderr
@@ -0,0 +1,17 @@
+warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-71382.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
+
+error: using function pointers as const generic parameters is forbidden
+  --> $DIR/issue-71382.rs:15:23
+   |
+LL |     fn test<const FN: fn() -> u8>(&self) -> u8 {
+   |                       ^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/src/test/ui/const-generics/type-dependent/non-local.rs b/src/test/ui/const-generics/type-dependent/non-local.rs
new file mode 100644
index 00000000000..e6f3eb075f1
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/non-local.rs
@@ -0,0 +1,24 @@
+// aux-build:type_dependent_lib.rs
+// run-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+extern crate type_dependent_lib;
+
+use type_dependent_lib::*;
+
+fn main() {
+    let s = Struct::<42>::new();
+    assert_eq!(s.same_ty::<7>(), (42, 7));
+    assert_eq!(s.different_ty::<19>(), (42, 19));
+    assert_eq!(Struct::<1337>::new().different_ty::<96>(), (1337, 96));
+    assert_eq!(
+        Struct::<18>::new()
+            .we_have_to_go_deeper::<19>()
+            .containing_ty::<Option<u32>, 3>(),
+        (27, 3),
+    );
+
+    let s = Struct::<7>::new();
+    assert_eq!(s.foo::<18>(), 18);
+}
diff --git a/src/test/ui/const-generics/type-dependent/qpath.rs b/src/test/ui/const-generics/type-dependent/qpath.rs
new file mode 100644
index 00000000000..f3f98e5faf5
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/qpath.rs
@@ -0,0 +1,12 @@
+// run-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+struct A;
+impl A {
+    fn foo<const N: usize>() -> usize { N + 1 }
+}
+
+fn main() {
+    assert_eq!(A::foo::<7>(), 8);
+}
diff --git a/src/test/ui/const-generics/type-dependent/simple.rs b/src/test/ui/const-generics/type-dependent/simple.rs
new file mode 100644
index 00000000000..cc7c50d8fd8
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/simple.rs
@@ -0,0 +1,12 @@
+// run-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+struct R;
+
+impl R {
+    fn method<const N: u8>(&self) -> u8 { N }
+}
+fn main() {
+    assert_eq!(R.method::<1u8>(), 1);
+}
diff --git a/src/test/ui/const-generics/type-dependent/type-mismatch.rs b/src/test/ui/const-generics/type-dependent/type-mismatch.rs
new file mode 100644
index 00000000000..0c71f338bd2
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/type-mismatch.rs
@@ -0,0 +1,12 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete
+
+struct R;
+
+impl R {
+    fn method<const N: u8>(&self) -> u8 { N }
+}
+fn main() {
+    assert_eq!(R.method::<1u16>(), 1);
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/const-generics/type-dependent/type-mismatch.stderr b/src/test/ui/const-generics/type-dependent/type-mismatch.stderr
new file mode 100644
index 00000000000..5bb7c5b0ea9
--- /dev/null
+++ b/src/test/ui/const-generics/type-dependent/type-mismatch.stderr
@@ -0,0 +1,23 @@
+warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/type-mismatch.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
+
+error[E0308]: mismatched types
+  --> $DIR/type-mismatch.rs:10:27
+   |
+LL |     assert_eq!(R.method::<1u16>(), 1);
+   |                           ^^^^ expected `u8`, found `u16`
+   |
+help: change the type of the numeric literal from `u16` to `u8`
+   |
+LL |     assert_eq!(R.method::<1u8>(), 1);
+   |                           ^^^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/unknown_adt.rs b/src/test/ui/const-generics/unknown_adt.rs
new file mode 100644
index 00000000000..0ba9945b399
--- /dev/null
+++ b/src/test/ui/const-generics/unknown_adt.rs
@@ -0,0 +1,7 @@
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+fn main() {
+    let _: UnknownStruct<7>;
+    //~^ ERROR cannot find type `UnknownStruct`
+}
diff --git a/src/test/ui/const-generics/unknown_adt.stderr b/src/test/ui/const-generics/unknown_adt.stderr
new file mode 100644
index 00000000000..b2e287b762c
--- /dev/null
+++ b/src/test/ui/const-generics/unknown_adt.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `UnknownStruct` in this scope
+  --> $DIR/unknown_adt.rs:5:12
+   |
+LL |     let _: UnknownStruct<7>;
+   |            ^^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/tools/clippy/clippy_lints/src/consts.rs b/src/tools/clippy/clippy_lints/src/consts.rs
index 2f963dfcf8b..e6ef54f528f 100644
--- a/src/tools/clippy/clippy_lints/src/consts.rs
+++ b/src/tools/clippy/clippy_lints/src/consts.rs
@@ -332,7 +332,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
                 let result = self
                     .lcx
                     .tcx
-                    .const_eval_resolve(self.param_env, def_id, substs, None, None)
+                    .const_eval_resolve(self.param_env, ty::WithOptConstParam::unknown(def_id), substs, None, None)
                     .ok()
                     .map(|val| rustc_middle::ty::Const::from_value(self.lcx.tcx, val, ty))?;
                 let result = miri_to_const(&result);