diff --git a/compiler/rustc_codegen_cranelift/example/alloc_example.rs b/compiler/rustc_codegen_cranelift/example/alloc_example.rs
index d0d492e96742d..bc1594d82ecf9 100644
--- a/compiler/rustc_codegen_cranelift/example/alloc_example.rs
+++ b/compiler/rustc_codegen_cranelift/example/alloc_example.rs
@@ -1,10 +1,10 @@
-#![feature(start, core_intrinsics, alloc_prelude, alloc_error_handler, box_syntax)]
+#![feature(start, core_intrinsics, alloc_error_handler, box_syntax)]
 #![no_std]
 
 extern crate alloc;
 extern crate alloc_system;
 
-use alloc::prelude::v1::*;
+use alloc::boxed::Box;
 
 use alloc_system::System;
 
diff --git a/compiler/rustc_codegen_gcc/example/alloc_example.rs b/compiler/rustc_codegen_gcc/example/alloc_example.rs
index bc6dd007ba010..74ea7ec4ede69 100644
--- a/compiler/rustc_codegen_gcc/example/alloc_example.rs
+++ b/compiler/rustc_codegen_gcc/example/alloc_example.rs
@@ -1,10 +1,10 @@
-#![feature(start, box_syntax, core_intrinsics, alloc_prelude, alloc_error_handler)]
+#![feature(start, box_syntax, core_intrinsics, alloc_error_handler)]
 #![no_std]
 
 extern crate alloc;
 extern crate alloc_system;
 
-use alloc::prelude::v1::*;
+use alloc::boxed::Box;
 
 use alloc_system::System;
 
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 60a48b5a2d9c1..9b2094adb150c 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -341,7 +341,7 @@ impl CodeSuggestion {
                     });
                     buf.push_str(&part.snippet);
                     let cur_hi = sm.lookup_char_pos(part.span.hi());
-                    if prev_hi.line == cur_lo.line {
+                    if prev_hi.line == cur_lo.line && cur_hi.line == cur_lo.line {
                         // Account for the difference between the width of the current code and the
                         // snippet being suggested, so that the *later* suggestions are correctly
                         // aligned on the screen.
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
index 0efe5a56436b5..ea9d0eae17e2c 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
@@ -46,7 +46,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 }
             }
         }
-        if let RegionResolutionError::ConcreteFailure(origin, _, _) = error.clone() {
+        if let RegionResolutionError::ConcreteFailure(origin, _, _)
+        | RegionResolutionError::GenericBoundFailure(origin, _, _) = error.clone()
+        {
             if let SubregionOrigin::CompareImplTypeObligation {
                 span,
                 item_name,
diff --git a/compiler/rustc_middle/src/ty/outlives.rs b/compiler/rustc_infer/src/infer/outlives/components.rs
similarity index 94%
rename from compiler/rustc_middle/src/ty/outlives.rs
rename to compiler/rustc_infer/src/infer/outlives/components.rs
index ef4ad998f10c8..98f926e9d76d5 100644
--- a/compiler/rustc_middle/src/ty/outlives.rs
+++ b/compiler/rustc_infer/src/infer/outlives/components.rs
@@ -2,10 +2,10 @@
 // refers to rules defined in RFC 1214 (`OutlivesFooBar`), so see that
 // RFC for reference.
 
-use crate::ty::subst::{GenericArg, GenericArgKind};
-use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc_data_structures::sso::SsoHashSet;
-use smallvec::SmallVec;
+use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
+use smallvec::{smallvec, SmallVec};
 
 #[derive(Debug)]
 pub enum Component<'tcx> {
@@ -47,14 +47,16 @@ pub enum Component<'tcx> {
     EscapingProjection(Vec<Component<'tcx>>),
 }
 
-impl<'tcx> TyCtxt<'tcx> {
-    /// Push onto `out` all the things that must outlive `'a` for the condition
-    /// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**.
-    pub fn push_outlives_components(self, ty0: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) {
-        let mut visited = SsoHashSet::new();
-        compute_components(self, ty0, out, &mut visited);
-        debug!("components({:?}) = {:?}", ty0, out);
-    }
+/// Push onto `out` all the things that must outlive `'a` for the condition
+/// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**.
+pub fn push_outlives_components(
+    tcx: TyCtxt<'tcx>,
+    ty0: Ty<'tcx>,
+    out: &mut SmallVec<[Component<'tcx>; 4]>,
+) {
+    let mut visited = SsoHashSet::new();
+    compute_components(tcx, ty0, out, &mut visited);
+    debug!("components({:?}) = {:?}", ty0, out);
 }
 
 fn compute_components(
diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs
index 4dd5e8ba54500..03d6c45a65345 100644
--- a/compiler/rustc_infer/src/infer/outlives/mod.rs
+++ b/compiler/rustc_infer/src/infer/outlives/mod.rs
@@ -1,5 +1,6 @@
 //! Various code related to computing outlives relations.
 
+pub mod components;
 pub mod env;
 pub mod obligations;
 pub mod verify;
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index 437083c68dcec..91a22ecc5a994 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -1,5 +1,5 @@
 //! Code that handles "type-outlives" constraints like `T: 'a`. This
-//! is based on the `push_outlives_components` function defined on the tcx,
+//! is based on the `push_outlives_components` function defined in rustc_infer,
 //! but it adds a bit of heuristics on top, in particular to deal with
 //! associated types and projections.
 //!
@@ -59,13 +59,13 @@
 //! might later infer `?U` to something like `&'b u32`, which would
 //! imply that `'b: 'a`.
 
+use crate::infer::outlives::components::{push_outlives_components, Component};
 use crate::infer::outlives::env::RegionBoundPairs;
 use crate::infer::outlives::verify::VerifyBoundCx;
 use crate::infer::{
     self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, UndoLog, VerifyBound,
 };
 use crate::traits::{ObligationCause, ObligationCauseCode};
-use rustc_middle::ty::outlives::Component;
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeFoldable};
 
@@ -271,7 +271,7 @@ where
         assert!(!ty.has_escaping_bound_vars());
 
         let mut components = smallvec![];
-        self.tcx.push_outlives_components(ty, &mut components);
+        push_outlives_components(self.tcx, ty, &mut components);
         self.components_must_outlive(origin, &components, region);
     }
 
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 30d5613d5820d..c839f824d1c9c 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -1,8 +1,8 @@
 use smallvec::smallvec;
 
+use crate::infer::outlives::components::{push_outlives_components, Component};
 use crate::traits::{Obligation, ObligationCause, PredicateObligation};
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
-use rustc_middle::ty::outlives::Component;
 use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness};
 use rustc_span::symbol::Ident;
 
@@ -200,7 +200,7 @@ impl Elaborator<'tcx> {
 
                 let visited = &mut self.visited;
                 let mut components = smallvec![];
-                tcx.push_outlives_components(ty_max, &mut components);
+                push_outlives_components(tcx, ty_max, &mut components);
                 self.stack.extend(
                     components
                         .into_iter()
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 0eacedc09ee6d..20d07bdc48a62 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -92,7 +92,6 @@ pub mod fold;
 pub mod inhabitedness;
 pub mod layout;
 pub mod normalize_erasing_regions;
-pub mod outlives;
 pub mod print;
 pub mod query;
 pub mod relate;
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index 8fb4eb641c26a..70816b5722b2d 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -1,12 +1,8 @@
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
-use crate::traits::query::outlives_bounds::InferCtxtExt as _;
 use crate::traits::{self, TraitEngine, TraitEngineExt};
 
-use rustc_data_structures::stable_set::FxHashSet;
-use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
-use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::arena::ArenaAllocatable;
 use rustc_middle::infer::canonical::{Canonical, CanonicalizedQueryResponse, QueryResponse};
@@ -180,48 +176,3 @@ impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
         )
     }
 }
-
-pub trait OutlivesEnvironmentExt<'tcx> {
-    fn add_implied_bounds(
-        &mut self,
-        infcx: &InferCtxt<'a, 'tcx>,
-        fn_sig_tys: FxHashSet<Ty<'tcx>>,
-        body_id: hir::HirId,
-        span: Span,
-    );
-}
-
-impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> {
-    /// This method adds "implied bounds" into the outlives environment.
-    /// Implied bounds are outlives relationships that we can deduce
-    /// on the basis that certain types must be well-formed -- these are
-    /// either the types that appear in the function signature or else
-    /// the input types to an impl. For example, if you have a function
-    /// like
-    ///
-    /// ```
-    /// fn foo<'a, 'b, T>(x: &'a &'b [T]) { }
-    /// ```
-    ///
-    /// we can assume in the caller's body that `'b: 'a` and that `T:
-    /// 'b` (and hence, transitively, that `T: 'a`). This method would
-    /// add those assumptions into the outlives-environment.
-    ///
-    /// Tests: `src/test/ui/regions/regions-free-region-ordering-*.rs`
-    fn add_implied_bounds(
-        &mut self,
-        infcx: &InferCtxt<'a, 'tcx>,
-        fn_sig_tys: FxHashSet<Ty<'tcx>>,
-        body_id: hir::HirId,
-        span: Span,
-    ) {
-        debug!("add_implied_bounds()");
-
-        for ty in fn_sig_tys {
-            let ty = infcx.resolve_vars_if_possible(ty);
-            debug!("add_implied_bounds: ty = {}", ty);
-            let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span);
-            self.add_outlives_bounds(Some(infcx), implied_bounds)
-        }
-    }
-}
diff --git a/compiler/rustc_trait_selection/src/traits/query/mod.rs b/compiler/rustc_trait_selection/src/traits/query/mod.rs
index f6f42814d3f07..ef3493678131f 100644
--- a/compiler/rustc_trait_selection/src/traits/query/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/mod.rs
@@ -9,7 +9,6 @@ pub mod dropck_outlives;
 pub mod evaluate_obligation;
 pub mod method_autoderef;
 pub mod normalize;
-pub mod outlives_bounds;
 pub mod type_op;
 
 pub use rustc_middle::traits::query::*;
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index 03087e3353a6e..04c382d439d4c 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -1,6 +1,6 @@
 use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
-use crate::traits::query::outlives_bounds::OutlivesBound;
 use crate::traits::query::Fallible;
+use rustc_infer::traits::query::OutlivesBound;
 use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt};
 
 #[derive(Copy, Clone, Debug, HashStable, TypeFoldable, Lift)]
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index 1d10d06849062..37e007337374f 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -4,14 +4,14 @@
 
 use rustc_hir as hir;
 use rustc_infer::infer::canonical::{self, Canonical};
+use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
+use rustc_infer::traits::query::OutlivesBound;
 use rustc_infer::traits::TraitEngineExt as _;
-use rustc_middle::ty::outlives::Component;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc_span::source_map::DUMMY_SP;
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
-use rustc_trait_selection::traits::query::outlives_bounds::OutlivesBound;
 use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution};
 use rustc_trait_selection::traits::wf;
 use rustc_trait_selection::traits::FulfillmentContext;
@@ -118,7 +118,7 @@ fn compute_implied_outlives_bounds<'tcx>(
                     ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, r_b)) => {
                         let ty_a = infcx.resolve_vars_if_possible(ty_a);
                         let mut components = smallvec![];
-                        tcx.push_outlives_components(ty_a, &mut components);
+                        push_outlives_components(tcx, ty_a, &mut components);
                         implied_bounds_from_components(r_b, components)
                     }
                 },
diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs
index 79443010fbb3d..7c8b75271871a 100644
--- a/compiler/rustc_typeck/src/check/regionck.rs
+++ b/compiler/rustc_typeck/src/check/regionck.rs
@@ -76,19 +76,19 @@ use crate::check::dropck;
 use crate::check::FnCtxt;
 use crate::mem_categorization as mc;
 use crate::middle::region;
+use crate::outlives::outlives_bounds::InferCtxtExt as _;
 use rustc_data_structures::stable_set::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::PatKind;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{self, RegionObligation, RegionckMode};
+use rustc_infer::infer::{self, InferCtxt, RegionObligation, RegionckMode};
 use rustc_middle::hir::place::{PlaceBase, PlaceWithHirId};
 use rustc_middle::ty::adjustment;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::Span;
-use rustc_trait_selection::infer::OutlivesEnvironmentExt;
-use rustc_trait_selection::opaque_types::InferCtxtExt;
+use rustc_trait_selection::opaque_types::InferCtxtExt as _;
 use std::ops::Deref;
 
 // a variation on try that just returns unit
@@ -104,6 +104,51 @@ macro_rules! ignore_err {
     };
 }
 
+trait OutlivesEnvironmentExt<'tcx> {
+    fn add_implied_bounds(
+        &mut self,
+        infcx: &InferCtxt<'a, 'tcx>,
+        fn_sig_tys: FxHashSet<Ty<'tcx>>,
+        body_id: hir::HirId,
+        span: Span,
+    );
+}
+
+impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> {
+    /// This method adds "implied bounds" into the outlives environment.
+    /// Implied bounds are outlives relationships that we can deduce
+    /// on the basis that certain types must be well-formed -- these are
+    /// either the types that appear in the function signature or else
+    /// the input types to an impl. For example, if you have a function
+    /// like
+    ///
+    /// ```
+    /// fn foo<'a, 'b, T>(x: &'a &'b [T]) { }
+    /// ```
+    ///
+    /// we can assume in the caller's body that `'b: 'a` and that `T:
+    /// 'b` (and hence, transitively, that `T: 'a`). This method would
+    /// add those assumptions into the outlives-environment.
+    ///
+    /// Tests: `src/test/ui/regions/regions-free-region-ordering-*.rs`
+    fn add_implied_bounds(
+        &mut self,
+        infcx: &InferCtxt<'a, 'tcx>,
+        fn_sig_tys: FxHashSet<Ty<'tcx>>,
+        body_id: hir::HirId,
+        span: Span,
+    ) {
+        debug!("add_implied_bounds()");
+
+        for ty in fn_sig_tys {
+            let ty = infcx.resolve_vars_if_possible(ty);
+            debug!("add_implied_bounds: ty = {}", ty);
+            let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span);
+            self.add_outlives_bounds(Some(infcx), implied_bounds)
+        }
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // PUBLIC ENTRY POINTS
 
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 20cf9a75e1267..30aab38b1eb85 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -142,23 +142,23 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
             }
         }
         hir::ItemKind::Fn(ref sig, ..) => {
-            check_item_fn(tcx, item.hir_id(), item.ident, item.span, sig.decl);
+            check_item_fn(tcx, item.def_id, item.ident, item.span, sig.decl);
         }
         hir::ItemKind::Static(ty, ..) => {
-            check_item_type(tcx, item.hir_id(), ty.span, false);
+            check_item_type(tcx, item.def_id, ty.span, false);
         }
         hir::ItemKind::Const(ty, ..) => {
-            check_item_type(tcx, item.hir_id(), ty.span, false);
+            check_item_type(tcx, item.def_id, ty.span, false);
         }
         hir::ItemKind::ForeignMod { items, .. } => {
             for it in items.iter() {
                 let it = tcx.hir().foreign_item(it.id);
                 match it.kind {
                     hir::ForeignItemKind::Fn(decl, ..) => {
-                        check_item_fn(tcx, it.hir_id(), it.ident, it.span, decl)
+                        check_item_fn(tcx, it.def_id, it.ident, it.span, decl)
                     }
                     hir::ForeignItemKind::Static(ty, ..) => {
-                        check_item_type(tcx, it.hir_id(), ty.span, true)
+                        check_item_type(tcx, it.def_id, ty.span, true)
                     }
                     hir::ForeignItemKind::Type => (),
                 }
@@ -199,7 +199,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         _ => (None, trait_item.span),
     };
     check_object_unsafe_self_trait_by_name(tcx, trait_item);
-    check_associated_item(tcx, trait_item.hir_id(), span, method_sig);
+    check_associated_item(tcx, trait_item.def_id, span, method_sig);
 
     let encl_trait_hir_id = tcx.hir().get_parent_item(hir_id);
     let encl_trait = tcx.hir().expect_item(encl_trait_hir_id);
@@ -327,7 +327,7 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         _ => (None, impl_item.span),
     };
 
-    check_associated_item(tcx, impl_item.hir_id(), span, method_sig);
+    check_associated_item(tcx, impl_item.def_id, span, method_sig);
 }
 
 fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
@@ -437,13 +437,13 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
 #[tracing::instrument(level = "debug", skip(tcx, span, sig_if_method))]
 fn check_associated_item(
     tcx: TyCtxt<'_>,
-    item_id: hir::HirId,
+    item_id: LocalDefId,
     span: Span,
     sig_if_method: Option<&hir::FnSig<'_>>,
 ) {
-    let code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id.expect_owner())));
+    let code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id)));
     for_id(tcx, item_id, span).with_fcx(|fcx| {
-        let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id(item_id));
+        let item = fcx.tcx.associated_item(item_id);
 
         let (mut implied_bounds, self_ty) = match item.container {
             ty::TraitContainer(_) => (FxHashSet::default(), fcx.tcx.types.self_param),
@@ -455,11 +455,7 @@ fn check_associated_item(
         match item.kind {
             ty::AssocKind::Const => {
                 let ty = fcx.tcx.type_of(item.def_id);
-                let ty = fcx.normalize_associated_types_in_wf(
-                    span,
-                    ty,
-                    WellFormedLoc::Ty(item_id.expect_owner()),
-                );
+                let ty = fcx.normalize_associated_types_in_wf(span, ty, WellFormedLoc::Ty(item_id));
                 fcx.register_wf_obligation(ty.into(), span, code.clone());
             }
             ty::AssocKind::Fn => {
@@ -481,11 +477,8 @@ fn check_associated_item(
                 }
                 if item.defaultness.has_value() {
                     let ty = fcx.tcx.type_of(item.def_id);
-                    let ty = fcx.normalize_associated_types_in_wf(
-                        span,
-                        ty,
-                        WellFormedLoc::Ty(item_id.expect_owner()),
-                    );
+                    let ty =
+                        fcx.normalize_associated_types_in_wf(span, ty, WellFormedLoc::Ty(item_id));
                     fcx.register_wf_obligation(ty.into(), span, code.clone());
                 }
             }
@@ -496,14 +489,13 @@ fn check_associated_item(
 }
 
 fn for_item<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>) -> CheckWfFcxBuilder<'tcx> {
-    for_id(tcx, item.hir_id(), item.span)
+    for_id(tcx, item.def_id, item.span)
 }
 
-fn for_id(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) -> CheckWfFcxBuilder<'_> {
-    let def_id = tcx.hir().local_def_id(id);
+fn for_id(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> CheckWfFcxBuilder<'_> {
     CheckWfFcxBuilder {
         inherited: Inherited::build(tcx, def_id),
-        id,
+        id: hir::HirId::make_owner(def_id),
         span,
         param_env: tcx.param_env(def_id),
     }
@@ -665,13 +657,12 @@ fn check_associated_type_bounds(fcx: &FnCtxt<'_, '_>, item: &ty::AssocItem, span
 
 fn check_item_fn(
     tcx: TyCtxt<'_>,
-    item_id: hir::HirId,
+    def_id: LocalDefId,
     ident: Ident,
     span: Span,
     decl: &hir::FnDecl<'_>,
 ) {
-    for_id(tcx, item_id, span).with_fcx(|fcx| {
-        let def_id = tcx.hir().local_def_id(item_id);
+    for_id(tcx, def_id, span).with_fcx(|fcx| {
         let sig = tcx.fn_sig(def_id);
         let mut implied_bounds = FxHashSet::default();
         check_fn_or_method(fcx, ident.span, sig, decl, def_id.to_def_id(), &mut implied_bounds);
@@ -679,16 +670,12 @@ fn check_item_fn(
     })
 }
 
-fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_foreign_ty: bool) {
+fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_foreign_ty: bool) {
     debug!("check_item_type: {:?}", item_id);
 
     for_id(tcx, item_id, ty_span).with_fcx(|fcx| {
-        let ty = tcx.type_of(tcx.hir().local_def_id(item_id));
-        let item_ty = fcx.normalize_associated_types_in_wf(
-            ty_span,
-            ty,
-            WellFormedLoc::Ty(item_id.expect_owner()),
-        );
+        let ty = tcx.type_of(item_id);
+        let item_ty = fcx.normalize_associated_types_in_wf(ty_span, ty, WellFormedLoc::Ty(item_id));
 
         let mut forbid_unsized = true;
         if allow_foreign_ty {
@@ -701,7 +688,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo
         fcx.register_wf_obligation(
             item_ty.into(),
             ty_span,
-            ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id.expect_owner()))),
+            ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id))),
         );
         if forbid_unsized {
             fcx.register_bound(
diff --git a/compiler/rustc_typeck/src/outlives/mod.rs b/compiler/rustc_typeck/src/outlives/mod.rs
index 957ff2525190d..eb3853b6b3dee 100644
--- a/compiler/rustc_typeck/src/outlives/mod.rs
+++ b/compiler/rustc_typeck/src/outlives/mod.rs
@@ -9,6 +9,7 @@ use rustc_span::Span;
 
 mod explicit;
 mod implicit_infer;
+crate mod outlives_bounds;
 /// Code to write unit test for outlives.
 pub mod test;
 mod utils;
diff --git a/compiler/rustc_trait_selection/src/traits/query/outlives_bounds.rs b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs
similarity index 93%
rename from compiler/rustc_trait_selection/src/traits/query/outlives_bounds.rs
rename to compiler/rustc_typeck/src/outlives/outlives_bounds.rs
index f5fa52c915d90..4ab5fe26abe56 100644
--- a/compiler/rustc_trait_selection/src/traits/query/outlives_bounds.rs
+++ b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs
@@ -1,11 +1,11 @@
-use crate::infer::canonical::OriginalQueryValues;
-use crate::infer::InferCtxt;
-use crate::traits::query::NoSolution;
-use crate::traits::{FulfillmentContext, ObligationCause, TraitEngine};
 use rustc_hir as hir;
 use rustc_infer::traits::TraitEngineExt as _;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::source_map::Span;
+use rustc_trait_selection::infer::canonical::OriginalQueryValues;
+use rustc_trait_selection::infer::InferCtxt;
+use rustc_trait_selection::traits::query::NoSolution;
+use rustc_trait_selection::traits::{FulfillmentContext, ObligationCause, TraitEngine};
 
 pub use rustc_middle::traits::query::OutlivesBound;
 
diff --git a/compiler/rustc_typeck/src/outlives/utils.rs b/compiler/rustc_typeck/src/outlives/utils.rs
index 8b06967879638..76ae2ee43566e 100644
--- a/compiler/rustc_typeck/src/outlives/utils.rs
+++ b/compiler/rustc_typeck/src/outlives/utils.rs
@@ -1,4 +1,4 @@
-use rustc_middle::ty::outlives::Component;
+use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
 use rustc_middle::ty::{self, Region, RegionKind, Ty, TyCtxt};
 use rustc_span::Span;
@@ -35,7 +35,7 @@ pub fn insert_outlives_predicate<'tcx>(
             // Or if within `struct Foo<U>` you had `T = Vec<U>`, then
             // we would want to add `U: 'outlived_region`
             let mut components = smallvec![];
-            tcx.push_outlives_components(ty, &mut components);
+            push_outlives_components(tcx, ty, &mut components);
             for component in components {
                 match component {
                     Component::Region(r) => {
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index e86c41b1ff887..635708fd4cf6e 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -189,7 +189,6 @@ mod boxed {
 pub mod borrow;
 pub mod collections;
 pub mod fmt;
-pub mod prelude;
 pub mod raw_vec;
 pub mod rc;
 pub mod slice;
diff --git a/library/alloc/src/prelude/mod.rs b/library/alloc/src/prelude/mod.rs
deleted file mode 100644
index 0534ad3edc79d..0000000000000
--- a/library/alloc/src/prelude/mod.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-//! The alloc Prelude
-//!
-//! The purpose of this module is to alleviate imports of commonly-used
-//! items of the `alloc` crate by adding a glob import to the top of modules:
-//!
-//! ```
-//! # #![allow(unused_imports)]
-//! #![feature(alloc_prelude)]
-//! extern crate alloc;
-//! use alloc::prelude::v1::*;
-//! ```
-
-#![unstable(feature = "alloc_prelude", issue = "58935")]
-
-pub mod v1;
diff --git a/library/alloc/src/prelude/v1.rs b/library/alloc/src/prelude/v1.rs
deleted file mode 100644
index 6a53b4ca1f6ca..0000000000000
--- a/library/alloc/src/prelude/v1.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//! The first version of the prelude of `alloc` crate.
-//!
-//! See the [module-level documentation](../index.html) for more.
-
-#![unstable(feature = "alloc_prelude", issue = "58935")]
-
-#[unstable(feature = "alloc_prelude", issue = "58935")]
-pub use crate::borrow::ToOwned;
-#[unstable(feature = "alloc_prelude", issue = "58935")]
-pub use crate::boxed::Box;
-#[unstable(feature = "alloc_prelude", issue = "58935")]
-pub use crate::string::{String, ToString};
-#[unstable(feature = "alloc_prelude", issue = "58935")]
-pub use crate::vec::Vec;
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 1c3afcdaa69e9..95798879155c5 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -44,7 +44,7 @@ use crate::intrinsics;
 /// ```
 #[inline]
 #[stable(feature = "unreachable", since = "1.27.0")]
-#[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")]
+#[rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0")]
 pub const unsafe fn unreachable_unchecked() -> ! {
     // SAFETY: the safety contract for `intrinsics::unreachable` must
     // be upheld by the caller.
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 886ace193c428..1aeb83931e5aa 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -735,7 +735,7 @@ extern "rust-intrinsic" {
     /// reach code marked with this function.
     ///
     /// The stabilized version of this intrinsic is [`core::hint::unreachable_unchecked`].
-    #[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")]
+    #[rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0")]
     pub fn unreachable() -> !;
 
     /// Informs the optimizer that a condition is always true.
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 7bc641c52767d..13b80c05dbb30 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -130,7 +130,6 @@
 #![feature(const_trait_impl)]
 #![feature(const_type_id)]
 #![feature(const_type_name)]
-#![feature(const_unreachable_unchecked)]
 #![feature(const_default_impls)]
 #![feature(duration_consts_2)]
 #![feature(ptr_metadata)]
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index b07752116e514..1247f33087558 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -62,7 +62,7 @@
 //! some atomic operations. Maximally portable code will want to be careful
 //! about which atomic types are used. `AtomicUsize` and `AtomicIsize` are
 //! generally the most portable, but even then they're not available everywhere.
-//! For reference, the `std` library requires pointer-sized atomics, although
+//! For reference, the `std` library requires `AtomicBool`s and pointer-sized atomics, although
 //! `core` does not.
 //!
 //! Currently you'll need to use `#[cfg(target_arch)]` primarily to
diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs
index 6f4863057aba4..b99eb2e553f08 100644
--- a/library/std/src/sys/unix/thread.rs
+++ b/library/std/src/sys/unix/thread.rs
@@ -275,6 +275,14 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
             target_os = "solaris",
             target_os = "illumos",
         ))] {
+            #[cfg(any(target_os = "android", target_os = "linux"))]
+            {
+                let mut set: libc::cpu_set_t = unsafe { mem::zeroed() };
+                if unsafe { libc::sched_getaffinity(0, mem::size_of::<libc::cpu_set_t>(), &mut set) } == 0 {
+                    let count = unsafe { libc::CPU_COUNT(&set) };
+                    return Ok(unsafe { NonZeroUsize::new_unchecked(count as usize) });
+                }
+            }
             match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } {
                 -1 => Err(io::Error::last_os_error()),
                 0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")),
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index 637e5f2288d62..0031e3915fa40 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -255,7 +255,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
                     )
                 })
                 .collect(),
-            format_version: 9,
+            format_version: types::FORMAT_VERSION,
         };
         let mut p = self.out_path.clone();
         p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 7c418697c1c1c..9466f84ffcd59 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -510,5 +510,8 @@ pub struct Static {
     pub expr: String,
 }
 
+/// rustdoc format-version.
+pub const FORMAT_VERSION: u32 = 9;
+
 #[cfg(test)]
 mod tests;
diff --git a/src/test/ui/consts/const_unsafe_unreachable.rs b/src/test/ui/consts/const_unsafe_unreachable.rs
index 1fec491ca95b1..1c3baec5d8638 100644
--- a/src/test/ui/consts/const_unsafe_unreachable.rs
+++ b/src/test/ui/consts/const_unsafe_unreachable.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(const_unreachable_unchecked)]
-
 const unsafe fn foo(x: bool) -> bool {
     match x {
         true => true,
@@ -12,5 +10,5 @@ const unsafe fn foo(x: bool) -> bool {
 const BAR: bool = unsafe { foo(true) };
 
 fn main() {
-  assert_eq!(BAR, true);
+    assert_eq!(BAR, true);
 }
diff --git a/src/test/ui/consts/const_unsafe_unreachable_ub.rs b/src/test/ui/consts/const_unsafe_unreachable_ub.rs
index 8cee5b5065136..b418fea617cea 100644
--- a/src/test/ui/consts/const_unsafe_unreachable_ub.rs
+++ b/src/test/ui/consts/const_unsafe_unreachable_ub.rs
@@ -1,5 +1,4 @@
 // error-pattern: evaluation of constant value failed
-#![feature(const_unreachable_unchecked)]
 
 const unsafe fn foo(x: bool) -> bool {
     match x {
@@ -11,5 +10,5 @@ const unsafe fn foo(x: bool) -> bool {
 const BAR: bool = unsafe { foo(false) };
 
 fn main() {
-  assert_eq!(BAR, true);
+    assert_eq!(BAR, true);
 }
diff --git a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr
index 65cb3d74b233e..ec6ce1f5d7c08 100644
--- a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr
+++ b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr
@@ -7,13 +7,13 @@ LL |     unsafe { intrinsics::unreachable() }
    |              entering unreachable code
    |              inside `unreachable_unchecked` at $SRC_DIR/core/src/hint.rs:LL:COL
    |
-  ::: $DIR/const_unsafe_unreachable_ub.rs:7:18
+  ::: $DIR/const_unsafe_unreachable_ub.rs:6:18
    |
 LL |         false => std::hint::unreachable_unchecked(),
-   |                  ---------------------------------- inside `foo` at $DIR/const_unsafe_unreachable_ub.rs:7:18
+   |                  ---------------------------------- inside `foo` at $DIR/const_unsafe_unreachable_ub.rs:6:18
 ...
 LL | const BAR: bool = unsafe { foo(false) };
-   |                            ---------- inside `BAR` at $DIR/const_unsafe_unreachable_ub.rs:11:28
+   |                            ---------- inside `BAR` at $DIR/const_unsafe_unreachable_ub.rs:10:28
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/errors/issue-89280-emitter-overflow-splice-lines.rs b/src/test/ui/errors/issue-89280-emitter-overflow-splice-lines.rs
new file mode 100644
index 0000000000000..a1c7af128d2ee
--- /dev/null
+++ b/src/test/ui/errors/issue-89280-emitter-overflow-splice-lines.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+trait X {
+    fn test(x: u32, (
+//~^ WARN anonymous parameters are deprecated and will be removed in the next edition
+//~^^ WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+    )) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr b/src/test/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr
new file mode 100644
index 0000000000000..4ec78a298fe62
--- /dev/null
+++ b/src/test/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr
@@ -0,0 +1,23 @@
+warning: anonymous parameters are deprecated and will be removed in the next edition
+  --> $DIR/issue-89280-emitter-overflow-splice-lines.rs:4:21
+   |
+LL |       fn test(x: u32, (
+   |  _____________________^
+LL | |
+LL | |
+LL | |     )) {}
+   | |_____^
+   |
+   = note: `#[warn(anonymous_parameters)]` on by default
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+   = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
+help: try naming the parameter or explicitly ignoring it
+   |
+LL ~     fn test(x: u32, _: (
+LL +
+LL +
+LL ~     )) {}
+   |
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/generic-associated-types/impl_bounds.rs b/src/test/ui/generic-associated-types/impl_bounds.rs
index 27c135cb7cf82..ff2ffec22c456 100644
--- a/src/test/ui/generic-associated-types/impl_bounds.rs
+++ b/src/test/ui/generic-associated-types/impl_bounds.rs
@@ -13,7 +13,7 @@ struct Fooy<T>(T);
 
 impl<T> Foo for Fooy<T> {
     type A<'a> where Self: 'static = (&'a ());
-    //~^ ERROR the parameter type `T` may not live long enough
+    //~^ ERROR `impl` associated type
     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
     //~^ ERROR `impl` associated type
     //~| ERROR lifetime bound not satisfied
diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr
index 649eadec515d0..f47b5f81e25b2 100644
--- a/src/test/ui/generic-associated-types/impl_bounds.stderr
+++ b/src/test/ui/generic-associated-types/impl_bounds.stderr
@@ -1,11 +1,11 @@
-error[E0310]: the parameter type `T` may not live long enough
+error: `impl` associated type signature for `A` doesn't match `trait` associated type signature
   --> $DIR/impl_bounds.rs:15:5
    |
+LL |     type A<'a> where Self: 'a;
+   |     -------------------------- expected
+...
 LL |     type A<'a> where Self: 'static = (&'a ());
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
-   = note: ...so that the definition in impl matches the definition from the trait
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found
 
 error: `impl` associated type signature for `B` doesn't match `trait` associated type signature
   --> $DIR/impl_bounds.rs:17:5
@@ -85,5 +85,5 @@ LL | impl<T: std::marker::Copy> Foo for Fooy<T> {
 
 error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0277, E0310, E0478.
+Some errors have detailed explanations: E0277, E0478.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/generic-associated-types/issue-86787.rs b/src/test/ui/generic-associated-types/issue-86787.rs
index 57d478a9ef1e3..f1f05ea6627e8 100644
--- a/src/test/ui/generic-associated-types/issue-86787.rs
+++ b/src/test/ui/generic-associated-types/issue-86787.rs
@@ -21,8 +21,8 @@ where
 {
     type T = Either<Left::T, Right::T>;
     type TRef<'a>
-    //~^ the associated type
-    //~^^ the associated type
+    //~^ `impl` associated type signature
+    //~^^ `impl` associated type signature
     where
     <Left as HasChildrenOf>::T: 'a,
     <Right as HasChildrenOf>::T: 'a
diff --git a/src/test/ui/generic-associated-types/issue-86787.stderr b/src/test/ui/generic-associated-types/issue-86787.stderr
index e1ff772921104..648eff77d73bb 100644
--- a/src/test/ui/generic-associated-types/issue-86787.stderr
+++ b/src/test/ui/generic-associated-types/issue-86787.stderr
@@ -1,29 +1,32 @@
-error[E0309]: the associated type `<Left as HasChildrenOf>::T` may not live long enough
+error: `impl` associated type signature for `TRef` doesn't match `trait` associated type signature
   --> $DIR/issue-86787.rs:23:5
    |
+LL |       type TRef<'a>;
+   |       -------------- expected
+...
 LL | /     type TRef<'a>
 LL | |
 LL | |
 LL | |     where
 LL | |     <Left as HasChildrenOf>::T: 'a,
 LL | |     <Right as HasChildrenOf>::T: 'a
-   | |                                    - help: consider adding a where clause: `, <Left as HasChildrenOf>::T: 'a`
 LL | |     = Either<&'a Left::T, &'a Right::T>;
-   | |________________________________________^ ...so that the definition in impl matches the definition from the trait
+   | |________________________________________^ found
 
-error[E0309]: the associated type `<Right as HasChildrenOf>::T` may not live long enough
+error: `impl` associated type signature for `TRef` doesn't match `trait` associated type signature
   --> $DIR/issue-86787.rs:23:5
    |
+LL |       type TRef<'a>;
+   |       -------------- expected
+...
 LL | /     type TRef<'a>
 LL | |
 LL | |
 LL | |     where
 LL | |     <Left as HasChildrenOf>::T: 'a,
 LL | |     <Right as HasChildrenOf>::T: 'a
-   | |                                    - help: consider adding a where clause: `, <Right as HasChildrenOf>::T: 'a`
 LL | |     = Either<&'a Left::T, &'a Right::T>;
-   | |________________________________________^ ...so that the definition in impl matches the definition from the trait
+   | |________________________________________^ found
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/generic-associated-types/issue-88287.rs b/src/test/ui/generic-associated-types/issue-88287.rs
new file mode 100644
index 0000000000000..2e65af594a6bd
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-88287.rs
@@ -0,0 +1,39 @@
+// check-pass
+// edition:2018
+
+#![feature(generic_associated_types)]
+#![feature(type_alias_impl_trait)]
+
+use std::future::Future;
+
+trait SearchableResource<Criteria> {
+    type SearchResult;
+}
+
+trait SearchableResourceExt<Criteria>: SearchableResource<Criteria> {
+    type Future<'f, A: 'f + ?Sized, B: 'f>: Future<Output = Result<Vec<A::SearchResult>, ()>> + 'f
+    where
+        A: SearchableResource<B>;
+
+    fn search<'c>(&'c self, client: &'c ()) -> Self::Future<'c, Self, Criteria>;
+}
+
+type SearchFutureTy<'f, A, B: 'f>
+where
+    A: SearchableResource<B> + ?Sized + 'f,
+= impl Future<Output = Result<Vec<A::SearchResult>, ()>> + 'f;
+impl<T, Criteria> SearchableResourceExt<Criteria> for T
+where
+    T: SearchableResource<Criteria>,
+{
+    type Future<'f, A, B: 'f>
+    where
+        A: SearchableResource<B> + ?Sized + 'f,
+    = SearchFutureTy<'f, A, B>;
+
+    fn search<'c>(&'c self, _client: &'c ()) -> Self::Future<'c, Self, Criteria> {
+        async move { todo!() }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-88405.rs b/src/test/ui/generic-associated-types/issue-88405.rs
new file mode 100644
index 0000000000000..4a405bd3625c1
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-88405.rs
@@ -0,0 +1,16 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+
+trait SomeTrait {}
+trait OtherTrait {
+    type Item;
+}
+
+trait ErrorSimpleExample {
+    type AssociatedType: SomeTrait;
+    type GatBounded<T: SomeTrait>;
+    type ErrorMinimal: OtherTrait<Item = Self::GatBounded<Self::AssociatedType>>;
+}
+
+fn main() {}