Rollup merge of #106928 - bvanjoi:print-keyword-raw-identifier, r=petrochenkov

add raw identifier for keyword in suggestion

fix https://github.com/rust-lang/rust/issues/106841
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index 9cf4d8c..82ff862 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -359,9 +359,9 @@
                         .insert(ty::OutlivesPredicate(GenericKind::Param(param_b), r_a));
                 }
 
-                OutlivesBound::RegionSubAlias(r_a, kind, alias_b) => {
+                OutlivesBound::RegionSubAlias(r_a, alias_b) => {
                     self.region_bound_pairs
-                        .insert(ty::OutlivesPredicate(GenericKind::Alias(kind, alias_b), r_a));
+                        .insert(ty::OutlivesPredicate(GenericKind::Alias(alias_b), r_a));
                 }
             }
         }
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 9031c04..ce72b78 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -2602,7 +2602,7 @@
         match path.res {
             Res::Def(DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder, did) => {
                 // Check for desugared `impl Trait`.
-                assert!(ty::is_impl_trait_defn(tcx, did).is_none());
+                assert!(tcx.is_type_alias_impl_trait(did));
                 let item_segment = path.segments.split_last().unwrap();
                 self.prohibit_generics(item_segment.1.iter(), |err| {
                     err.note("`impl Trait` types can't have type parameters");
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 35f47df..9be37db 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -76,6 +76,7 @@
         is_foreign_item,
         generator_kind,
         collect_mod_item_types,
+        is_type_alias_impl_trait,
         ..*providers
     };
 }
@@ -1537,3 +1538,13 @@
         _ => bug!("generator_kind applied to non-local def-id {:?}", def_id),
     }
 }
+
+fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+    match tcx.hir().get_if_local(def_id) {
+        Some(Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(opaque), .. })) => {
+            matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias)
+        }
+        Some(_) => bug!("tried getting opaque_ty_origin for non-opaque: {:?}", def_id),
+        _ => bug!("tried getting opaque_ty_origin for non-local def-id {:?}", def_id),
+    }
+}
diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs
index 3f691be..9459c5f 100644
--- a/compiler/rustc_hir_analysis/src/outlives/utils.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs
@@ -80,7 +80,7 @@
                             .or_insert(span);
                     }
 
-                    Component::Alias(kind, alias) => {
+                    Component::Alias(alias_ty) => {
                         // This would either arise from something like:
                         //
                         // ```
@@ -99,13 +99,13 @@
                         //
                         // Here we want to add an explicit `where <T as Iterator>::Item: 'a`
                         // or `Opaque<T>: 'a` depending on the alias kind.
-                        let ty: Ty<'tcx> = tcx.mk_ty(ty::Alias(kind, alias));
+                        let ty = alias_ty.to_ty(tcx);
                         required_predicates
                             .entry(ty::OutlivesPredicate(ty.into(), outlived_region))
                             .or_insert(span);
                     }
 
-                    Component::EscapingProjection(_) => {
+                    Component::EscapingAlias(_) => {
                         // As above, but the projection involves
                         // late-bound regions. Therefore, the WF
                         // requirement is not checked in type definition
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
index 16806fd..b3dd303 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
@@ -304,8 +304,8 @@
         let mut reinit = None;
         match expr.kind {
             ExprKind::Assign(lhs, rhs, _) => {
-                self.visit_expr(lhs);
                 self.visit_expr(rhs);
+                self.visit_expr(lhs);
 
                 reinit = Some(lhs);
             }
@@ -433,7 +433,7 @@
                     self.drop_ranges.add_control_edge(self.expr_index, *target)
                 }),
 
-            ExprKind::Break(destination, ..) => {
+            ExprKind::Break(destination, value) => {
                 // destination either points to an expression or to a block. We use
                 // find_target_expression_from_destination to use the last expression of the block
                 // if destination points to a block.
@@ -443,7 +443,11 @@
                 // will refer to the end of the block due to the post order traversal.
                 self.find_target_expression_from_destination(destination).map_or((), |target| {
                     self.drop_ranges.add_control_edge_hir_id(self.expr_index, target)
-                })
+                });
+
+                if let Some(value) = value {
+                    self.visit_expr(value);
+                }
             }
 
             ExprKind::Call(f, args) => {
@@ -465,6 +469,12 @@
 
             ExprKind::AddrOf(..)
             | ExprKind::Array(..)
+            // FIXME(eholk): We probably need special handling for AssignOps. The ScopeTree builder
+            // in region.rs runs both lhs then rhs and rhs then lhs and then sets all yields to be
+            // the latest they show up in either traversal. With the older scope-based
+            // approximation, this was fine, but it's probably not right now. What we probably want
+            // to do instead is still run both orders, but consider anything that showed up as a
+            // yield in either order.
             | ExprKind::AssignOp(..)
             | ExprKind::Binary(..)
             | ExprKind::Block(..)
@@ -502,6 +512,9 @@
 
         // Increment expr_count here to match what InteriorVisitor expects.
         self.expr_index = self.expr_index + 1;
+
+        // Save a node mapping to get better CFG visualization
+        self.drop_ranges.add_node_mapping(pat.hir_id, self.expr_index);
     }
 }
 
@@ -521,7 +534,7 @@
                 }
             });
         }
-        debug!("hir_id_map: {:?}", tracked_value_map);
+        debug!("hir_id_map: {:#?}", tracked_value_map);
         let num_values = tracked_value_map.len();
         Self {
             tracked_value_map,
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs
index c0a0bfe..e8d31be 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs
@@ -2,6 +2,7 @@
 //! flow graph when needed for debugging.
 
 use rustc_graphviz as dot;
+use rustc_hir::{Expr, ExprKind, Node};
 use rustc_middle::ty::TyCtxt;
 
 use super::{DropRangesBuilder, PostOrderId};
@@ -80,10 +81,14 @@
                     .post_order_map
                     .iter()
                     .find(|(_hir_id, &post_order_id)| post_order_id == *n)
-                    .map_or("<unknown>".into(), |(hir_id, _)| self
-                        .tcx
-                        .hir()
-                        .node_to_string(*hir_id))
+                    .map_or("<unknown>".into(), |(hir_id, _)| format!(
+                        "{}{}",
+                        self.tcx.hir().node_to_string(*hir_id),
+                        match self.tcx.hir().find(*hir_id) {
+                            Some(Node::Expr(Expr { kind: ExprKind::Yield(..), .. })) => " (yield)",
+                            _ => "",
+                        }
+                    ))
             )
             .into(),
         )
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
index 7990d95..7af5260 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
@@ -71,10 +71,8 @@
                                 yield_data.expr_and_pat_count, self.expr_count, source_span
                             );
 
-                            if self.fcx.sess().opts.unstable_opts.drop_tracking
-                                && self
-                                    .drop_ranges
-                                    .is_dropped_at(hir_id, yield_data.expr_and_pat_count)
+                            if self
+                                .is_dropped_at_yield_location(hir_id, yield_data.expr_and_pat_count)
                             {
                                 debug!("value is dropped at yield point; not recording");
                                 return false;
@@ -173,6 +171,18 @@
             }
         }
     }
+
+    /// If drop tracking is enabled, consult drop_ranges to see if a value is
+    /// known to be dropped at a yield point and therefore can be omitted from
+    /// the generator witness.
+    fn is_dropped_at_yield_location(&self, value_hir_id: HirId, yield_location: usize) -> bool {
+        // short-circuit if drop tracking is not enabled.
+        if !self.fcx.sess().opts.unstable_opts.drop_tracking {
+            return false;
+        }
+
+        self.drop_ranges.is_dropped_at(value_hir_id, yield_location)
+    }
 }
 
 pub fn resolve_interior<'a, 'tcx>(
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 9c38eb6..28fd03b 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -2272,13 +2272,10 @@
 
         let labeled_user_string = match bound_kind {
             GenericKind::Param(ref p) => format!("the parameter type `{}`", p),
-            GenericKind::Alias(ty::Projection, ref p) => format!("the associated type `{}`", p),
-            GenericKind::Alias(ty::Opaque, ref p) => {
-                format!(
-                    "the opaque type `{}`",
-                    self.tcx.def_path_str_with_substs(p.def_id, p.substs)
-                )
-            }
+            GenericKind::Alias(ref p) => match p.kind(self.tcx) {
+                ty::AliasKind::Projection => format!("the associated type `{}`", p),
+                ty::AliasKind::Opaque => format!("the opaque type `{}`", p),
+            },
         };
 
         if let Some(SubregionOrigin::CompareImplItemObligation {
diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs
index 37907d2..3d86279 100644
--- a/compiler/rustc_infer/src/infer/outlives/components.rs
+++ b/compiler/rustc_infer/src/infer/outlives/components.rs
@@ -22,7 +22,7 @@
     // is not in a position to judge which is the best technique, so
     // we just product the projection as a component and leave it to
     // the consumer to decide (but see `EscapingProjection` below).
-    Alias(ty::AliasKind, ty::AliasTy<'tcx>),
+    Alias(ty::AliasTy<'tcx>),
 
     // In the case where a projection has escaping regions -- meaning
     // regions bound within the type itself -- we always use
@@ -44,7 +44,7 @@
     // projection, so that implied bounds code can avoid relying on
     // them. This gives us room to improve the regionck reasoning in
     // the future without breaking backwards compat.
-    EscapingProjection(Vec<Component<'tcx>>),
+    EscapingAlias(Vec<Component<'tcx>>),
 }
 
 /// Push onto `out` all the things that must outlive `'a` for the condition
@@ -120,17 +120,6 @@
                 out.push(Component::Param(p));
             }
 
-            // Ignore lifetimes found in opaque types. Opaque types can
-            // have lifetimes in their substs which their hidden type doesn't
-            // actually use. If we inferred that an opaque type is outlived by
-            // its parameter lifetimes, then we could prove that any lifetime
-            // outlives any other lifetime, which is unsound.
-            // See https://github.com/rust-lang/rust/issues/84305 for
-            // more details.
-            ty::Alias(ty::Opaque, data) => {
-                out.push(Component::Alias(ty::Opaque, data));
-            },
-
             // For projections, we prefer to generate an obligation like
             // `<P0 as Trait<P1...Pn>>::Foo: 'a`, because this gives the
             // regionck more ways to prove that it holds. However,
@@ -139,15 +128,15 @@
             // trait-ref. Therefore, if we see any higher-ranked regions,
             // we simply fallback to the most restrictive rule, which
             // requires that `Pi: 'a` for all `i`.
-            ty::Alias(ty::Projection, data) => {
-                if !data.has_escaping_bound_vars() {
+            ty::Alias(_, alias_ty) => {
+                if !alias_ty.has_escaping_bound_vars() {
                     // best case: no escaping regions, so push the
                     // projection and skip the subtree (thus generating no
                     // constraints for Pi). This defers the choice between
                     // the rules OutlivesProjectionEnv,
                     // OutlivesProjectionTraitDef, and
                     // OutlivesProjectionComponents to regionck.
-                    out.push(Component::Alias(ty::Projection, data));
+                    out.push(Component::Alias(alias_ty));
                 } else {
                     // fallback case: hard code
                     // OutlivesProjectionComponents. Continue walking
@@ -155,7 +144,7 @@
                     let mut subcomponents = smallvec![];
                     let mut subvisited = SsoHashSet::new();
                     compute_components_recursive(tcx, ty.into(), &mut subcomponents, &mut subvisited);
-                    out.push(Component::EscapingProjection(subcomponents.into_iter().collect()));
+                    out.push(Component::EscapingAlias(subcomponents.into_iter().collect()));
                 }
             }
 
diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs
index 52c3d97..24e3c34 100644
--- a/compiler/rustc_infer/src/infer/outlives/env.rs
+++ b/compiler/rustc_infer/src/infer/outlives/env.rs
@@ -138,9 +138,9 @@
                     self.region_bound_pairs
                         .insert(ty::OutlivesPredicate(GenericKind::Param(param_b), r_a));
                 }
-                OutlivesBound::RegionSubAlias(r_a, kind, projection_b) => {
+                OutlivesBound::RegionSubAlias(r_a, alias_b) => {
                     self.region_bound_pairs
-                        .insert(ty::OutlivesPredicate(GenericKind::Alias(kind, projection_b), r_a));
+                        .insert(ty::OutlivesPredicate(GenericKind::Alias(alias_b), r_a));
                 }
                 OutlivesBound::RegionSubRegion(r_a, r_b) => {
                     if let (ReEarlyBound(_) | ReFree(_), ReVar(vid_b)) = (r_a.kind(), r_b.kind()) {
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index 77de335..0194549 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -67,7 +67,6 @@
 };
 use crate::traits::{ObligationCause, ObligationCauseCode};
 use rustc_data_structures::undo_log::UndoLogs;
-use rustc_hir::def_id::DefId;
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, Region, SubstsRef, Ty, TyCtxt, TypeVisitable};
@@ -266,10 +265,8 @@
                 Component::Param(param_ty) => {
                     self.param_ty_must_outlive(origin, region, *param_ty);
                 }
-                Component::Alias(kind, data) => {
-                    self.alias_must_outlive(*kind, *data, origin, region)
-                }
-                Component::EscapingProjection(subcomponents) => {
+                Component::Alias(alias_ty) => self.alias_ty_must_outlive(origin, region, *alias_ty),
+                Component::EscapingAlias(subcomponents) => {
                     self.components_must_outlive(origin, &subcomponents, region, category);
                 }
                 Component::UnresolvedInferenceVariable(v) => {
@@ -285,61 +282,26 @@
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn param_ty_must_outlive(
         &mut self,
         origin: infer::SubregionOrigin<'tcx>,
         region: ty::Region<'tcx>,
         param_ty: ty::ParamTy,
     ) {
-        debug!(
-            "param_ty_must_outlive(region={:?}, param_ty={:?}, origin={:?})",
-            region, param_ty, origin
-        );
-
-        let generic = GenericKind::Param(param_ty);
         let verify_bound = self.verify_bound.param_bound(param_ty);
-        self.delegate.push_verify(origin, generic, region, verify_bound);
+        self.delegate.push_verify(origin, GenericKind::Param(param_ty), region, verify_bound);
     }
 
     #[instrument(level = "debug", skip(self))]
-    fn alias_must_outlive(
-        &mut self,
-        kind: ty::AliasKind,
-        data: ty::AliasTy<'tcx>,
-        origin: infer::SubregionOrigin<'tcx>,
-        region: ty::Region<'tcx>,
-    ) {
-        self.generic_must_outlive(
-            origin,
-            region,
-            GenericKind::Alias(kind, data),
-            data.def_id,
-            data.substs,
-            kind == ty::Opaque,
-            |ty| match *ty.kind() {
-                ty::Alias(filter_kind, ty::AliasTy { def_id, substs, .. })
-                    if kind == filter_kind =>
-                {
-                    (def_id, substs)
-                }
-                _ => bug!("expected only projection types from env, not {:?}", ty),
-            },
-        );
-    }
-
-    #[instrument(level = "debug", skip(self, filter))]
-    fn generic_must_outlive(
+    fn alias_ty_must_outlive(
         &mut self,
         origin: infer::SubregionOrigin<'tcx>,
         region: ty::Region<'tcx>,
-        generic: GenericKind<'tcx>,
-        def_id: DefId,
-        substs: SubstsRef<'tcx>,
-        is_opaque: bool,
-        filter: impl Fn(Ty<'tcx>) -> (DefId, SubstsRef<'tcx>),
+        alias_ty: ty::AliasTy<'tcx>,
     ) {
         // An optimization for a common case with opaque types.
-        if substs.is_empty() {
+        if alias_ty.substs.is_empty() {
             return;
         }
 
@@ -361,14 +323,14 @@
         // These are guaranteed to apply, no matter the inference
         // results.
         let trait_bounds: Vec<_> =
-            self.verify_bound.declared_region_bounds(def_id, substs).collect();
+            self.verify_bound.declared_bounds_from_definition(alias_ty).collect();
 
         debug!(?trait_bounds);
 
         // Compute the bounds we can derive from the environment. This
         // is an "approximate" match -- in some cases, these bounds
         // may not apply.
-        let mut approx_env_bounds = self.verify_bound.approx_declared_bounds_from_env(generic);
+        let mut approx_env_bounds = self.verify_bound.approx_declared_bounds_from_env(alias_ty);
         debug!(?approx_env_bounds);
 
         // Remove outlives bounds that we get from the environment but
@@ -383,8 +345,8 @@
             // If the declaration is `trait Trait<'b> { type Item: 'b; }`, then `projection_declared_bounds_from_trait`
             // will be invoked with `['b => ^1]` and so we will get `^1` returned.
             let bound = bound_outlives.skip_binder();
-            let (def_id, substs) = filter(bound.0);
-            self.verify_bound.declared_region_bounds(def_id, substs).all(|r| r != bound.1)
+            let ty::Alias(_, alias_ty) = bound.0.kind() else { bug!("expected AliasTy") };
+            self.verify_bound.declared_bounds_from_definition(*alias_ty).all(|r| r != bound.1)
         });
 
         // If declared bounds list is empty, the only applicable rule is
@@ -401,12 +363,12 @@
         // the problem is to add `T: 'r`, which isn't true. So, if there are no
         // inference variables, we use a verify constraint instead of adding
         // edges, which winds up enforcing the same condition.
-        let needs_infer = substs.needs_infer();
-        if approx_env_bounds.is_empty() && trait_bounds.is_empty() && (needs_infer || is_opaque) {
+        if approx_env_bounds.is_empty()
+            && trait_bounds.is_empty()
+            && (alias_ty.needs_infer() || alias_ty.kind(self.tcx) == ty::Opaque)
+        {
             debug!("no declared bounds");
-
-            self.substs_must_outlive(substs, origin, region);
-
+            self.substs_must_outlive(alias_ty.substs, origin, region);
             return;
         }
 
@@ -447,14 +409,9 @@
         // projection outlive; in some cases, this may add insufficient
         // edges into the inference graph, leading to inference failures
         // even though a satisfactory solution exists.
-        let verify_bound = self.verify_bound.projection_opaque_bounds(
-            generic,
-            def_id,
-            substs,
-            &mut Default::default(),
-        );
-        debug!("projection_must_outlive: pushing {:?}", verify_bound);
-        self.delegate.push_verify(origin, generic, region, verify_bound);
+        let verify_bound = self.verify_bound.alias_bound(alias_ty, &mut Default::default());
+        debug!("alias_must_outlive: pushing {:?}", verify_bound);
+        self.delegate.push_verify(origin, GenericKind::Alias(alias_ty), region, verify_bound);
     }
 
     fn substs_must_outlive(
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index 56695a8..94de9bc 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -1,11 +1,10 @@
 use crate::infer::outlives::components::{compute_components_recursive, Component};
 use crate::infer::outlives::env::RegionBoundPairs;
 use crate::infer::region_constraints::VerifyIfEq;
-use crate::infer::{GenericKind, VerifyBound};
+use crate::infer::VerifyBound;
 use rustc_data_structures::sso::SsoHashSet;
-use rustc_hir::def_id::DefId;
 use rustc_middle::ty::GenericArg;
-use rustc_middle::ty::{self, OutlivesPredicate, SubstsRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, OutlivesPredicate, Ty, TyCtxt};
 
 use smallvec::smallvec;
 
@@ -94,29 +93,26 @@
     /// this list.
     pub fn approx_declared_bounds_from_env(
         &self,
-        generic: GenericKind<'tcx>,
+        alias_ty: ty::AliasTy<'tcx>,
     ) -> Vec<ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>> {
-        let projection_ty = generic.to_ty(self.tcx);
-        let erased_projection_ty = self.tcx.erase_regions(projection_ty);
-        self.declared_generic_bounds_from_env_for_erased_ty(erased_projection_ty)
+        let erased_alias_ty = self.tcx.erase_regions(alias_ty.to_ty(self.tcx));
+        self.declared_generic_bounds_from_env_for_erased_ty(erased_alias_ty)
     }
 
     #[instrument(level = "debug", skip(self, visited))]
-    pub fn projection_opaque_bounds(
+    pub fn alias_bound(
         &self,
-        generic: GenericKind<'tcx>,
-        def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        alias_ty: ty::AliasTy<'tcx>,
         visited: &mut SsoHashSet<GenericArg<'tcx>>,
     ) -> VerifyBound<'tcx> {
-        let generic_ty = generic.to_ty(self.tcx);
+        let alias_ty_as_ty = alias_ty.to_ty(self.tcx);
 
         // Search the env for where clauses like `P: 'a`.
-        let projection_opaque_bounds = self
-            .approx_declared_bounds_from_env(generic)
+        let env_bounds = self
+            .approx_declared_bounds_from_env(alias_ty)
             .into_iter()
             .map(|binder| {
-                if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars() && ty == generic_ty {
+                if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars() && ty == alias_ty_as_ty {
                     // Micro-optimize if this is an exact match (this
                     // occurs often when there are no region variables
                     // involved).
@@ -126,19 +122,19 @@
                     VerifyBound::IfEq(verify_if_eq_b)
                 }
             });
-        // Extend with bounds that we can find from the trait.
-        let trait_bounds =
-            self.declared_region_bounds(def_id, substs).map(|r| VerifyBound::OutlivedBy(r));
+
+        // Extend with bounds that we can find from the definition.
+        let definition_bounds =
+            self.declared_bounds_from_definition(alias_ty).map(|r| VerifyBound::OutlivedBy(r));
 
         // see the extensive comment in projection_must_outlive
         let recursive_bound = {
             let mut components = smallvec![];
-            compute_components_recursive(self.tcx, generic_ty.into(), &mut components, visited);
+            compute_components_recursive(self.tcx, alias_ty_as_ty.into(), &mut components, visited);
             self.bound_from_components(&components, visited)
         };
 
-        VerifyBound::AnyBound(projection_opaque_bounds.chain(trait_bounds).collect())
-            .or(recursive_bound)
+        VerifyBound::AnyBound(env_bounds.chain(definition_bounds).collect()).or(recursive_bound)
     }
 
     fn bound_from_components(
@@ -149,10 +145,8 @@
         let mut bounds = components
             .iter()
             .map(|component| self.bound_from_single_component(component, visited))
-            .filter(|bound| {
-                // Remove bounds that must hold, since they are not interesting.
-                !bound.must_hold()
-            });
+            // Remove bounds that must hold, since they are not interesting.
+            .filter(|bound| !bound.must_hold());
 
         match (bounds.next(), bounds.next()) {
             (Some(first), None) => first,
@@ -170,13 +164,8 @@
         match *component {
             Component::Region(lt) => VerifyBound::OutlivedBy(lt),
             Component::Param(param_ty) => self.param_bound(param_ty),
-            Component::Alias(kind, data) => self.projection_opaque_bounds(
-                GenericKind::Alias(kind, data),
-                data.def_id,
-                data.substs,
-                visited,
-            ),
-            Component::EscapingProjection(ref components) => {
+            Component::Alias(alias_ty) => self.alias_bound(alias_ty, visited),
+            Component::EscapingAlias(ref components) => {
                 self.bound_from_components(components, visited)
             }
             Component::UnresolvedInferenceVariable(v) => {
@@ -292,16 +281,15 @@
     ///
     /// This is for simplicity, and because we are not really smart
     /// enough to cope with such bounds anywhere.
-    pub fn declared_region_bounds(
+    pub fn declared_bounds_from_definition(
         &self,
-        def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        alias_ty: ty::AliasTy<'tcx>,
     ) -> impl Iterator<Item = ty::Region<'tcx>> {
         let tcx = self.tcx;
-        let bounds = tcx.item_bounds(def_id);
+        let bounds = tcx.item_bounds(alias_ty.def_id);
         trace!("{:#?}", bounds.0);
         bounds
-            .subst_iter(tcx, substs)
+            .subst_iter(tcx, alias_ty.substs)
             .filter_map(|p| p.to_opt_type_outlives())
             .filter_map(|p| p.no_bound_vars())
             .map(|OutlivesPredicate(_, r)| r)
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index fda5ffe..0428481 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -167,7 +167,7 @@
 #[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
 pub enum GenericKind<'tcx> {
     Param(ty::ParamTy),
-    Alias(ty::AliasKind, ty::AliasTy<'tcx>),
+    Alias(ty::AliasTy<'tcx>),
 }
 
 /// Describes the things that some `GenericKind` value `G` is known to
@@ -746,10 +746,7 @@
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             GenericKind::Param(ref p) => write!(f, "{:?}", p),
-            GenericKind::Alias(ty::Projection, ref p) => write!(f, "{:?}", p),
-            GenericKind::Alias(ty::Opaque, ref p) => ty::tls::with(|tcx| {
-                write!(f, "{}", tcx.def_path_str_with_substs(p.def_id, tcx.lift(p.substs).unwrap()))
-            }),
+            GenericKind::Alias(ref p) => write!(f, "{:?}", p),
         }
     }
 }
@@ -758,10 +755,7 @@
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             GenericKind::Param(ref p) => write!(f, "{}", p),
-            GenericKind::Alias(ty::Projection, ref p) => write!(f, "{}", p),
-            GenericKind::Alias(ty::Opaque, ref p) => ty::tls::with(|tcx| {
-                write!(f, "{}", tcx.def_path_str_with_substs(p.def_id, tcx.lift(p.substs).unwrap()))
-            }),
+            GenericKind::Alias(ref p) => write!(f, "{}", p),
         }
     }
 }
@@ -770,7 +764,7 @@
     pub fn to_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         match *self {
             GenericKind::Param(ref p) => p.to_ty(tcx),
-            GenericKind::Alias(kind, data) => tcx.mk_ty(ty::Alias(kind, data)),
+            GenericKind::Alias(ref p) => p.to_ty(tcx),
         }
     }
 }
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 4ada7b2..cd5bde2 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -261,14 +261,15 @@
 
                             Component::UnresolvedInferenceVariable(_) => None,
 
-                            Component::Alias(kind, data) => {
-                                let ty = tcx.mk_ty(ty::Alias(kind, data));
+                            Component::Alias(alias_ty) => {
+                                // We might end up here if we have `Foo<<Bar as Baz>::Assoc>: 'a`.
+                                // With this, we can deduce that `<Bar as Baz>::Assoc: 'a`.
                                 Some(ty::PredicateKind::Clause(ty::Clause::TypeOutlives(
-                                    ty::OutlivesPredicate(ty, r_min),
+                                    ty::OutlivesPredicate(alias_ty.to_ty(tcx), r_min),
                                 )))
                             }
 
-                            Component::EscapingProjection(_) => {
+                            Component::EscapingAlias(_) => {
                                 // We might be able to do more here, but we don't
                                 // want to deal with escaping vars right now.
                                 None
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index cb45193..0d924f2 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -223,6 +223,15 @@
     generator_kind => { table }
     trait_def => { table }
     deduced_param_attrs => { table }
+    is_type_alias_impl_trait => {
+        debug_assert_eq!(tcx.def_kind(def_id), DefKind::OpaqueTy);
+        cdata
+            .root
+            .tables
+            .is_type_alias_impl_trait
+            .get(cdata, def_id.index)
+            .is_some()
+    }
     collect_return_position_impl_trait_in_trait_tys => {
         Ok(cdata
             .root
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index a3d44fa..ab2ad79 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1512,8 +1512,11 @@
             hir::ItemKind::Mod(ref m) => {
                 return self.encode_info_for_mod(item.owner_id.def_id, m);
             }
-            hir::ItemKind::OpaqueTy(..) => {
+            hir::ItemKind::OpaqueTy(ref opaque) => {
                 self.encode_explicit_item_bounds(def_id);
+                if matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias) {
+                    self.tables.is_type_alias_impl_trait.set(def_id.index, ());
+                }
             }
             hir::ItemKind::Enum(..) => {
                 let adt_def = self.tcx.adt_def(def_id);
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 5b7b096..5066dbb 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -404,6 +404,8 @@
     proc_macro: Table<DefIndex, MacroKind>,
     module_reexports: Table<DefIndex, LazyArray<ModChild>>,
     deduced_param_attrs: Table<DefIndex, LazyArray<DeducedParamAttrs>>,
+    // Slot is full when opaque is TAIT.
+    is_type_alias_impl_trait: Table<DefIndex, ()>,
 
     trait_impl_trait_tys: Table<DefIndex, LazyValue<FxHashMap<DefId, Ty<'static>>>>,
 }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 0ec6f48..6bbf7fa 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -177,6 +177,12 @@
         separate_provide_extern
     }
 
+    query is_type_alias_impl_trait(key: DefId) -> bool
+    {
+        desc { "determine whether the opaque is a type-alias impl trait" }
+        separate_provide_extern
+    }
+
     query analysis(key: ()) -> Result<(), ErrorGuaranteed> {
         eval_always
         desc { "running analysis passes on this crate" }
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index 2a68315..615154a 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -213,5 +213,5 @@
 pub enum OutlivesBound<'tcx> {
     RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
     RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
-    RegionSubAlias(ty::Region<'tcx>, ty::AliasKind, ty::AliasTy<'tcx>),
+    RegionSubAlias(ty::Region<'tcx>, ty::AliasTy<'tcx>),
 }
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index e32a7ee..24f3d1a 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -52,6 +52,7 @@
     usize,
     (),
     u32,
+    bool,
     std::string::String,
     crate::metadata::ModChild,
     crate::middle::codegen_fn_attrs::CodegenFnAttrs,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index a128e90..6a7b23e 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1245,19 +1245,34 @@
     /// aka. `tcx.parent(def_id)`.
     pub def_id: DefId,
 
-    /// This field exists to prevent the creation of `ProjectionTy` without using
+    /// This field exists to prevent the creation of `AliasTy` without using
     /// [TyCtxt::mk_alias_ty].
     pub(super) _use_mk_alias_ty_instead: (),
 }
 
 impl<'tcx> AliasTy<'tcx> {
+    pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasKind {
+        match tcx.def_kind(self.def_id) {
+            DefKind::AssocTy | DefKind::ImplTraitPlaceholder => ty::Projection,
+            DefKind::OpaqueTy => ty::Opaque,
+            kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
+        }
+    }
+
+    pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+        tcx.mk_ty(ty::Alias(self.kind(tcx), self))
+    }
+}
+
+/// The following methods work only with associated type projections.
+impl<'tcx> AliasTy<'tcx> {
     pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
         match tcx.def_kind(self.def_id) {
             DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
             DefKind::ImplTraitPlaceholder => {
                 tcx.parent(tcx.impl_trait_in_trait_parent(self.def_id))
             }
-            kind => bug!("unexpected DefKind in ProjectionTy: {kind:?}"),
+            kind => bug!("expected a projection AliasTy; found {kind:?}"),
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 434f75d..5297148 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1350,6 +1350,7 @@
                         expected_trait_ref,
                         obligation.cause.code(),
                         found_node,
+                        obligation.param_env,
                     )
                 } else {
                     let (closure_span, closure_arg_span, found) = found_did
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 195bbe9..39e50b2 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -283,6 +283,7 @@
         expected: ty::PolyTraitRef<'tcx>,
         cause: &ObligationCauseCode<'tcx>,
         found_node: Option<Node<'_>>,
+        param_env: ty::ParamEnv<'tcx>,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
 
     fn note_conflicting_closure_bounds(
@@ -1978,6 +1979,7 @@
         expected: ty::PolyTraitRef<'tcx>,
         cause: &ObligationCauseCode<'tcx>,
         found_node: Option<Node<'_>>,
+        param_env: ty::ParamEnv<'tcx>,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         pub(crate) fn build_fn_sig_ty<'tcx>(
             infcx: &InferCtxt<'tcx>,
@@ -2040,7 +2042,7 @@
         self.note_conflicting_closure_bounds(cause, &mut err);
 
         if let Some(found_node) = found_node {
-            hint_missing_borrow(span, found, expected, found_node, &mut err);
+            hint_missing_borrow(self, param_env, span, found, expected, found_node, &mut err);
         }
 
         err
@@ -3747,6 +3749,8 @@
 
 /// Add a hint to add a missing borrow or remove an unnecessary one.
 fn hint_missing_borrow<'tcx>(
+    infcx: &InferCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
     span: Span,
     found: Ty<'tcx>,
     expected: Ty<'tcx>,
@@ -3769,7 +3773,7 @@
     // This could be a variant constructor, for example.
     let Some(fn_decl) = found_node.fn_decl() else { return; };
 
-    let arg_spans = fn_decl.inputs.iter().map(|ty| ty.span);
+    let args = fn_decl.inputs.iter().map(|ty| ty);
 
     fn get_deref_type_and_refs(mut ty: Ty<'_>) -> (Ty<'_>, usize) {
         let mut refs = 0;
@@ -3785,21 +3789,34 @@
     let mut to_borrow = Vec::new();
     let mut remove_borrow = Vec::new();
 
-    for ((found_arg, expected_arg), arg_span) in found_args.zip(expected_args).zip(arg_spans) {
+    for ((found_arg, expected_arg), arg) in found_args.zip(expected_args).zip(args) {
         let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg);
         let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg);
 
-        if found_ty == expected_ty {
+        if infcx.can_eq(param_env, found_ty, expected_ty).is_ok() {
             if found_refs < expected_refs {
-                to_borrow.push((arg_span, expected_arg.to_string()));
+                to_borrow.push((arg.span.shrink_to_lo(), "&".repeat(expected_refs - found_refs)));
             } else if found_refs > expected_refs {
-                remove_borrow.push((arg_span, expected_arg.to_string()));
+                let mut span = arg.span.shrink_to_lo();
+                let mut left = found_refs - expected_refs;
+                let mut ty = arg;
+                while let hir::TyKind::Ref(_, mut_ty) = &ty.kind && left > 0 {
+                    span = span.with_hi(mut_ty.ty.span.lo());
+                    ty = mut_ty.ty;
+                    left -= 1;
+                }
+                let sugg = if left == 0 {
+                    (span, String::new())
+                } else {
+                    (arg.span, expected_arg.to_string())
+                };
+                remove_borrow.push(sugg);
             }
         }
     }
 
     if !to_borrow.is_empty() {
-        err.multipart_suggestion(
+        err.multipart_suggestion_verbose(
             "consider borrowing the argument",
             to_borrow,
             Applicability::MaybeIncorrect,
@@ -3807,7 +3824,7 @@
     }
 
     if !remove_borrow.is_empty() {
-        err.multipart_suggestion(
+        err.multipart_suggestion_verbose(
             "do not borrow the argument",
             remove_borrow,
             Applicability::MaybeIncorrect,
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index b47a70b..12d4cb4 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -654,7 +654,7 @@
                     // All of the requirements on type parameters
                     // have already been checked for `impl Trait` in
                     // return position. We do need to check type-alias-impl-trait though.
-                    if ty::is_impl_trait_defn(self.tcx, def_id).is_none() {
+                    if self.tcx.is_type_alias_impl_trait(def_id) {
                         let obligations = self.nominal_obligations(def_id, substs);
                         self.out.extend(obligations);
                     }
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index d457a4a..7d2d843 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -154,10 +154,8 @@
             match component {
                 Component::Region(r) => Some(OutlivesBound::RegionSubRegion(sub_region, r)),
                 Component::Param(p) => Some(OutlivesBound::RegionSubParam(sub_region, p)),
-                Component::Alias(kind, p) => {
-                    Some(OutlivesBound::RegionSubAlias(sub_region, kind, p))
-                }
-                Component::EscapingProjection(_) =>
+                Component::Alias(p) => Some(OutlivesBound::RegionSubAlias(sub_region, p)),
+                Component::EscapingAlias(_) =>
                 // If the projection has escaping regions, don't
                 // try to infer any implied bounds even for its
                 // free components. This is conservative, because
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index ca3e991..bc8bada 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -138,7 +138,7 @@
         Ok((ret, krates))
     }
 
-    /// Read a file and return all lines that match the <code>"{crate}":{data},\ </code> format,
+    /// Read a file and return all lines that match the <code>"{crate}":{data},\</code> format,
     /// and return a tuple `(Vec<DataString>, Vec<CrateNameString>)`.
     ///
     /// This forms the payload of files that look like this:
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 7db4703..22068eb 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -5,10 +5,8 @@
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
-use rustc_hir::intravisit::{walk_item, Visitor};
 use rustc_hir::Node;
 use rustc_hir::CRATE_HIR_ID;
-use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -59,6 +57,9 @@
     false
 }
 
+// Also, is there some reason that this doesn't use the 'visit'
+// framework from syntax?.
+
 pub(crate) struct RustdocVisitor<'a, 'tcx> {
     cx: &'a mut core::DocContext<'tcx>,
     view_item_stack: FxHashSet<hir::HirId>,
@@ -66,7 +67,6 @@
     /// Are the current module and all of its parents public?
     inside_public_path: bool,
     exact_paths: FxHashMap<DefId, Vec<Symbol>>,
-    modules: Vec<Module<'tcx>>,
 }
 
 impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
@@ -74,19 +74,12 @@
         // If the root is re-exported, terminate all recursion.
         let mut stack = FxHashSet::default();
         stack.insert(hir::CRATE_HIR_ID);
-        let om = Module::new(
-            cx.tcx.crate_name(LOCAL_CRATE),
-            hir::CRATE_HIR_ID,
-            cx.tcx.hir().root_module().spans.inner_span,
-        );
-
         RustdocVisitor {
             cx,
             view_item_stack: stack,
             inlining: false,
             inside_public_path: true,
             exact_paths: FxHashMap::default(),
-            modules: vec![om],
         }
     }
 
@@ -96,10 +89,12 @@
     }
 
     pub(crate) fn visit(mut self) -> Module<'tcx> {
-        let root_module = self.cx.tcx.hir().root_module();
-        self.visit_mod_contents(CRATE_HIR_ID, root_module);
-
-        let mut top_level_module = self.modules.pop().unwrap();
+        let mut top_level_module = self.visit_mod_contents(
+            hir::CRATE_HIR_ID,
+            self.cx.tcx.hir().root_module(),
+            self.cx.tcx.crate_name(LOCAL_CRATE),
+            None,
+        );
 
         // `#[macro_export] macro_rules!` items are reexported at the top level of the
         // crate, regardless of where they're defined. We want to document the
@@ -114,13 +109,15 @@
         // macro in the same module.
         let mut inserted = FxHashSet::default();
         for export in self.cx.tcx.module_reexports(CRATE_DEF_ID).unwrap_or(&[]) {
-            if let Res::Def(DefKind::Macro(_), def_id) = export.res &&
-                let Some(local_def_id) = def_id.as_local() &&
-                self.cx.tcx.has_attr(def_id, sym::macro_export) &&
-                inserted.insert(def_id)
-            {
-                    let item = self.cx.tcx.hir().expect_item(local_def_id);
-                    top_level_module.items.push((item, None, None));
+            if let Res::Def(DefKind::Macro(_), def_id) = export.res {
+                if let Some(local_def_id) = def_id.as_local() {
+                    if self.cx.tcx.has_attr(def_id, sym::macro_export) {
+                        if inserted.insert(def_id) {
+                            let item = self.cx.tcx.hir().expect_item(local_def_id);
+                            top_level_module.items.push((item, None, None));
+                        }
+                    }
+                }
             }
         }
 
@@ -154,23 +151,24 @@
         top_level_module
     }
 
-    /// This method will go through the given module items in two passes:
-    /// 1. The items which are not glob imports/reexports.
-    /// 2. The glob imports/reexports.
-    fn visit_mod_contents(&mut self, id: hir::HirId, m: &'tcx hir::Mod<'tcx>) {
-        debug!("Going through module {:?}", m);
+    fn visit_mod_contents(
+        &mut self,
+        id: hir::HirId,
+        m: &'tcx hir::Mod<'tcx>,
+        name: Symbol,
+        parent_id: Option<hir::HirId>,
+    ) -> Module<'tcx> {
+        let mut om = Module::new(name, id, m.spans.inner_span);
         let def_id = self.cx.tcx.hir().local_def_id(id).to_def_id();
         // Keep track of if there were any private modules in the path.
         let orig_inside_public_path = self.inside_public_path;
         self.inside_public_path &= self.cx.tcx.visibility(def_id).is_public();
-
-        // Reimplementation of `walk_mod` because we need to do it in two passes (explanations in
-        // the second loop):
         for &i in m.item_ids {
             let item = self.cx.tcx.hir().item(i);
-            if !matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
-                self.visit_item(item);
+            if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
+                continue;
             }
+            self.visit_item(item, None, &mut om, parent_id);
         }
         for &i in m.item_ids {
             let item = self.cx.tcx.hir().item(i);
@@ -178,10 +176,11 @@
             // Later passes in rustdoc will de-duplicate by name and kind, so if glob-
             // imported items appear last, then they'll be the ones that get discarded.
             if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
-                self.visit_item(item);
+                self.visit_item(item, None, &mut om, parent_id);
             }
         }
         self.inside_public_path = orig_inside_public_path;
+        om
     }
 
     /// Tries to resolve the target of a `pub use` statement and inlines the
@@ -199,6 +198,7 @@
         res: Res,
         renamed: Option<Symbol>,
         glob: bool,
+        om: &mut Module<'tcx>,
         please_inline: bool,
     ) -> bool {
         debug!("maybe_inline_local res: {:?}", res);
@@ -249,20 +249,20 @@
                 let prev = mem::replace(&mut self.inlining, true);
                 for &i in m.item_ids {
                     let i = self.cx.tcx.hir().item(i);
-                    self.visit_item_inner(i, None, Some(id));
+                    self.visit_item(i, None, om, Some(id));
                 }
                 self.inlining = prev;
                 true
             }
             Node::Item(it) if !glob => {
                 let prev = mem::replace(&mut self.inlining, true);
-                self.visit_item_inner(it, renamed, Some(id));
+                self.visit_item(it, renamed, om, Some(id));
                 self.inlining = prev;
                 true
             }
             Node::ForeignItem(it) if !glob => {
                 let prev = mem::replace(&mut self.inlining, true);
-                self.visit_foreign_item_inner(it, renamed);
+                self.visit_foreign_item(it, renamed, om);
                 self.inlining = prev;
                 true
             }
@@ -272,22 +272,13 @@
         ret
     }
 
-    #[inline]
-    fn add_to_current_mod(
+    fn visit_item(
         &mut self,
         item: &'tcx hir::Item<'_>,
         renamed: Option<Symbol>,
+        om: &mut Module<'tcx>,
         parent_id: Option<hir::HirId>,
     ) {
-        self.modules.last_mut().unwrap().items.push((item, renamed, parent_id))
-    }
-
-    fn visit_item_inner(
-        &mut self,
-        item: &'tcx hir::Item<'_>,
-        renamed: Option<Symbol>,
-        parent_id: Option<hir::HirId>,
-    ) -> bool {
         debug!("visiting item {:?}", item);
         let name = renamed.unwrap_or(item.ident.name);
 
@@ -302,7 +293,7 @@
             hir::ItemKind::ForeignMod { items, .. } => {
                 for item in items {
                     let item = self.cx.tcx.hir().foreign_item(item.id);
-                    self.visit_foreign_item_inner(item, None);
+                    self.visit_foreign_item(item, None, om);
                 }
             }
             // If we're inlining, skip private items or item reexported as "_".
@@ -335,13 +326,14 @@
                             res,
                             ident,
                             is_glob,
+                            om,
                             please_inline,
                         ) {
                             continue;
                         }
                     }
 
-                    self.add_to_current_mod(item, renamed, parent_id);
+                    om.items.push((item, renamed, parent_id))
                 }
             }
             hir::ItemKind::Macro(ref macro_def, _) => {
@@ -361,11 +353,11 @@
                 let nonexported = !self.cx.tcx.has_attr(def_id, sym::macro_export);
 
                 if is_macro_2_0 || nonexported || self.inlining {
-                    self.add_to_current_mod(item, renamed, None);
+                    om.items.push((item, renamed, None));
                 }
             }
             hir::ItemKind::Mod(ref m) => {
-                self.enter_mod(item.hir_id(), m, name);
+                om.mods.push(self.visit_mod_contents(item.hir_id(), m, name, parent_id));
             }
             hir::ItemKind::Fn(..)
             | hir::ItemKind::ExternCrate(..)
@@ -376,92 +368,33 @@
             | hir::ItemKind::OpaqueTy(..)
             | hir::ItemKind::Static(..)
             | hir::ItemKind::Trait(..)
-            | hir::ItemKind::TraitAlias(..) => {
-                self.add_to_current_mod(item, renamed, parent_id);
-            }
+            | hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed, parent_id)),
             hir::ItemKind::Const(..) => {
                 // Underscore constants do not correspond to a nameable item and
                 // so are never useful in documentation.
                 if name != kw::Underscore {
-                    self.add_to_current_mod(item, renamed, parent_id);
+                    om.items.push((item, renamed, parent_id));
                 }
             }
             hir::ItemKind::Impl(impl_) => {
                 // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
                 // them up regardless of where they're located.
                 if !self.inlining && impl_.of_trait.is_none() {
-                    self.add_to_current_mod(item, None, None);
+                    om.items.push((item, None, None));
                 }
             }
         }
-        true
     }
 
-    fn visit_foreign_item_inner(
+    fn visit_foreign_item(
         &mut self,
         item: &'tcx hir::ForeignItem<'_>,
         renamed: Option<Symbol>,
+        om: &mut Module<'tcx>,
     ) {
         // If inlining we only want to include public functions.
         if !self.inlining || self.cx.tcx.visibility(item.owner_id).is_public() {
-            self.modules.last_mut().unwrap().foreigns.push((item, renamed));
+            om.foreigns.push((item, renamed));
         }
     }
-
-    /// This method will create a new module and push it onto the "modules stack" then call
-    /// `visit_mod_contents`. Once done, it'll remove it from the "modules stack" and instead
-    /// add into the list of modules of the current module.
-    fn enter_mod(&mut self, id: hir::HirId, m: &'tcx hir::Mod<'tcx>, name: Symbol) {
-        self.modules.push(Module::new(name, id, m.spans.inner_span));
-
-        self.visit_mod_contents(id, m);
-
-        let last = self.modules.pop().unwrap();
-        self.modules.last_mut().unwrap().mods.push(last);
-    }
-}
-
-// We need to implement this visitor so it'll go everywhere and retrieve items we're interested in
-// such as impl blocks in const blocks.
-impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
-    type NestedFilter = nested_filter::All;
-
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
-    }
-
-    fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
-        let parent_id = if self.modules.len() > 1 {
-            Some(self.modules[self.modules.len() - 2].id)
-        } else {
-            None
-        };
-        if self.visit_item_inner(i, None, parent_id) {
-            walk_item(self, i);
-        }
-    }
-
-    fn visit_mod(&mut self, _: &hir::Mod<'tcx>, _: Span, _: hir::HirId) {
-        // Handled in `visit_item_inner`
-    }
-
-    fn visit_use(&mut self, _: &hir::UsePath<'tcx>, _: hir::HirId) {
-        // Handled in `visit_item_inner`
-    }
-
-    fn visit_path(&mut self, _: &hir::Path<'tcx>, _: hir::HirId) {
-        // Handled in `visit_item_inner`
-    }
-
-    fn visit_label(&mut self, _: &rustc_ast::Label) {
-        // Unneeded.
-    }
-
-    fn visit_infer(&mut self, _: &hir::InferArg) {
-        // Unneeded.
-    }
-
-    fn visit_lifetime(&mut self, _: &hir::Lifetime) {
-        // Unneeded.
-    }
 }
diff --git a/src/tools/cargo b/src/tools/cargo
index a5d47a7..50eb688 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit a5d47a72595dd6fbe7d4e4f6ec20dc5fe724edd1
+Subproject commit 50eb688c2bbea5de5a2e8496230a7428798089d1
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index c5767a7..c49ecb1 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -426,10 +426,15 @@
                         self.known_bug = true;
                     } else {
                         panic!(
-                            "Invalid known-bug value: {known_bug}\nIt requires comma-separated issue references (`#000` or `chalk#000`) or `unknown`."
+                            "Invalid known-bug value: {known_bug}\nIt requires comma-separated issue references (`#000` or `chalk#000`) or `known-bug: unknown`."
                         );
                     }
+                } else if config.parse_name_directive(ln, KNOWN_BUG) {
+                    panic!(
+                        "Invalid known-bug attribute, requires comma-separated issue references (`#000` or `chalk#000`) or `known-bug: unknown`."
+                    );
                 }
+
                 config.set_name_value_directive(ln, MIR_UNIT_TEST, &mut self.mir_unit_test, |s| {
                     s.trim().to_string()
                 });
diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs b/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
index 939da18..4b1e042 100644
--- a/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
+++ b/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
@@ -1,10 +1,12 @@
+// check-pass
 // normalize-stderr-test: "`.*`" -> "`DEF_ID`"
 // normalize-stdout-test: "`.*`" -> "`DEF_ID`"
 // edition:2018
 
 pub async fn f() -> impl std::fmt::Debug {
+    // rustdoc doesn't care that this is infinitely sized
     #[derive(Debug)]
-    enum E { //~ ERROR
+    enum E {
         This(E),
         Unit,
     }
diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr b/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr
deleted file mode 100644
index aff7402..0000000
--- a/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0072]: recursive type `DEF_ID` has infinite size
-  --> $DIR/infinite-recursive-type-impl-trait-return.rs:7:5
-   |
-LL |     enum E {
-   |     ^^^^^^
-LL |         This(E),
-   |              - recursive without indirection
-   |
-help: insert some indirection (e.g., a `DEF_ID`) to break the cycle
-   |
-LL |         This(Box<E>),
-   |              ++++ +
-
-error: aborting due to previous error
-
-For more information about this error, try `DEF_ID`.
diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs b/tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs
index ac51725..ac79582 100644
--- a/tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs
+++ b/tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs
@@ -1,5 +1,8 @@
+// check-pass
+
 fn f() -> impl Sized {
-    enum E { //~ ERROR
+    // rustdoc doesn't care that this is infinitely sized
+    enum E {
         V(E),
     }
     unimplemented!()
diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr b/tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr
deleted file mode 100644
index a61577b..0000000
--- a/tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0072]: recursive type `f::E` has infinite size
-  --> $DIR/infinite-recursive-type-impl-trait.rs:2:5
-   |
-LL |     enum E {
-   |     ^^^^^^
-LL |         V(E),
-   |           - recursive without indirection
-   |
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
-   |
-LL |         V(Box<E>),
-   |           ++++ +
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0072`.
diff --git a/tests/rustdoc/impl-in-const-block.rs b/tests/rustdoc/impl-in-const-block.rs
deleted file mode 100644
index b44e713..0000000
--- a/tests/rustdoc/impl-in-const-block.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-// Regression test for #83026.
-// The goal of this test is to ensure that impl blocks inside
-// const expressions are documented as well.
-
-#![crate_name = "foo"]
-
-// @has 'foo/struct.A.html'
-// @has - '//*[@id="method.new"]/*[@class="code-header"]' 'pub fn new() -> A'
-// @has - '//*[@id="method.bar"]/*[@class="code-header"]' 'pub fn bar(&self)'
-// @has - '//*[@id="method.woo"]/*[@class="code-header"]' 'pub fn woo(&self)'
-// @has - '//*[@id="method.yoo"]/*[@class="code-header"]' 'pub fn yoo()'
-// @has - '//*[@id="method.yuu"]/*[@class="code-header"]' 'pub fn yuu()'
-pub struct A;
-
-const _: () = {
-    impl A {
-        const FOO: () = {
-            impl A {
-                pub fn woo(&self) {}
-            }
-        };
-
-        pub fn new() -> A {
-            A
-        }
-    }
-};
-pub const X: () = {
-    impl A {
-        pub fn bar(&self) {}
-    }
-};
-
-fn foo() {
-    impl A {
-        pub fn yoo() {}
-    }
-    const _: () = {
-        impl A {
-            pub fn yuu() {}
-        }
-    };
-}
diff --git a/tests/ui/anonymous-higher-ranked-lifetime.stderr b/tests/ui/anonymous-higher-ranked-lifetime.stderr
index afb7f8f..c023d1b 100644
--- a/tests/ui/anonymous-higher-ranked-lifetime.stderr
+++ b/tests/ui/anonymous-higher-ranked-lifetime.stderr
@@ -16,7 +16,7 @@
 help: consider borrowing the argument
    |
 LL |     f1(|_: &(), _: &()| {});
-   |            ~~~     ~~~
+   |            +       +
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:3:5
@@ -35,8 +35,8 @@
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f2`
 help: consider borrowing the argument
    |
-LL |     f2(|_: &'a (), _: &()| {});
-   |            ~~~~~~     ~~~
+LL |     f2(|_: &(), _: &()| {});
+   |            +       +
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5
@@ -56,7 +56,7 @@
 help: consider borrowing the argument
    |
 LL |     f3(|_: &(), _: &()| {});
-   |            ~~~     ~~~
+   |            +       +
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:5:5
@@ -75,8 +75,8 @@
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f4`
 help: consider borrowing the argument
    |
-LL |     f4(|_: &(), _: &'r ()| {});
-   |            ~~~     ~~~~~~
+LL |     f4(|_: &(), _: &()| {});
+   |            +       +
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5
@@ -95,17 +95,15 @@
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f5`
 help: consider borrowing the argument
    |
-LL |     f5(|_: &'r (), _: &'r ()| {});
-   |            ~~~~~~     ~~~~~~
+LL |     f5(|_: &(), _: &()| {});
+   |            +       +
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:7:5
    |
 LL |     g1(|_: (), _: ()| {});
-   |     ^^ --------------
-   |     |  |   |
-   |     |  |   help: consider borrowing the argument: `&()`
-   |     |  found signature defined here
+   |     ^^ -------------- found signature defined here
+   |     |
    |     expected due to this
    |
    = note: expected closure signature `for<'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
@@ -115,15 +113,17 @@
    |
 LL | fn g1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g1`
+help: consider borrowing the argument
+   |
+LL |     g1(|_: &(), _: ()| {});
+   |            +
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5
    |
 LL |     g2(|_: (), _: ()| {});
-   |     ^^ --------------
-   |     |  |   |
-   |     |  |   help: consider borrowing the argument: `&()`
-   |     |  found signature defined here
+   |     ^^ -------------- found signature defined here
+   |     |
    |     expected due to this
    |
    = note: expected closure signature `for<'a> fn(&'a (), for<'a> fn(&'a ())) -> _`
@@ -133,15 +133,17 @@
    |
 LL | fn g2<F>(_: F) where F: Fn(&(), fn(&())) {}
    |                         ^^^^^^^^^^^^^^^^ required by this bound in `g2`
+help: consider borrowing the argument
+   |
+LL |     g2(|_: &(), _: ()| {});
+   |            +
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:9:5
    |
 LL |     g3(|_: (), _: ()| {});
-   |     ^^ --------------
-   |     |  |   |
-   |     |  |   help: consider borrowing the argument: `&'s ()`
-   |     |  found signature defined here
+   |     ^^ -------------- found signature defined here
+   |     |
    |     expected due to this
    |
    = note: expected closure signature `for<'s> fn(&'s (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
@@ -151,15 +153,17 @@
    |
 LL | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<dyn Fn(&())>) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g3`
+help: consider borrowing the argument
+   |
+LL |     g3(|_: &(), _: ()| {});
+   |            +
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5
    |
 LL |     g4(|_: (), _: ()| {});
-   |     ^^ --------------
-   |     |  |   |
-   |     |  |   help: consider borrowing the argument: `&()`
-   |     |  found signature defined here
+   |     ^^ -------------- found signature defined here
+   |     |
    |     expected due to this
    |
    = note: expected closure signature `for<'a> fn(&'a (), for<'r> fn(&'r ())) -> _`
@@ -169,6 +173,10 @@
    |
 LL | fn g4<F>(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g4`
+help: consider borrowing the argument
+   |
+LL |     g4(|_: &(), _: ()| {});
+   |            +
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:11:5
@@ -188,7 +196,7 @@
 help: consider borrowing the argument
    |
 LL |     h1(|_: &(), _: (), _: &(), _: ()| {});
-   |            ~~~            ~~~
+   |            +              +
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
@@ -207,8 +215,8 @@
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h2`
 help: consider borrowing the argument
    |
-LL |     h2(|_: &(), _: (), _: &'t0 (), _: ()| {});
-   |            ~~~            ~~~~~~~
+LL |     h2(|_: &(), _: (), _: &(), _: ()| {});
+   |            +              +
 
 error: aborting due to 11 previous errors
 
diff --git a/tests/ui/async-await/auxiliary/issue-107036.rs b/tests/ui/async-await/auxiliary/issue-107036.rs
new file mode 100644
index 0000000..c3f6141
--- /dev/null
+++ b/tests/ui/async-await/auxiliary/issue-107036.rs
@@ -0,0 +1,12 @@
+// edition:2021
+
+pub trait T {}
+impl T for () {}
+
+pub struct S {}
+
+impl S {
+    pub async fn f<'a>(&self) -> impl T + 'a {
+        ()
+    }
+}
diff --git a/tests/ui/async-await/await-sequence.rs b/tests/ui/async-await/await-sequence.rs
new file mode 100644
index 0000000..726c428
--- /dev/null
+++ b/tests/ui/async-await/await-sequence.rs
@@ -0,0 +1,21 @@
+// edition:2021
+// compile-flags: -Z drop-tracking
+// build-pass
+
+use std::collections::HashMap;
+
+fn main() {
+    let _ = real_main();
+}
+
+async fn nop() {}
+
+async fn real_main() {
+    nop().await;
+    nop().await;
+    nop().await;
+    nop().await;
+
+    let mut map: HashMap<(), ()> = HashMap::new();
+    map.insert((), nop().await);
+}
diff --git a/tests/ui/async-await/issue-107036.rs b/tests/ui/async-await/issue-107036.rs
new file mode 100644
index 0000000..6a22de2
--- /dev/null
+++ b/tests/ui/async-await/issue-107036.rs
@@ -0,0 +1,14 @@
+// aux-build:issue-107036.rs
+// edition:2021
+// check-pass
+
+extern crate issue_107036;
+use issue_107036::S;
+
+async fn f() {
+    S{}.f().await;
+}
+
+fn main() {
+    let _ = f();
+}
diff --git a/tests/ui/chalkify/bugs/async.rs b/tests/ui/chalkify/bugs/async.rs
index 1c69b07..3169e47 100644
--- a/tests/ui/chalkify/bugs/async.rs
+++ b/tests/ui/chalkify/bugs/async.rs
@@ -1,7 +1,7 @@
-// check-fail
-// known-bug
+// edition:2021
+// known-bug: unknown
 // unset-rustc-env:RUST_BACKTRACE
-// compile-flags:-Z trait-solver=chalk --edition=2021
+// compile-flags:-Z trait-solver=chalk
 // error-pattern:internal compiler error
 // failure-status:101
 // normalize-stderr-test "DefId([^)]*)" -> "..."
diff --git a/tests/ui/closures/multiple-fn-bounds.stderr b/tests/ui/closures/multiple-fn-bounds.stderr
index da26302..32a1edb 100644
--- a/tests/ui/closures/multiple-fn-bounds.stderr
+++ b/tests/ui/closures/multiple-fn-bounds.stderr
@@ -2,10 +2,8 @@
   --> $DIR/multiple-fn-bounds.rs:10:5
    |
 LL |     foo(move |x| v);
-   |     ^^^ --------
-   |     |   |     |
-   |     |   |     help: do not borrow the argument: `char`
-   |     |   found signature defined here
+   |     ^^^ -------- found signature defined here
+   |     |
    |     expected due to this
    |
    = note: expected closure signature `fn(char) -> _`
@@ -20,6 +18,10 @@
    |
 LL | fn foo<F: Fn(&char) -> bool + Fn(char) -> bool>(f: F) {
    |                               ^^^^^^^^^^^^^^^^ required by this bound in `foo`
+help: do not borrow the argument
+   |
+LL |     foo(move |char| v);
+   |               ~~~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/const-generics/issues/issue-85031-2.rs b/tests/ui/const-generics/issues/issue-85031-2.rs
index 4908fb2..50dd66d 100644
--- a/tests/ui/const-generics/issues/issue-85031-2.rs
+++ b/tests/ui/const-generics/issues/issue-85031-2.rs
@@ -1,5 +1,5 @@
 // check-pass
-// known-bug
+// known-bug: unknown
 
 // This should not compile, as the compiler should not know
 // `A - 0` is satisfied `?x - 0` if `?x` is inferred to `A`.
@@ -10,7 +10,6 @@
 
 impl<'a> Ref<'a> {
     pub fn foo<const A: usize>() -> [(); A - 0] {
-        //~^ WARN function cannot
         Self::foo()
     }
 }
diff --git a/tests/ui/const-generics/issues/issue-85031-2.stderr b/tests/ui/const-generics/issues/issue-85031-2.stderr
index fc69057..896e1c7 100644
--- a/tests/ui/const-generics/issues/issue-85031-2.stderr
+++ b/tests/ui/const-generics/issues/issue-85031-2.stderr
@@ -3,7 +3,6 @@
    |
 LL |     pub fn foo<const A: usize>() -> [(); A - 0] {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
-LL |
 LL |         Self::foo()
    |         ----------- recursive call site
    |
diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-1.rs b/tests/ui/generic-associated-types/bugs/hrtb-implied-1.rs
index 719d1bd..5101de1 100644
--- a/tests/ui/generic-associated-types/bugs/hrtb-implied-1.rs
+++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-1.rs
@@ -1,5 +1,5 @@
 // check-fail
-// known-bug
+// known-bug: unknown
 
 // This gives us problems because `for<'a> I::Item<'a>: Debug` should mean "for
 // all 'a where I::Item<'a> is WF", but really means "for all 'a possible"
@@ -29,7 +29,6 @@
 
 fn main() {
     let slice = &mut ();
-    //~^ temporary value dropped while borrowed
     let windows = WindowsMut { slice };
     print_items::<WindowsMut<'_>>(windows);
 }
diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr b/tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr
index 1c9abc4..362aeae 100644
--- a/tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr
+++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr
@@ -3,7 +3,7 @@
    |
 LL |     let slice = &mut ();
    |                      ^^ creates a temporary value which is freed while still in use
-...
+LL |     let windows = WindowsMut { slice };
 LL |     print_items::<WindowsMut<'_>>(windows);
    |     -------------------------------------- argument requires that borrow lasts for `'static`
 LL | }
diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-2.rs b/tests/ui/generic-associated-types/bugs/hrtb-implied-2.rs
index 8e6c534..3174227 100644
--- a/tests/ui/generic-associated-types/bugs/hrtb-implied-2.rs
+++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-2.rs
@@ -1,5 +1,5 @@
 // check-fail
-// known-bug
+// known-bug: unknown
 
 // This gives us problems because `for<'a> I::Item<'a>: Debug` should mean "for
 // all 'a where I::Item<'a> is WF", but really means "for all 'a possible"
@@ -16,7 +16,6 @@
 {
     let mut iter2 = Eat(iter, f);
     let _next = iter2.next();
-    //~^ borrowed data escapes
     true
 }
 impl<I: LendingIterator> LendingIterator for &mut I {
diff --git a/tests/ui/generic-associated-types/bugs/issue-100013.rs b/tests/ui/generic-associated-types/bugs/issue-100013.rs
index fc4e47a..973c548 100644
--- a/tests/ui/generic-associated-types/bugs/issue-100013.rs
+++ b/tests/ui/generic-associated-types/bugs/issue-100013.rs
@@ -1,5 +1,5 @@
 // check-fail
-// known-bug
+// known-bug: unknown
 // edition: 2021
 
 // We really should accept this, but we need implied bounds between the regions
@@ -13,7 +13,6 @@
 
 fn call<I: FutureIterator>() -> impl Send {
     async { // a generator checked for autotrait impl `Send`
-        //~^ lifetime bound not satisfied
         let x = None::<I::Future<'_, '_>>; // a type referencing GAT
         async {}.await; // a yield point
     }
@@ -21,16 +20,13 @@
 
 fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
     async { // a generator checked for autotrait impl `Send`
-        //~^ lifetime bound not satisfied
         let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
-        //~^ lifetime may not live long enough
         async {}.await; // a yield point
     }
 }
 
 fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send {
     async { // a generator checked for autotrait impl `Send`
-        //~^ lifetime bound not satisfied
         let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
         async {}.await; // a yield point
     }
diff --git a/tests/ui/generic-associated-types/bugs/issue-100013.stderr b/tests/ui/generic-associated-types/bugs/issue-100013.stderr
index 72ae288..9db124a 100644
--- a/tests/ui/generic-associated-types/bugs/issue-100013.stderr
+++ b/tests/ui/generic-associated-types/bugs/issue-100013.stderr
@@ -2,77 +2,73 @@
   --> $DIR/issue-100013.rs:15:5
    |
 LL | /     async { // a generator checked for autotrait impl `Send`
-LL | |
 LL | |         let x = None::<I::Future<'_, '_>>; // a type referencing GAT
 LL | |         async {}.await; // a yield point
 LL | |     }
    | |_____^
    |
 note: the lifetime defined here...
-  --> $DIR/issue-100013.rs:17:38
+  --> $DIR/issue-100013.rs:16:38
    |
 LL |         let x = None::<I::Future<'_, '_>>; // a type referencing GAT
    |                                      ^^
 note: ...must outlive the lifetime defined here
-  --> $DIR/issue-100013.rs:17:34
+  --> $DIR/issue-100013.rs:16:34
    |
 LL |         let x = None::<I::Future<'_, '_>>; // a type referencing GAT
    |                                  ^^
    = note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
 
 error: lifetime bound not satisfied
-  --> $DIR/issue-100013.rs:23:5
+  --> $DIR/issue-100013.rs:22:5
    |
 LL | /     async { // a generator checked for autotrait impl `Send`
-LL | |
 LL | |         let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
-LL | |
 LL | |         async {}.await; // a yield point
 LL | |     }
    | |_____^
    |
 note: the lifetime defined here...
-  --> $DIR/issue-100013.rs:22:14
+  --> $DIR/issue-100013.rs:21:14
    |
 LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
    |              ^^
 note: ...must outlive the lifetime defined here
-  --> $DIR/issue-100013.rs:22:10
+  --> $DIR/issue-100013.rs:21:10
    |
 LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
    |          ^^
    = note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
 
 error: lifetime may not live long enough
-  --> $DIR/issue-100013.rs:25:17
+  --> $DIR/issue-100013.rs:23:17
    |
 LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
    |          --  -- lifetime `'b` defined here
    |          |
    |          lifetime `'a` defined here
-...
+LL |     async { // a generator checked for autotrait impl `Send`
 LL |         let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime bound not satisfied
-  --> $DIR/issue-100013.rs:32:5
+  --> $DIR/issue-100013.rs:29:5
    |
 LL | /     async { // a generator checked for autotrait impl `Send`
-LL | |
 LL | |         let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
 LL | |         async {}.await; // a yield point
 LL | |     }
    | |_____^
    |
 note: the lifetime defined here...
-  --> $DIR/issue-100013.rs:31:18
+  --> $DIR/issue-100013.rs:28:18
    |
 LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send {
    |                  ^^
 note: ...must outlive the lifetime defined here
-  --> $DIR/issue-100013.rs:31:10
+  --> $DIR/issue-100013.rs:28:10
    |
 LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send {
    |          ^^
diff --git a/tests/ui/generic-associated-types/bugs/issue-91762.rs b/tests/ui/generic-associated-types/bugs/issue-91762.rs
index dec668b..8f2cc45 100644
--- a/tests/ui/generic-associated-types/bugs/issue-91762.rs
+++ b/tests/ui/generic-associated-types/bugs/issue-91762.rs
@@ -1,5 +1,5 @@
 // check-fail
-// known-bug
+// known-bug: unknown
 
 // We almost certainly want this to pass, but
 // it's particularly difficult currently, because we need a way of specifying
@@ -22,7 +22,6 @@
 
         arg = self;
         ret = <Self::Base as Functor>::fmap(arg);
-        //~^ type annotations needed
     }
 }
 
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.fixed b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.fixed
new file mode 100644
index 0000000..6315fcc
--- /dev/null
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.fixed
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+    let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments
+    let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments
+}
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs
new file mode 100644
index 0000000..c12c536
--- /dev/null
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+    let _ = (-10..=10).find(|x: i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments
+    let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments
+}
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr
new file mode 100644
index 0000000..fb8af4b
--- /dev/null
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr
@@ -0,0 +1,38 @@
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/closure-arg-type-mismatch-issue-45727.rs:3:24
+   |
+LL |     let _ = (-10..=10).find(|x: i32| x.signum() == 0);
+   |                        ^^^^ -------- found signature defined here
+   |                        |
+   |                        expected due to this
+   |
+   = note: expected closure signature `for<'a> fn(&'a {integer}) -> _`
+              found closure signature `fn(i32) -> _`
+note: required by a bound in `find`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+help: consider borrowing the argument
+   |
+LL |     let _ = (-10..=10).find(|x: &i32| x.signum() == 0);
+   |                                 +
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/closure-arg-type-mismatch-issue-45727.rs:4:24
+   |
+LL |     let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
+   |                        ^^^^ ----------- found signature defined here
+   |                        |
+   |                        expected due to this
+   |
+   = note: expected closure signature `for<'a> fn(&'a {integer}) -> _`
+              found closure signature `for<'a, 'b, 'c> fn(&'a &'b &'c i32) -> _`
+note: required by a bound in `find`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+help: do not borrow the argument
+   |
+LL -     let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
+LL +     let _ = (-10..=10).find(|x: &i32| x.signum() == 0);
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0631`.
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr
index fab9b7e..811ff05 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr
@@ -2,16 +2,18 @@
   --> $DIR/closure-arg-type-mismatch.rs:3:14
    |
 LL |     a.iter().map(|_: (u32, u32)| 45);
-   |              ^^^ ---------------
-   |              |   |   |
-   |              |   |   help: consider borrowing the argument: `&(u32, u32)`
-   |              |   found signature defined here
+   |              ^^^ --------------- found signature defined here
+   |              |
    |              expected due to this
    |
    = note: expected closure signature `fn(&(u32, u32)) -> _`
               found closure signature `fn((u32, u32)) -> _`
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+help: consider borrowing the argument
+   |
+LL |     a.iter().map(|_: &(u32, u32)| 45);
+   |                      +
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/closure-arg-type-mismatch.rs:4:14
diff --git a/tests/ui/mismatched_types/issue-36053-2.stderr b/tests/ui/mismatched_types/issue-36053-2.stderr
index 72fb0e4..a6764a1 100644
--- a/tests/ui/mismatched_types/issue-36053-2.stderr
+++ b/tests/ui/mismatched_types/issue-36053-2.stderr
@@ -2,16 +2,18 @@
   --> $DIR/issue-36053-2.rs:7:32
    |
 LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
-   |                                ^^^^^^ ---------
-   |                                |      |   |
-   |                                |      |   help: consider borrowing the argument: `&&str`
-   |                                |      found signature defined here
+   |                                ^^^^^^ --------- found signature defined here
+   |                                |
    |                                expected due to this
    |
    = note: expected closure signature `for<'a> fn(&'a &str) -> _`
               found closure signature `for<'a> fn(&'a str) -> _`
 note: required by a bound in `filter`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+help: consider borrowing the argument
+   |
+LL |     once::<&str>("str").fuse().filter(|a: &&str| true).count();
+   |                                           +
 
 error[E0599]: the method `count` exists for struct `Filter<Fuse<Once<&str>>, [closure@issue-36053-2.rs:7:39]>`, but its trait bounds were not satisfied
   --> $DIR/issue-36053-2.rs:7:55
diff --git a/tests/ui/type-alias-impl-trait/outlives-bound-var.rs b/tests/ui/type-alias-impl-trait/outlives-bound-var.rs
new file mode 100644
index 0000000..b8fac45
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/outlives-bound-var.rs
@@ -0,0 +1,18 @@
+// Here we process outlive obligations involving
+// opaque types with bound vars in substs.
+// This was an ICE.
+//
+// check-pass
+#![feature(type_alias_impl_trait)]
+
+type Ty<'a> = impl Sized + 'a;
+fn define<'a>() -> Ty<'a> {}
+
+// Ty<'^0>: 'static
+fn test1(_: &'static fn(Ty<'_>)) {}
+
+fn test2() {
+    None::<&fn(Ty<'_>)>;
+}
+
+fn main() { }