about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs4
-rw-r--r--compiler/rustc_data_structures/src/graph/dominators/mod.rs2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0208.md45
-rw-r--r--compiler/rustc_hir/src/hir.rs8
-rw-r--r--compiler/rustc_hir/src/lang_items.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/utils.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/variance/test.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs38
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs11
-rw-r--r--compiler/rustc_infer/src/infer/outlives/components.rs23
-rw-r--r--compiler/rustc_infer/src/infer/outlives/env.rs4
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs81
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs62
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/mod.rs14
-rw-r--r--compiler/rustc_infer/src/traits/util.rs9
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs9
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs5
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs6
-rw-r--r--compiler/rustc_middle/src/traits/query.rs2
-rw-r--r--compiler/rustc_middle/src/ty/assoc.rs5
-rw-r--r--compiler/rustc_middle/src/ty/context.rs9
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs1
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs19
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs10
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs118
-rw-r--r--compiler/rustc_parse/src/lexer/unicode_chars.rs642
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs61
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs42
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs2
-rw-r--r--compiler/rustc_traits/src/implied_outlives_bounds.rs6
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs34
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/vec/is_zero.rs20
-rw-r--r--library/core/src/future/mod.rs4
-rw-r--r--library/core/src/task/wake.rs1
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs2
-rw-r--r--src/librustdoc/html/render/write_shared.rs2
-rw-r--r--src/librustdoc/visit_ast.rs163
m---------src/tools/cargo0
-rw-r--r--src/tools/compiletest/src/main.rs2
-rw-r--r--src/tools/tidy/src/error_codes.rs3
-rw-r--r--tests/codegen/vec-calloc.rs17
-rw-r--r--tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir41
-rw-r--r--tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir337
-rw-r--r--tests/mir-opt/building/async_await.rs17
-rw-r--r--tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs4
-rw-r--r--tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr16
-rw-r--r--tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs5
-rw-r--r--tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr16
-rw-r--r--tests/rustdoc/impl-in-const-block.rs43
-rw-r--r--tests/ui/async-await/auxiliary/issue-107036.rs12
-rw-r--r--tests/ui/async-await/issue-107036.rs14
-rw-r--r--tests/ui/coherence/coherence-with-generator.rs8
-rw-r--r--tests/ui/coherence/coherence-with-generator.stock.stderr (renamed from tests/ui/coherence/coherence-with-generator.stderr)2
-rw-r--r--tests/ui/error-codes/E0208.rs8
-rw-r--r--tests/ui/error-codes/E0208.stderr8
-rw-r--r--tests/ui/error-codes/E0606.rs3
-rw-r--r--tests/ui/error-codes/E0606.stderr28
-rw-r--r--tests/ui/error-festival.stderr10
-rw-r--r--tests/ui/mismatched_types/cast-rfc0401.stderr10
-rw-r--r--tests/ui/parser/recover-unticked-labels.fixed7
-rw-r--r--tests/ui/parser/recover-unticked-labels.rs7
-rw-r--r--tests/ui/parser/recover-unticked-labels.stderr25
-rw-r--r--tests/ui/parser/unicode-chars.rs3
-rw-r--r--tests/ui/parser/unicode-chars.stderr13
-rw-r--r--tests/ui/type-alias-impl-trait/issue-104817.rs19
-rw-r--r--tests/ui/type-alias-impl-trait/issue-104817.stock.stderr11
-rw-r--r--tests/ui/type-alias-impl-trait/outlives-bound-var.rs18
-rw-r--r--tests/ui/variance/variance-associated-consts.stderr3
-rw-r--r--tests/ui/variance/variance-associated-types.stderr5
-rw-r--r--tests/ui/variance/variance-object-types.stderr3
-rw-r--r--tests/ui/variance/variance-regions-direct.stderr15
-rw-r--r--tests/ui/variance/variance-regions-indirect.stderr11
-rw-r--r--tests/ui/variance/variance-trait-bounds.stderr9
-rw-r--r--tests/ui/variance/variance-trait-object-bound.stderr3
-rw-r--r--tests/ui/variance/variance-types-bounds.stderr11
-rw-r--r--tests/ui/variance/variance-types.stderr13
81 files changed, 1473 insertions, 800 deletions
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 9cf4d8cdf7d..82ff862479e 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 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
                         .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_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
index 07b1ace2189..fb2a22e94a5 100644
--- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
@@ -299,7 +299,7 @@ impl<Node: Idx> Dominators<Node> {
     /// of two unrelated nodes will also be consistent, but otherwise the order has no
     /// meaning.) This method cannot be used to determine if either Node dominates the other.
     pub fn rank_partial_cmp(&self, lhs: Node, rhs: Node) -> Option<Ordering> {
-        self.post_order_rank[lhs].partial_cmp(&self.post_order_rank[rhs])
+        self.post_order_rank[rhs].partial_cmp(&self.post_order_rank[lhs])
     }
 }
 
diff --git a/compiler/rustc_error_codes/src/error_codes/E0208.md b/compiler/rustc_error_codes/src/error_codes/E0208.md
index 7edd93e56a9..1ae01106f20 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0208.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0208.md
@@ -1 +1,46 @@
 #### This error code is internal to the compiler and will not be emitted with normal Rust code.
+#### Note: this error code is no longer emitted by the compiler.
+
+This error code shows the variance of a type's generic parameters.
+
+Erroneous code example:
+
+```compile_fail
+// NOTE: this feature is perma-unstable and should *only* be used for
+//       testing purposes.
+#![feature(rustc_attrs)]
+
+#[rustc_variance]
+struct Foo<'a, T> { // error: deliberate error to display type's variance
+    t: &'a mut T,
+}
+```
+
+which produces the following error:
+
+```text
+error: [-, o]
+ --> <anon>:4:1
+  |
+4 | struct Foo<'a, T> {
+  | ^^^^^^^^^^^^^^^^^
+```
+
+*Note that while `#[rustc_variance]` still exists and is used within the*
+*compiler, it no longer is marked as `E0208` and instead has no error code.*
+
+This error is deliberately triggered with the `#[rustc_variance]` attribute
+(`#![feature(rustc_attrs)]` must be enabled) and helps to show you the variance
+of the type's generic parameters. You can read more about variance and
+subtyping in [this section of the Rustnomicon]. For a more in depth look at
+variance (including a more complete list of common variances) see
+[this section of the Reference]. For information on how variance is implemented
+in the compiler, see [this section of `rustc-dev-guide`].
+
+This error can be easily fixed by removing the `#[rustc_variance]` attribute,
+the compiler's suggestion to comment it out can be applied automatically with
+`rustfix`.
+
+[this section of the Rustnomicon]: https://doc.rust-lang.org/nomicon/subtyping.html
+[this section of the Reference]: https://doc.rust-lang.org/reference/subtyping.html#variance
+[this section of `rustc-dev-guide`]: https://rustc-dev-guide.rust-lang.org/variance.html
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 56f0e0b3e7d..d6566860f81 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1787,6 +1787,14 @@ impl Expr<'_> {
         expr
     }
 
+    pub fn peel_borrows(&self) -> &Self {
+        let mut expr = self;
+        while let ExprKind::AddrOf(.., inner) = &expr.kind {
+            expr = inner;
+        }
+        expr
+    }
+
     pub fn can_have_side_effects(&self) -> bool {
         match self.peel_drop_temps().kind {
             ExprKind::Path(_) | ExprKind::Lit(_) => false,
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 3474fab34f0..54fa5702fbc 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -291,6 +291,7 @@ language_item_table! {
     IdentityFuture,          sym::identity_future,     identity_future_fn,         Target::Fn,             GenericRequirement::None;
     GetContext,              sym::get_context,         get_context_fn,             Target::Fn,             GenericRequirement::None;
 
+    Context,                 sym::Context,             context,                    Target::Struct,         GenericRequirement::None;
     FuturePoll,              sym::poll,                future_poll_fn,             Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
 
     FromFrom,                sym::from,                from_fn,                    Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 9031c04849d..ce72b78f42f 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -2602,7 +2602,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         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 35f47dfc1a5..9be37dbe8c6 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -76,6 +76,7 @@ pub fn provide(providers: &mut Providers) {
         is_foreign_item,
         generator_kind,
         collect_mod_item_types,
+        is_type_alias_impl_trait,
         ..*providers
     };
 }
@@ -1537,3 +1538,13 @@ fn generator_kind(tcx: TyCtxt<'_>, def_id: DefId) -> Option<hir::GeneratorKind>
         _ => 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 3f691beec31..9459c5f54ab 100644
--- a/compiler/rustc_hir_analysis/src/outlives/utils.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs
@@ -80,7 +80,7 @@ pub(crate) fn insert_outlives_predicate<'tcx>(
                             .or_insert(span);
                     }
 
-                    Component::Alias(kind, alias) => {
+                    Component::Alias(alias_ty) => {
                         // This would either arise from something like:
                         //
                         // ```
@@ -99,13 +99,13 @@ pub(crate) fn insert_outlives_predicate<'tcx>(
                         //
                         // 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_analysis/src/variance/test.rs b/compiler/rustc_hir_analysis/src/variance/test.rs
index 83ed3e44b3d..5feeb92d337 100644
--- a/compiler/rustc_hir_analysis/src/variance/test.rs
+++ b/compiler/rustc_hir_analysis/src/variance/test.rs
@@ -1,4 +1,3 @@
-use rustc_errors::struct_span_err;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::sym;
 
@@ -8,8 +7,8 @@ pub fn test_variance(tcx: TyCtxt<'_>) {
     for id in tcx.hir().items() {
         if tcx.has_attr(id.owner_id.to_def_id(), sym::rustc_variance) {
             let variances_of = tcx.variances_of(id.owner_id);
-            struct_span_err!(tcx.sess, tcx.def_span(id.owner_id), E0208, "{:?}", variances_of)
-                .emit();
+
+            tcx.sess.struct_span_err(tcx.def_span(id.owner_id), format!("{variances_of:?}")).emit();
         }
     }
 }
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 0a230fca107..712f9b87aed 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -31,6 +31,7 @@
 use super::FnCtxt;
 
 use crate::type_error_struct;
+use hir::ExprKind;
 use rustc_errors::{
     struct_span_err, Applicability, DelayDm, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
 };
@@ -151,7 +152,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
 #[derive(Copy, Clone)]
 pub enum CastError {
-    ErrorGuaranteed,
+    ErrorGuaranteed(ErrorGuaranteed),
 
     CastToBool,
     CastToChar,
@@ -176,8 +177,8 @@ pub enum CastError {
 }
 
 impl From<ErrorGuaranteed> for CastError {
-    fn from(_: ErrorGuaranteed) -> Self {
-        CastError::ErrorGuaranteed
+    fn from(err: ErrorGuaranteed) -> Self {
+        CastError::ErrorGuaranteed(err)
     }
 }
 
@@ -225,11 +226,10 @@ impl<'a, 'tcx> CastCheck<'tcx> {
 
     fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
         match e {
-            CastError::ErrorGuaranteed => {
+            CastError::ErrorGuaranteed(_) => {
                 // an error has already been reported
             }
             CastError::NeedDeref => {
-                let error_span = self.span;
                 let mut err = make_invalid_casting_error(
                     fcx.tcx.sess,
                     self.span,
@@ -237,21 +237,25 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                     self.cast_ty,
                     fcx,
                 );
-                let cast_ty = fcx.ty_to_string(self.cast_ty);
-                err.span_label(
-                    error_span,
-                    format!("cannot cast `{}` as `{}`", fcx.ty_to_string(self.expr_ty), cast_ty),
-                );
-                if let Ok(snippet) = fcx.sess().source_map().span_to_snippet(self.expr_span) {
-                    err.span_suggestion(
-                        self.expr_span,
-                        "dereference the expression",
-                        format!("*{}", snippet),
-                        Applicability::MaybeIncorrect,
+
+                if matches!(self.expr.kind, ExprKind::AddrOf(..)) {
+                    // get just the borrow part of the expression
+                    let span = self.expr_span.with_hi(self.expr.peel_borrows().span.lo());
+                    err.span_suggestion_verbose(
+                        span,
+                        "remove the unneeded borrow",
+                        "",
+                        Applicability::MachineApplicable,
                     );
                 } else {
-                    err.span_help(self.expr_span, "dereference the expression with `*`");
+                    err.span_suggestion_verbose(
+                        self.expr_span.shrink_to_lo(),
+                        "dereference the expression",
+                        "*",
+                        Applicability::MachineApplicable,
+                    );
                 }
+
                 err.emit();
             }
             CastError::NeedViaThinPtr | CastError::NeedViaPtr => {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 9c38eb6163f..28fd03b878b 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 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
         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 37907d289a8..3d86279b03c 100644
--- a/compiler/rustc_infer/src/infer/outlives/components.rs
+++ b/compiler/rustc_infer/src/infer/outlives/components.rs
@@ -22,7 +22,7 @@ pub enum Component<'tcx> {
     // 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 @@ pub enum Component<'tcx> {
     // 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 @@ fn compute_components<'tcx>(
                 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 @@ fn compute_components<'tcx>(
             // 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 @@ fn compute_components<'tcx>(
                     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 52c3d97f241..24e3c34dd94 100644
--- a/compiler/rustc_infer/src/infer/outlives/env.rs
+++ b/compiler/rustc_infer/src/infer/outlives/env.rs
@@ -138,9 +138,9 @@ impl<'tcx> OutlivesEnvironmentBuilder<'tcx> {
                     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 77de335e7f5..0194549a886 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::infer::{
 };
 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 @@ where
                 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 @@ where
         }
     }
 
+    #[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(
+    fn alias_ty_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(
-        &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 @@ where
         // 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 @@ where
             // 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 @@ where
         // 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 @@ where
         // 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 56695a87b7c..94de9bc2d02 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 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
     /// 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 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
                     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 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
         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 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
         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 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
     ///
     /// 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 fda5ffe7846..0428481b7ff 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 @@ pub struct Verify<'tcx> {
 #[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 @@ impl<'tcx> fmt::Debug for GenericKind<'tcx> {
     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 @@ impl<'tcx> fmt::Display for GenericKind<'tcx> {
     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 @@ impl<'tcx> GenericKind<'tcx> {
     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 4ada7b22d08..cd5bde2a791 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -261,14 +261,15 @@ impl<'tcx> Elaborator<'tcx> {
 
                             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 cb451931dfe..0d924f27c21 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 @@ provide! { tcx, def_id, other, cdata,
     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 a3d44fa890d..ab2ad79b876 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1512,8 +1512,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             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 5b7b096b4ed..5066dbbb90f 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -404,6 +404,8 @@ define_tables! {
     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 0ec6f481af1..6bbf7fa3914 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -177,6 +177,12 @@ rustc_queries! {
         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 2a68315fefc..615154a55e5 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -213,5 +213,5 @@ pub struct NormalizationResult<'tcx> {
 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/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index 859a58c8998..bb7fba3ee71 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -37,6 +37,11 @@ impl AssocItem {
         Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
     }
 
+    /// Gets the defaultness of the associated item.
+    /// To get the default associated type, use the [`type_of`] query on the
+    /// [`DefId`] of the type.
+    ///
+    /// [`type_of`]: crate::ty::TyCtxt::type_of
     pub fn defaultness(&self, tcx: TyCtxt<'_>) -> hir::Defaultness {
         tcx.impl_defaultness(self.def_id)
     }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 0c66443555f..ce04d8d21f4 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1952,6 +1952,15 @@ impl<'tcx> TyCtxt<'tcx> {
         self.mk_ty(GeneratorWitness(types))
     }
 
+    /// Creates a `&mut Context<'_>` [`Ty`] with erased lifetimes.
+    pub fn mk_task_context(self) -> Ty<'tcx> {
+        let context_did = self.require_lang_item(LangItem::Context, None);
+        let context_adt_ref = self.adt_def(context_did);
+        let context_substs = self.intern_substs(&[self.lifetimes.re_erased.into()]);
+        let context_ty = self.mk_adt(context_adt_ref, context_substs);
+        self.mk_mut_ref(self.lifetimes.re_erased, context_ty)
+    }
+
     #[inline]
     pub fn mk_ty_var(self, v: TyVid) -> Ty<'tcx> {
         self.mk_ty_infer(TyVar(v))
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index e32a7ee1c35..24f3d1acff1 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -52,6 +52,7 @@ trivially_parameterized_over_tcx! {
     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 a128e9025fd..6a7b23e40a7 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1245,19 +1245,34 @@ pub struct AliasTy<'tcx> {
     /// 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_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index 9f842c929dc..c5434840453 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -341,11 +341,11 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
                     if a.is_in_same_bcb(b) {
                         Some(Ordering::Equal)
                     } else {
-                        // Sort equal spans by dominator relationship, in reverse order (so
-                        // dominators always come after the dominated equal spans). When later
-                        // comparing two spans in order, the first will either dominate the second,
-                        // or they will have no dominator relationship.
-                        self.basic_coverage_blocks.dominators().rank_partial_cmp(b.bcb, a.bcb)
+                        // Sort equal spans by dominator relationship (so dominators always come
+                        // before the dominated equal spans). When later comparing two spans in
+                        // order, the first will either dominate the second, or they will have no
+                        // dominator relationship.
+                        self.basic_coverage_blocks.dominators().rank_partial_cmp(a.bcb, b.bcb)
                     }
                 } else {
                     // Sort hi() in reverse order so shorter spans are attempted after longer spans.
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index c097af61611..39c61a34afc 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -460,6 +460,104 @@ fn replace_local<'tcx>(
     new_local
 }
 
+/// Transforms the `body` of the generator applying the following transforms:
+///
+/// - Eliminates all the `get_context` calls that async lowering created.
+/// - Replace all `Local` `ResumeTy` types with `&mut Context<'_>` (`context_mut_ref`).
+///
+/// The `Local`s that have their types replaced are:
+/// - The `resume` argument itself.
+/// - The argument to `get_context`.
+/// - The yielded value of a `yield`.
+///
+/// The `ResumeTy` hides a `&mut Context<'_>` behind an unsafe raw pointer, and the
+/// `get_context` function is being used to convert that back to a `&mut Context<'_>`.
+///
+/// Ideally the async lowering would not use the `ResumeTy`/`get_context` indirection,
+/// but rather directly use `&mut Context<'_>`, however that would currently
+/// lead to higher-kinded lifetime errors.
+/// See <https://github.com/rust-lang/rust/issues/105501>.
+///
+/// The async lowering step and the type / lifetime inference / checking are
+/// still using the `ResumeTy` indirection for the time being, and that indirection
+/// is removed here. After this transform, the generator body only knows about `&mut Context<'_>`.
+fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+    let context_mut_ref = tcx.mk_task_context();
+
+    // replace the type of the `resume` argument
+    replace_resume_ty_local(tcx, body, Local::new(2), context_mut_ref);
+
+    let get_context_def_id = tcx.require_lang_item(LangItem::GetContext, None);
+
+    for bb in BasicBlock::new(0)..body.basic_blocks.next_index() {
+        let bb_data = &body[bb];
+        if bb_data.is_cleanup {
+            continue;
+        }
+
+        match &bb_data.terminator().kind {
+            TerminatorKind::Call { func, .. } => {
+                let func_ty = func.ty(body, tcx);
+                if let ty::FnDef(def_id, _) = *func_ty.kind() {
+                    if def_id == get_context_def_id {
+                        let local = eliminate_get_context_call(&mut body[bb]);
+                        replace_resume_ty_local(tcx, body, local, context_mut_ref);
+                    }
+                } else {
+                    continue;
+                }
+            }
+            TerminatorKind::Yield { resume_arg, .. } => {
+                replace_resume_ty_local(tcx, body, resume_arg.local, context_mut_ref);
+            }
+            _ => {}
+        }
+    }
+}
+
+fn eliminate_get_context_call<'tcx>(bb_data: &mut BasicBlockData<'tcx>) -> Local {
+    let terminator = bb_data.terminator.take().unwrap();
+    if let TerminatorKind::Call { mut args, destination, target, .. } = terminator.kind {
+        let arg = args.pop().unwrap();
+        let local = arg.place().unwrap().local;
+
+        let arg = Rvalue::Use(arg);
+        let assign = Statement {
+            source_info: terminator.source_info,
+            kind: StatementKind::Assign(Box::new((destination, arg))),
+        };
+        bb_data.statements.push(assign);
+        bb_data.terminator = Some(Terminator {
+            source_info: terminator.source_info,
+            kind: TerminatorKind::Goto { target: target.unwrap() },
+        });
+        local
+    } else {
+        bug!();
+    }
+}
+
+#[cfg_attr(not(debug_assertions), allow(unused))]
+fn replace_resume_ty_local<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    body: &mut Body<'tcx>,
+    local: Local,
+    context_mut_ref: Ty<'tcx>,
+) {
+    let local_ty = std::mem::replace(&mut body.local_decls[local].ty, context_mut_ref);
+    // We have to replace the `ResumeTy` that is used for type and borrow checking
+    // with `&mut Context<'_>` in MIR.
+    #[cfg(debug_assertions)]
+    {
+        if let ty::Adt(resume_ty_adt, _) = local_ty.kind() {
+            let expected_adt = tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, None));
+            assert_eq!(*resume_ty_adt, expected_adt);
+        } else {
+            panic!("expected `ResumeTy`, found `{:?}`", local_ty);
+        };
+    }
+}
+
 struct LivenessInfo {
     /// Which locals are live across any suspension point.
     saved_locals: GeneratorSavedLocals,
@@ -1283,13 +1381,13 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
             }
         };
 
-        let is_async_kind = body.generator_kind().unwrap() != GeneratorKind::Gen;
+        let is_async_kind = matches!(body.generator_kind(), Some(GeneratorKind::Async(_)));
         let (state_adt_ref, state_substs) = if is_async_kind {
             // Compute Poll<return_ty>
-            let state_did = tcx.require_lang_item(LangItem::Poll, None);
-            let state_adt_ref = tcx.adt_def(state_did);
-            let state_substs = tcx.intern_substs(&[body.return_ty().into()]);
-            (state_adt_ref, state_substs)
+            let poll_did = tcx.require_lang_item(LangItem::Poll, None);
+            let poll_adt_ref = tcx.adt_def(poll_did);
+            let poll_substs = tcx.intern_substs(&[body.return_ty().into()]);
+            (poll_adt_ref, poll_substs)
         } else {
             // Compute GeneratorState<yield_ty, return_ty>
             let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
@@ -1303,13 +1401,19 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
         // RETURN_PLACE then is a fresh unused local with type ret_ty.
         let new_ret_local = replace_local(RETURN_PLACE, ret_ty, body, tcx);
 
+        // Replace all occurrences of `ResumeTy` with `&mut Context<'_>` within async bodies.
+        if is_async_kind {
+            transform_async_context(tcx, body);
+        }
+
         // We also replace the resume argument and insert an `Assign`.
         // This is needed because the resume argument `_2` might be live across a `yield`, in which
         // case there is no `Assign` to it that the transform can turn into a store to the generator
         // state. After the yield the slot in the generator state would then be uninitialized.
         let resume_local = Local::new(2);
-        let new_resume_local =
-            replace_local(resume_local, body.local_decls[resume_local].ty, body, tcx);
+        let resume_ty =
+            if is_async_kind { tcx.mk_task_context() } else { body.local_decls[resume_local].ty };
+        let new_resume_local = replace_local(resume_local, resume_ty, body, tcx);
 
         // When first entering the generator, move the resume argument into its new local.
         let source_info = SourceInfo::outermost(body.span);
diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs
index 65479b341d7..34d003ccfa7 100644
--- a/compiler/rustc_parse/src/lexer/unicode_chars.rs
+++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs
@@ -7,329 +7,331 @@ use rustc_errors::{Applicability, Diagnostic};
 use rustc_span::{symbol::kw, BytePos, Pos, Span};
 
 #[rustfmt::skip] // for line breaks
-pub(crate) const UNICODE_ARRAY: &[(char, &str, char)] = &[
-    ('
', "Line Separator", ' '),
-    ('
', "Paragraph Separator", ' '),
-    (' ', "Ogham Space mark", ' '),
-    (' ', "En Quad", ' '),
-    (' ', "Em Quad", ' '),
-    (' ', "En Space", ' '),
-    (' ', "Em Space", ' '),
-    (' ', "Three-Per-Em Space", ' '),
-    (' ', "Four-Per-Em Space", ' '),
-    (' ', "Six-Per-Em Space", ' '),
-    (' ', "Punctuation Space", ' '),
-    (' ', "Thin Space", ' '),
-    (' ', "Hair Space", ' '),
-    (' ', "Medium Mathematical Space", ' '),
-    (' ', "No-Break Space", ' '),
-    (' ', "Figure Space", ' '),
-    (' ', "Narrow No-Break Space", ' '),
-    (' ', "Ideographic Space", ' '),
-
-    ('ߺ', "Nko Lajanyalan", '_'),
-    ('﹍', "Dashed Low Line", '_'),
-    ('﹎', "Centreline Low Line", '_'),
-    ('﹏', "Wavy Low Line", '_'),
-    ('_', "Fullwidth Low Line", '_'),
-
-    ('‐', "Hyphen", '-'),
-    ('‑', "Non-Breaking Hyphen", '-'),
-    ('‒', "Figure Dash", '-'),
-    ('–', "En Dash", '-'),
-    ('—', "Em Dash", '-'),
-    ('﹘', "Small Em Dash", '-'),
-    ('۔', "Arabic Full Stop", '-'),
-    ('⁃', "Hyphen Bullet", '-'),
-    ('˗', "Modifier Letter Minus Sign", '-'),
-    ('−', "Minus Sign", '-'),
-    ('➖', "Heavy Minus Sign", '-'),
-    ('Ⲻ', "Coptic Letter Dialect-P Ni", '-'),
-    ('ー', "Katakana-Hiragana Prolonged Sound Mark", '-'),
-    ('-', "Fullwidth Hyphen-Minus", '-'),
-    ('―', "Horizontal Bar", '-'),
-    ('─', "Box Drawings Light Horizontal", '-'),
-    ('━', "Box Drawings Heavy Horizontal", '-'),
-    ('㇐', "CJK Stroke H", '-'),
-    ('ꟷ', "Latin Epigraphic Letter Sideways I", '-'),
-    ('ᅳ', "Hangul Jungseong Eu", '-'),
-    ('ㅡ', "Hangul Letter Eu", '-'),
-    ('一', "CJK Unified Ideograph-4E00", '-'),
-    ('⼀', "Kangxi Radical One", '-'),
-
-    ('؍', "Arabic Date Separator", ','),
-    ('٫', "Arabic Decimal Separator", ','),
-    ('‚', "Single Low-9 Quotation Mark", ','),
-    ('¸', "Cedilla", ','),
-    ('ꓹ', "Lisu Letter Tone Na Po", ','),
-    (',', "Fullwidth Comma", ','),
-
-    (';', "Greek Question Mark", ';'),
-    (';', "Fullwidth Semicolon", ';'),
-    ('︔', "Presentation Form For Vertical Semicolon", ';'),
-
-    ('ः', "Devanagari Sign Visarga", ':'),
-    ('ઃ', "Gujarati Sign Visarga", ':'),
-    (':', "Fullwidth Colon", ':'),
-    ('։', "Armenian Full Stop", ':'),
-    ('܃', "Syriac Supralinear Colon", ':'),
-    ('܄', "Syriac Sublinear Colon", ':'),
-    ('᛬', "Runic Multiple Punctuation", ':'),
-    ('︰', "Presentation Form For Vertical Two Dot Leader", ':'),
-    ('᠃', "Mongolian Full Stop", ':'),
-    ('᠉', "Mongolian Manchu Full Stop", ':'),
-    ('⁚', "Two Dot Punctuation", ':'),
-    ('׃', "Hebrew Punctuation Sof Pasuq", ':'),
-    ('˸', "Modifier Letter Raised Colon", ':'),
-    ('꞉', "Modifier Letter Colon", ':'),
-    ('∶', "Ratio", ':'),
-    ('ː', "Modifier Letter Triangular Colon", ':'),
-    ('ꓽ', "Lisu Letter Tone Mya Jeu", ':'),
-    ('︓', "Presentation Form For Vertical Colon", ':'),
-
-    ('!', "Fullwidth Exclamation Mark", '!'),
-    ('ǃ', "Latin Letter Retroflex Click", '!'),
-    ('ⵑ', "Tifinagh Letter Tuareg Yang", '!'),
-    ('︕', "Presentation Form For Vertical Exclamation Mark", '!'),
-
-    ('ʔ', "Latin Letter Glottal Stop", '?'),
-    ('Ɂ', "Latin Capital Letter Glottal Stop", '?'),
-    ('ॽ', "Devanagari Letter Glottal Stop", '?'),
-    ('Ꭾ', "Cherokee Letter He", '?'),
-    ('ꛫ', "Bamum Letter Ntuu", '?'),
-    ('?', "Fullwidth Question Mark", '?'),
-    ('︖', "Presentation Form For Vertical Question Mark", '?'),
-
-    ('𝅭', "Musical Symbol Combining Augmentation Dot", '.'),
-    ('․', "One Dot Leader", '.'),
-    ('܁', "Syriac Supralinear Full Stop", '.'),
-    ('܂', "Syriac Sublinear Full Stop", '.'),
-    ('꘎', "Vai Full Stop", '.'),
-    ('𐩐', "Kharoshthi Punctuation Dot", '.'),
-    ('٠', "Arabic-Indic Digit Zero", '.'),
-    ('۰', "Extended Arabic-Indic Digit Zero", '.'),
-    ('ꓸ', "Lisu Letter Tone Mya Ti", '.'),
-    ('·', "Middle Dot", '.'),
-    ('・', "Katakana Middle Dot", '.'),
-    ('・', "Halfwidth Katakana Middle Dot", '.'),
-    ('᛫', "Runic Single Punctuation", '.'),
-    ('·', "Greek Ano Teleia", '.'),
-    ('⸱', "Word Separator Middle Dot", '.'),
-    ('𐄁', "Aegean Word Separator Dot", '.'),
-    ('•', "Bullet", '.'),
-    ('‧', "Hyphenation Point", '.'),
-    ('∙', "Bullet Operator", '.'),
-    ('⋅', "Dot Operator", '.'),
-    ('ꞏ', "Latin Letter Sinological Dot", '.'),
-    ('ᐧ', "Canadian Syllabics Final Middle Dot", '.'),
-    ('ᐧ', "Canadian Syllabics Final Middle Dot", '.'),
-    ('.', "Fullwidth Full Stop", '.'),
-    ('。', "Ideographic Full Stop", '.'),
-    ('︒', "Presentation Form For Vertical Ideographic Full Stop", '.'),
-
-    ('՝', "Armenian Comma", '\''),
-    (''', "Fullwidth Apostrophe", '\''),
-    ('‘', "Left Single Quotation Mark", '\''),
-    ('’', "Right Single Quotation Mark", '\''),
-    ('‛', "Single High-Reversed-9 Quotation Mark", '\''),
-    ('′', "Prime", '\''),
-    ('‵', "Reversed Prime", '\''),
-    ('՚', "Armenian Apostrophe", '\''),
-    ('׳', "Hebrew Punctuation Geresh", '\''),
-    ('`', "Grave Accent", '\''),
-    ('`', "Greek Varia", '\''),
-    ('`', "Fullwidth Grave Accent", '\''),
-    ('´', "Acute Accent", '\''),
-    ('΄', "Greek Tonos", '\''),
-    ('´', "Greek Oxia", '\''),
-    ('᾽', "Greek Koronis", '\''),
-    ('᾿', "Greek Psili", '\''),
-    ('῾', "Greek Dasia", '\''),
-    ('ʹ', "Modifier Letter Prime", '\''),
-    ('ʹ', "Greek Numeral Sign", '\''),
-    ('ˈ', "Modifier Letter Vertical Line", '\''),
-    ('ˊ', "Modifier Letter Acute Accent", '\''),
-    ('ˋ', "Modifier Letter Grave Accent", '\''),
-    ('˴', "Modifier Letter Middle Grave Accent", '\''),
-    ('ʻ', "Modifier Letter Turned Comma", '\''),
-    ('ʽ', "Modifier Letter Reversed Comma", '\''),
-    ('ʼ', "Modifier Letter Apostrophe", '\''),
-    ('ʾ', "Modifier Letter Right Half Ring", '\''),
-    ('ꞌ', "Latin Small Letter Saltillo", '\''),
-    ('י', "Hebrew Letter Yod", '\''),
-    ('ߴ', "Nko High Tone Apostrophe", '\''),
-    ('ߵ', "Nko Low Tone Apostrophe", '\''),
-    ('ᑊ', "Canadian Syllabics West-Cree P", '\''),
-    ('ᛌ', "Runic Letter Short-Twig-Sol S", '\''),
-    ('𖽑', "Miao Sign Aspiration", '\''),
-    ('𖽒', "Miao Sign Reformed Voicing", '\''),
-
-    ('᳓', "Vedic Sign Nihshvasa", '"'),
-    ('"', "Fullwidth Quotation Mark", '"'),
-    ('“', "Left Double Quotation Mark", '"'),
-    ('”', "Right Double Quotation Mark", '"'),
-    ('‟', "Double High-Reversed-9 Quotation Mark", '"'),
-    ('″', "Double Prime", '"'),
-    ('‶', "Reversed Double Prime", '"'),
-    ('〃', "Ditto Mark", '"'),
-    ('״', "Hebrew Punctuation Gershayim", '"'),
-    ('˝', "Double Acute Accent", '"'),
-    ('ʺ', "Modifier Letter Double Prime", '"'),
-    ('˶', "Modifier Letter Middle Double Acute Accent", '"'),
-    ('˵', "Modifier Letter Middle Double Grave Accent", '"'),
-    ('ˮ', "Modifier Letter Double Apostrophe", '"'),
-    ('ײ', "Hebrew Ligature Yiddish Double Yod", '"'),
-    ('❞', "Heavy Double Comma Quotation Mark Ornament", '"'),
-    ('❝', "Heavy Double Turned Comma Quotation Mark Ornament", '"'),
-
-    ('(', "Fullwidth Left Parenthesis", '('),
-    ('❨', "Medium Left Parenthesis Ornament", '('),
-    ('﴾', "Ornate Left Parenthesis", '('),
-
-    (')', "Fullwidth Right Parenthesis", ')'),
-    ('❩', "Medium Right Parenthesis Ornament", ')'),
-    ('﴿', "Ornate Right Parenthesis", ')'),
-
-    ('[', "Fullwidth Left Square Bracket", '['),
-    ('❲', "Light Left Tortoise Shell Bracket Ornament", '['),
-    ('「', "Left Corner Bracket", '['),
-    ('『', "Left White Corner Bracket", '['),
-    ('【', "Left Black Lenticular Bracket", '['),
-    ('〔', "Left Tortoise Shell Bracket", '['),
-    ('〖', "Left White Lenticular Bracket", '['),
-    ('〘', "Left White Tortoise Shell Bracket", '['),
-    ('〚', "Left White Square Bracket", '['),
-
-    (']', "Fullwidth Right Square Bracket", ']'),
-    ('❳', "Light Right Tortoise Shell Bracket Ornament", ']'),
-    ('」', "Right Corner Bracket", ']'),
-    ('』', "Right White Corner Bracket", ']'),
-    ('】', "Right Black Lenticular Bracket", ']'),
-    ('〕', "Right Tortoise Shell Bracket", ']'),
-    ('〗', "Right White Lenticular Bracket", ']'),
-    ('〙', "Right White Tortoise Shell Bracket", ']'),
-    ('〛', "Right White Square Bracket", ']'),
-
-    ('❴', "Medium Left Curly Bracket Ornament", '{'),
-    ('𝄔', "Musical Symbol Brace", '{'),
-    ('{', "Fullwidth Left Curly Bracket", '{'),
-
-    ('❵', "Medium Right Curly Bracket Ornament", '}'),
-    ('}', "Fullwidth Right Curly Bracket", '}'),
-
-    ('⁎', "Low Asterisk", '*'),
-    ('٭', "Arabic Five Pointed Star", '*'),
-    ('∗', "Asterisk Operator", '*'),
-    ('𐌟', "Old Italic Letter Ess", '*'),
-    ('*', "Fullwidth Asterisk", '*'),
-
-    ('᜵', "Philippine Single Punctuation", '/'),
-    ('⁁', "Caret Insertion Point", '/'),
-    ('∕', "Division Slash", '/'),
-    ('⁄', "Fraction Slash", '/'),
-    ('╱', "Box Drawings Light Diagonal Upper Right To Lower Left", '/'),
-    ('⟋', "Mathematical Rising Diagonal", '/'),
-    ('⧸', "Big Solidus", '/'),
-    ('𝈺', "Greek Instrumental Notation Symbol-47", '/'),
-    ('㇓', "CJK Stroke Sp", '/'),
-    ('〳', "Vertical Kana Repeat Mark Upper Half", '/'),
-    ('Ⳇ', "Coptic Capital Letter Old Coptic Esh", '/'),
-    ('ノ', "Katakana Letter No", '/'),
-    ('丿', "CJK Unified Ideograph-4E3F", '/'),
-    ('⼃', "Kangxi Radical Slash", '/'),
-    ('/', "Fullwidth Solidus", '/'),
-
-    ('\', "Fullwidth Reverse Solidus", '\\'),
-    ('﹨', "Small Reverse Solidus", '\\'),
-    ('∖', "Set Minus", '\\'),
-    ('⟍', "Mathematical Falling Diagonal", '\\'),
-    ('⧵', "Reverse Solidus Operator", '\\'),
-    ('⧹', "Big Reverse Solidus", '\\'),
-    ('⧹', "Greek Vocal Notation Symbol-16", '\\'),
-    ('⧹', "Greek Instrumental Symbol-48", '\\'),
-    ('㇔', "CJK Stroke D", '\\'),
-    ('丶', "CJK Unified Ideograph-4E36", '\\'),
-    ('⼂', "Kangxi Radical Dot", '\\'),
-    ('、', "Ideographic Comma", '\\'),
-    ('ヽ', "Katakana Iteration Mark", '\\'),
-
-    ('ꝸ', "Latin Small Letter Um", '&'),
-    ('&', "Fullwidth Ampersand", '&'),
-
-    ('᛭', "Runic Cross Punctuation", '+'),
-    ('➕', "Heavy Plus Sign", '+'),
-    ('𐊛', "Lycian Letter H", '+'),
-    ('﬩', "Hebrew Letter Alternative Plus Sign", '+'),
-    ('+', "Fullwidth Plus Sign", '+'),
-
-    ('‹', "Single Left-Pointing Angle Quotation Mark", '<'),
-    ('❮', "Heavy Left-Pointing Angle Quotation Mark Ornament", '<'),
-    ('˂', "Modifier Letter Left Arrowhead", '<'),
-    ('𝈶', "Greek Instrumental Symbol-40", '<'),
-    ('ᐸ', "Canadian Syllabics Pa", '<'),
-    ('ᚲ', "Runic Letter Kauna", '<'),
-    ('❬', "Medium Left-Pointing Angle Bracket Ornament", '<'),
-    ('⟨', "Mathematical Left Angle Bracket", '<'),
-    ('〈', "Left-Pointing Angle Bracket", '<'),
-    ('〈', "Left Angle Bracket", '<'),
-    ('㇛', "CJK Stroke Pd", '<'),
-    ('く', "Hiragana Letter Ku", '<'),
-    ('𡿨', "CJK Unified Ideograph-21FE8", '<'),
-    ('《', "Left Double Angle Bracket", '<'),
-    ('<', "Fullwidth Less-Than Sign", '<'),
-
-    ('᐀', "Canadian Syllabics Hyphen", '='),
-    ('⹀', "Double Hyphen", '='),
-    ('゠', "Katakana-Hiragana Double Hyphen", '='),
-    ('꓿', "Lisu Punctuation Full Stop", '='),
-    ('=', "Fullwidth Equals Sign", '='),
-
-    ('›', "Single Right-Pointing Angle Quotation Mark", '>'),
-    ('❯', "Heavy Right-Pointing Angle Quotation Mark Ornament", '>'),
-    ('˃', "Modifier Letter Right Arrowhead", '>'),
-    ('𝈷', "Greek Instrumental Symbol-42", '>'),
-    ('ᐳ', "Canadian Syllabics Po", '>'),
-    ('𖼿', "Miao Letter Archaic Zza", '>'),
-    ('❭', "Medium Right-Pointing Angle Bracket Ornament", '>'),
-    ('⟩', "Mathematical Right Angle Bracket", '>'),
-    ('〉', "Right-Pointing Angle Bracket", '>'),
-    ('〉', "Right Angle Bracket", '>'),
-    ('》', "Right Double Angle Bracket", '>'),
-    ('>', "Fullwidth Greater-Than Sign", '>'),
+pub(crate) const UNICODE_ARRAY: &[(char, &str, &str)] = &[
+    ('
', "Line Separator", " "),
+    ('
', "Paragraph Separator", " "),
+    (' ', "Ogham Space mark", " "),
+    (' ', "En Quad", " "),
+    (' ', "Em Quad", " "),
+    (' ', "En Space", " "),
+    (' ', "Em Space", " "),
+    (' ', "Three-Per-Em Space", " "),
+    (' ', "Four-Per-Em Space", " "),
+    (' ', "Six-Per-Em Space", " "),
+    (' ', "Punctuation Space", " "),
+    (' ', "Thin Space", " "),
+    (' ', "Hair Space", " "),
+    (' ', "Medium Mathematical Space", " "),
+    (' ', "No-Break Space", " "),
+    (' ', "Figure Space", " "),
+    (' ', "Narrow No-Break Space", " "),
+    (' ', "Ideographic Space", " "),
+
+    ('ߺ', "Nko Lajanyalan", "_"),
+    ('﹍', "Dashed Low Line", "_"),
+    ('﹎', "Centreline Low Line", "_"),
+    ('﹏', "Wavy Low Line", "_"),
+    ('_', "Fullwidth Low Line", "_"),
+
+    ('‐', "Hyphen", "-"),
+    ('‑', "Non-Breaking Hyphen", "-"),
+    ('‒', "Figure Dash", "-"),
+    ('–', "En Dash", "-"),
+    ('—', "Em Dash", "-"),
+    ('﹘', "Small Em Dash", "-"),
+    ('۔', "Arabic Full Stop", "-"),
+    ('⁃', "Hyphen Bullet", "-"),
+    ('˗', "Modifier Letter Minus Sign", "-"),
+    ('−', "Minus Sign", "-"),
+    ('➖', "Heavy Minus Sign", "-"),
+    ('Ⲻ', "Coptic Letter Dialect-P Ni", "-"),
+    ('ー', "Katakana-Hiragana Prolonged Sound Mark", "-"),
+    ('-', "Fullwidth Hyphen-Minus", "-"),
+    ('―', "Horizontal Bar", "-"),
+    ('─', "Box Drawings Light Horizontal", "-"),
+    ('━', "Box Drawings Heavy Horizontal", "-"),
+    ('㇐', "CJK Stroke H", "-"),
+    ('ꟷ', "Latin Epigraphic Letter Sideways I", "-"),
+    ('ᅳ', "Hangul Jungseong Eu", "-"),
+    ('ㅡ', "Hangul Letter Eu", "-"),
+    ('一', "CJK Unified Ideograph-4E00", "-"),
+    ('⼀', "Kangxi Radical One", "-"),
+
+    ('؍', "Arabic Date Separator", ","),
+    ('٫', "Arabic Decimal Separator", ","),
+    ('‚', "Single Low-9 Quotation Mark", ","),
+    ('¸', "Cedilla", ","),
+    ('ꓹ', "Lisu Letter Tone Na Po", ","),
+    (',', "Fullwidth Comma", ","),
+
+    (';', "Greek Question Mark", ";"),
+    (';', "Fullwidth Semicolon", ";"),
+    ('︔', "Presentation Form For Vertical Semicolon", ";"),
+
+    ('ः', "Devanagari Sign Visarga", ":"),
+    ('ઃ', "Gujarati Sign Visarga", ":"),
+    (':', "Fullwidth Colon", ":"),
+    ('։', "Armenian Full Stop", ":"),
+    ('܃', "Syriac Supralinear Colon", ":"),
+    ('܄', "Syriac Sublinear Colon", ":"),
+    ('᛬', "Runic Multiple Punctuation", ":"),
+    ('︰', "Presentation Form For Vertical Two Dot Leader", ":"),
+    ('᠃', "Mongolian Full Stop", ":"),
+    ('᠉', "Mongolian Manchu Full Stop", ":"),
+    ('⁚', "Two Dot Punctuation", ":"),
+    ('׃', "Hebrew Punctuation Sof Pasuq", ":"),
+    ('˸', "Modifier Letter Raised Colon", ":"),
+    ('꞉', "Modifier Letter Colon", ":"),
+    ('∶', "Ratio", ":"),
+    ('ː', "Modifier Letter Triangular Colon", ":"),
+    ('ꓽ', "Lisu Letter Tone Mya Jeu", ":"),
+    ('︓', "Presentation Form For Vertical Colon", ":"),
+
+    ('!', "Fullwidth Exclamation Mark", "!"),
+    ('ǃ', "Latin Letter Retroflex Click", "!"),
+    ('ⵑ', "Tifinagh Letter Tuareg Yang", "!"),
+    ('︕', "Presentation Form For Vertical Exclamation Mark", "!"),
+
+    ('ʔ', "Latin Letter Glottal Stop", "?"),
+    ('Ɂ', "Latin Capital Letter Glottal Stop", "?"),
+    ('ॽ', "Devanagari Letter Glottal Stop", "?"),
+    ('Ꭾ', "Cherokee Letter He", "?"),
+    ('ꛫ', "Bamum Letter Ntuu", "?"),
+    ('?', "Fullwidth Question Mark", "?"),
+    ('︖', "Presentation Form For Vertical Question Mark", "?"),
+
+    ('𝅭', "Musical Symbol Combining Augmentation Dot", "."),
+    ('․', "One Dot Leader", "."),
+    ('܁', "Syriac Supralinear Full Stop", "."),
+    ('܂', "Syriac Sublinear Full Stop", "."),
+    ('꘎', "Vai Full Stop", "."),
+    ('𐩐', "Kharoshthi Punctuation Dot", "."),
+    ('٠', "Arabic-Indic Digit Zero", "."),
+    ('۰', "Extended Arabic-Indic Digit Zero", "."),
+    ('ꓸ', "Lisu Letter Tone Mya Ti", "."),
+    ('·', "Middle Dot", "."),
+    ('・', "Katakana Middle Dot", "."),
+    ('・', "Halfwidth Katakana Middle Dot", "."),
+    ('᛫', "Runic Single Punctuation", "."),
+    ('·', "Greek Ano Teleia", "."),
+    ('⸱', "Word Separator Middle Dot", "."),
+    ('𐄁', "Aegean Word Separator Dot", "."),
+    ('•', "Bullet", "."),
+    ('‧', "Hyphenation Point", "."),
+    ('∙', "Bullet Operator", "."),
+    ('⋅', "Dot Operator", "."),
+    ('ꞏ', "Latin Letter Sinological Dot", "."),
+    ('ᐧ', "Canadian Syllabics Final Middle Dot", "."),
+    ('ᐧ', "Canadian Syllabics Final Middle Dot", "."),
+    ('.', "Fullwidth Full Stop", "."),
+    ('。', "Ideographic Full Stop", "."),
+    ('︒', "Presentation Form For Vertical Ideographic Full Stop", "."),
+
+    ('՝', "Armenian Comma", "\'"),
+    (''', "Fullwidth Apostrophe", "\'"),
+    ('‘', "Left Single Quotation Mark", "\'"),
+    ('’', "Right Single Quotation Mark", "\'"),
+    ('‛', "Single High-Reversed-9 Quotation Mark", "\'"),
+    ('′', "Prime", "\'"),
+    ('‵', "Reversed Prime", "\'"),
+    ('՚', "Armenian Apostrophe", "\'"),
+    ('׳', "Hebrew Punctuation Geresh", "\'"),
+    ('`', "Grave Accent", "\'"),
+    ('`', "Greek Varia", "\'"),
+    ('`', "Fullwidth Grave Accent", "\'"),
+    ('´', "Acute Accent", "\'"),
+    ('΄', "Greek Tonos", "\'"),
+    ('´', "Greek Oxia", "\'"),
+    ('᾽', "Greek Koronis", "\'"),
+    ('᾿', "Greek Psili", "\'"),
+    ('῾', "Greek Dasia", "\'"),
+    ('ʹ', "Modifier Letter Prime", "\'"),
+    ('ʹ', "Greek Numeral Sign", "\'"),
+    ('ˈ', "Modifier Letter Vertical Line", "\'"),
+    ('ˊ', "Modifier Letter Acute Accent", "\'"),
+    ('ˋ', "Modifier Letter Grave Accent", "\'"),
+    ('˴', "Modifier Letter Middle Grave Accent", "\'"),
+    ('ʻ', "Modifier Letter Turned Comma", "\'"),
+    ('ʽ', "Modifier Letter Reversed Comma", "\'"),
+    ('ʼ', "Modifier Letter Apostrophe", "\'"),
+    ('ʾ', "Modifier Letter Right Half Ring", "\'"),
+    ('ꞌ', "Latin Small Letter Saltillo", "\'"),
+    ('י', "Hebrew Letter Yod", "\'"),
+    ('ߴ', "Nko High Tone Apostrophe", "\'"),
+    ('ߵ', "Nko Low Tone Apostrophe", "\'"),
+    ('ᑊ', "Canadian Syllabics West-Cree P", "\'"),
+    ('ᛌ', "Runic Letter Short-Twig-Sol S", "\'"),
+    ('𖽑', "Miao Sign Aspiration", "\'"),
+    ('𖽒', "Miao Sign Reformed Voicing", "\'"),
+
+    ('᳓', "Vedic Sign Nihshvasa", "\""),
+    ('"', "Fullwidth Quotation Mark", "\""),
+    ('“', "Left Double Quotation Mark", "\""),
+    ('”', "Right Double Quotation Mark", "\""),
+    ('‟', "Double High-Reversed-9 Quotation Mark", "\""),
+    ('″', "Double Prime", "\""),
+    ('‶', "Reversed Double Prime", "\""),
+    ('〃', "Ditto Mark", "\""),
+    ('״', "Hebrew Punctuation Gershayim", "\""),
+    ('˝', "Double Acute Accent", "\""),
+    ('ʺ', "Modifier Letter Double Prime", "\""),
+    ('˶', "Modifier Letter Middle Double Acute Accent", "\""),
+    ('˵', "Modifier Letter Middle Double Grave Accent", "\""),
+    ('ˮ', "Modifier Letter Double Apostrophe", "\""),
+    ('ײ', "Hebrew Ligature Yiddish Double Yod", "\""),
+    ('❞', "Heavy Double Comma Quotation Mark Ornament", "\""),
+    ('❝', "Heavy Double Turned Comma Quotation Mark Ornament", "\""),
+
+    ('(', "Fullwidth Left Parenthesis", "("),
+    ('❨', "Medium Left Parenthesis Ornament", "("),
+    ('﴾', "Ornate Left Parenthesis", "("),
+
+    (')', "Fullwidth Right Parenthesis", ")"),
+    ('❩', "Medium Right Parenthesis Ornament", ")"),
+    ('﴿', "Ornate Right Parenthesis", ")"),
+
+    ('[', "Fullwidth Left Square Bracket", "["),
+    ('❲', "Light Left Tortoise Shell Bracket Ornament", "["),
+    ('「', "Left Corner Bracket", "["),
+    ('『', "Left White Corner Bracket", "["),
+    ('【', "Left Black Lenticular Bracket", "["),
+    ('〔', "Left Tortoise Shell Bracket", "["),
+    ('〖', "Left White Lenticular Bracket", "["),
+    ('〘', "Left White Tortoise Shell Bracket", "["),
+    ('〚', "Left White Square Bracket", "["),
+
+    (']', "Fullwidth Right Square Bracket", "]"),
+    ('❳', "Light Right Tortoise Shell Bracket Ornament", "]"),
+    ('」', "Right Corner Bracket", "]"),
+    ('』', "Right White Corner Bracket", "]"),
+    ('】', "Right Black Lenticular Bracket", "]"),
+    ('〕', "Right Tortoise Shell Bracket", "]"),
+    ('〗', "Right White Lenticular Bracket", "]"),
+    ('〙', "Right White Tortoise Shell Bracket", "]"),
+    ('〛', "Right White Square Bracket", "]"),
+
+    ('❴', "Medium Left Curly Bracket Ornament", "{"),
+    ('𝄔', "Musical Symbol Brace", "{"),
+    ('{', "Fullwidth Left Curly Bracket", "{"),
+
+    ('❵', "Medium Right Curly Bracket Ornament", "}"),
+    ('}', "Fullwidth Right Curly Bracket", "}"),
+
+    ('⁎', "Low Asterisk", "*"),
+    ('٭', "Arabic Five Pointed Star", "*"),
+    ('∗', "Asterisk Operator", "*"),
+    ('𐌟', "Old Italic Letter Ess", "*"),
+    ('*', "Fullwidth Asterisk", "*"),
+
+    ('᜵', "Philippine Single Punctuation", "/"),
+    ('⁁', "Caret Insertion Point", "/"),
+    ('∕', "Division Slash", "/"),
+    ('⁄', "Fraction Slash", "/"),
+    ('╱', "Box Drawings Light Diagonal Upper Right To Lower Left", "/"),
+    ('⟋', "Mathematical Rising Diagonal", "/"),
+    ('⧸', "Big Solidus", "/"),
+    ('𝈺', "Greek Instrumental Notation Symbol-47", "/"),
+    ('㇓', "CJK Stroke Sp", "/"),
+    ('〳', "Vertical Kana Repeat Mark Upper Half", "/"),
+    ('Ⳇ', "Coptic Capital Letter Old Coptic Esh", "/"),
+    ('ノ', "Katakana Letter No", "/"),
+    ('丿', "CJK Unified Ideograph-4E3F", "/"),
+    ('⼃', "Kangxi Radical Slash", "/"),
+    ('/', "Fullwidth Solidus", "/"),
+
+    ('\', "Fullwidth Reverse Solidus", "\\"),
+    ('﹨', "Small Reverse Solidus", "\\"),
+    ('∖', "Set Minus", "\\"),
+    ('⟍', "Mathematical Falling Diagonal", "\\"),
+    ('⧵', "Reverse Solidus Operator", "\\"),
+    ('⧹', "Big Reverse Solidus", "\\"),
+    ('⧹', "Greek Vocal Notation Symbol-16", "\\"),
+    ('⧹', "Greek Instrumental Symbol-48", "\\"),
+    ('㇔', "CJK Stroke D", "\\"),
+    ('丶', "CJK Unified Ideograph-4E36", "\\"),
+    ('⼂', "Kangxi Radical Dot", "\\"),
+    ('、', "Ideographic Comma", "\\"),
+    ('ヽ', "Katakana Iteration Mark", "\\"),
+
+    ('ꝸ', "Latin Small Letter Um", "&"),
+    ('&', "Fullwidth Ampersand", "&"),
+
+    ('᛭', "Runic Cross Punctuation", "+"),
+    ('➕', "Heavy Plus Sign", "+"),
+    ('𐊛', "Lycian Letter H", "+"),
+    ('﬩', "Hebrew Letter Alternative Plus Sign", "+"),
+    ('+', "Fullwidth Plus Sign", "+"),
+
+    ('‹', "Single Left-Pointing Angle Quotation Mark", "<"),
+    ('❮', "Heavy Left-Pointing Angle Quotation Mark Ornament", "<"),
+    ('˂', "Modifier Letter Left Arrowhead", "<"),
+    ('𝈶', "Greek Instrumental Symbol-40", "<"),
+    ('ᐸ', "Canadian Syllabics Pa", "<"),
+    ('ᚲ', "Runic Letter Kauna", "<"),
+    ('❬', "Medium Left-Pointing Angle Bracket Ornament", "<"),
+    ('⟨', "Mathematical Left Angle Bracket", "<"),
+    ('〈', "Left-Pointing Angle Bracket", "<"),
+    ('〈', "Left Angle Bracket", "<"),
+    ('㇛', "CJK Stroke Pd", "<"),
+    ('く', "Hiragana Letter Ku", "<"),
+    ('𡿨', "CJK Unified Ideograph-21FE8", "<"),
+    ('《', "Left Double Angle Bracket", "<"),
+    ('<', "Fullwidth Less-Than Sign", "<"),
+
+    ('᐀', "Canadian Syllabics Hyphen", "="),
+    ('⹀', "Double Hyphen", "="),
+    ('゠', "Katakana-Hiragana Double Hyphen", "="),
+    ('꓿', "Lisu Punctuation Full Stop", "="),
+    ('=', "Fullwidth Equals Sign", "="),
+
+    ('›', "Single Right-Pointing Angle Quotation Mark", ">"),
+    ('❯', "Heavy Right-Pointing Angle Quotation Mark Ornament", ">"),
+    ('˃', "Modifier Letter Right Arrowhead", ">"),
+    ('𝈷', "Greek Instrumental Symbol-42", ">"),
+    ('ᐳ', "Canadian Syllabics Po", ">"),
+    ('𖼿', "Miao Letter Archaic Zza", ">"),
+    ('❭', "Medium Right-Pointing Angle Bracket Ornament", ">"),
+    ('⟩', "Mathematical Right Angle Bracket", ">"),
+    ('〉', "Right-Pointing Angle Bracket", ">"),
+    ('〉', "Right Angle Bracket", ">"),
+    ('》', "Right Double Angle Bracket", ">"),
+    ('>', "Fullwidth Greater-Than Sign", ">"),
+    ('⩵', "Two Consecutive Equals Signs", "==")
 ];
 
 // FIXME: the lexer could be used to turn the ASCII version of unicode homoglyphs, instead of
 // keeping the substitution token in this table. Ideally, this should be inside `rustc_lexer`.
 // However, we should first remove compound tokens like `<<` from `rustc_lexer`, and then add
 // fancier error recovery to it, as there will be less overall work to do this way.
-const ASCII_ARRAY: &[(char, &str, Option<token::TokenKind>)] = &[
-    (' ', "Space", None),
-    ('_', "Underscore", Some(token::Ident(kw::Underscore, false))),
-    ('-', "Minus/Hyphen", Some(token::BinOp(token::Minus))),
-    (',', "Comma", Some(token::Comma)),
-    (';', "Semicolon", Some(token::Semi)),
-    (':', "Colon", Some(token::Colon)),
-    ('!', "Exclamation Mark", Some(token::Not)),
-    ('?', "Question Mark", Some(token::Question)),
-    ('.', "Period", Some(token::Dot)),
-    ('(', "Left Parenthesis", Some(token::OpenDelim(Delimiter::Parenthesis))),
-    (')', "Right Parenthesis", Some(token::CloseDelim(Delimiter::Parenthesis))),
-    ('[', "Left Square Bracket", Some(token::OpenDelim(Delimiter::Bracket))),
-    (']', "Right Square Bracket", Some(token::CloseDelim(Delimiter::Bracket))),
-    ('{', "Left Curly Brace", Some(token::OpenDelim(Delimiter::Brace))),
-    ('}', "Right Curly Brace", Some(token::CloseDelim(Delimiter::Brace))),
-    ('*', "Asterisk", Some(token::BinOp(token::Star))),
-    ('/', "Slash", Some(token::BinOp(token::Slash))),
-    ('\\', "Backslash", None),
-    ('&', "Ampersand", Some(token::BinOp(token::And))),
-    ('+', "Plus Sign", Some(token::BinOp(token::Plus))),
-    ('<', "Less-Than Sign", Some(token::Lt)),
-    ('=', "Equals Sign", Some(token::Eq)),
-    ('>', "Greater-Than Sign", Some(token::Gt)),
+const ASCII_ARRAY: &[(&str, &str, Option<token::TokenKind>)] = &[
+    (" ", "Space", None),
+    ("_", "Underscore", Some(token::Ident(kw::Underscore, false))),
+    ("-", "Minus/Hyphen", Some(token::BinOp(token::Minus))),
+    (",", "Comma", Some(token::Comma)),
+    (";", "Semicolon", Some(token::Semi)),
+    (":", "Colon", Some(token::Colon)),
+    ("!", "Exclamation Mark", Some(token::Not)),
+    ("?", "Question Mark", Some(token::Question)),
+    (".", "Period", Some(token::Dot)),
+    ("(", "Left Parenthesis", Some(token::OpenDelim(Delimiter::Parenthesis))),
+    (")", "Right Parenthesis", Some(token::CloseDelim(Delimiter::Parenthesis))),
+    ("[", "Left Square Bracket", Some(token::OpenDelim(Delimiter::Bracket))),
+    ("]", "Right Square Bracket", Some(token::CloseDelim(Delimiter::Bracket))),
+    ("{", "Left Curly Brace", Some(token::OpenDelim(Delimiter::Brace))),
+    ("}", "Right Curly Brace", Some(token::CloseDelim(Delimiter::Brace))),
+    ("*", "Asterisk", Some(token::BinOp(token::Star))),
+    ("/", "Slash", Some(token::BinOp(token::Slash))),
+    ("\\", "Backslash", None),
+    ("&", "Ampersand", Some(token::BinOp(token::And))),
+    ("+", "Plus Sign", Some(token::BinOp(token::Plus))),
+    ("<", "Less-Than Sign", Some(token::Lt)),
+    ("=", "Equals Sign", Some(token::Eq)),
+    ("==", "Double Equals Sign", Some(token::EqEq)),
+    (">", "Greater-Than Sign", Some(token::Gt)),
     // FIXME: Literals are already lexed by this point, so we can't recover gracefully just by
     // spitting the correct token out.
-    ('\'', "Single Quote", None),
-    ('"', "Quotation Mark", None),
+    ("\'", "Single Quote", None),
+    ("\"", "Quotation Mark", None),
 ];
 
 pub(super) fn check_for_substitution<'a>(
@@ -339,11 +341,11 @@ pub(super) fn check_for_substitution<'a>(
     err: &mut Diagnostic,
     count: usize,
 ) -> Option<token::TokenKind> {
-    let &(_u_char, u_name, ascii_char) = UNICODE_ARRAY.iter().find(|&&(c, _, _)| c == ch)?;
+    let &(_, u_name, ascii_str) = UNICODE_ARRAY.iter().find(|&&(c, _, _)| c == ch)?;
 
     let span = Span::with_root_ctxt(pos, pos + Pos::from_usize(ch.len_utf8() * count));
 
-    let Some((_ascii_char, ascii_name, token)) = ASCII_ARRAY.iter().find(|&&(c, _, _)| c == ascii_char) else {
+    let Some((_, ascii_name, token)) = ASCII_ARRAY.iter().find(|&&(s, _, _)| s == ascii_str) else {
         let msg = format!("substitution character not found for '{}'", ch);
         reader.sess.span_diagnostic.span_bug_no_panic(span, &msg);
         return None;
@@ -354,7 +356,7 @@ pub(super) fn check_for_substitution<'a>(
         let msg = format!(
             "Unicode characters '“' (Left Double Quotation Mark) and \
              '”' (Right Double Quotation Mark) look like '{}' ({}), but are not",
-            ascii_char, ascii_name
+            ascii_str, ascii_name
         );
         err.span_suggestion(
             Span::with_root_ctxt(
@@ -368,12 +370,12 @@ pub(super) fn check_for_substitution<'a>(
     } else {
         let msg = format!(
             "Unicode character '{}' ({}) looks like '{}' ({}), but it is not",
-            ch, u_name, ascii_char, ascii_name
+            ch, u_name, ascii_str, ascii_name
         );
         err.span_suggestion(
             span,
             &msg,
-            ascii_char.to_string().repeat(count),
+            ascii_str.to_string().repeat(count),
             Applicability::MaybeIncorrect,
         );
     }
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index d58afcd4c9f..bf93a89f065 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1353,9 +1353,6 @@ impl<'a> Parser<'a> {
                 err.span_label(sp, "while parsing this `loop` expression");
                 err
             })
-        } else if self.eat_keyword(kw::Continue) {
-            let kind = ExprKind::Continue(self.eat_label());
-            Ok(self.mk_expr(lo.to(self.prev_token.span), kind))
         } else if self.eat_keyword(kw::Match) {
             let match_sp = self.prev_token.span;
             self.parse_match_expr().map_err(|mut err| {
@@ -1379,6 +1376,8 @@ impl<'a> Parser<'a> {
             self.parse_try_block(lo)
         } else if self.eat_keyword(kw::Return) {
             self.parse_return_expr()
+        } else if self.eat_keyword(kw::Continue) {
+            self.parse_continue_expr(lo)
         } else if self.eat_keyword(kw::Break) {
             self.parse_break_expr()
         } else if self.eat_keyword(kw::Yield) {
@@ -1715,10 +1714,10 @@ impl<'a> Parser<'a> {
     fn parse_break_expr(&mut self) -> PResult<'a, P<Expr>> {
         let lo = self.prev_token.span;
         let mut label = self.eat_label();
-        let kind = if label.is_some() && self.token == token::Colon {
+        let kind = if self.token == token::Colon && let Some(label) = label.take() {
             // The value expression can be a labeled loop, see issue #86948, e.g.:
             // `loop { break 'label: loop { break 'label 42; }; }`
-            let lexpr = self.parse_labeled_expr(label.take().unwrap(), true)?;
+            let lexpr = self.parse_labeled_expr(label, true)?;
             self.sess.emit_err(LabeledLoopInBreak {
                 span: lexpr.span,
                 sub: WrapExpressionInParentheses {
@@ -1730,8 +1729,8 @@ impl<'a> Parser<'a> {
         } else if self.token != token::OpenDelim(Delimiter::Brace)
             || !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
         {
-            let expr = self.parse_expr_opt()?;
-            if let Some(expr) = &expr {
+            let mut expr = self.parse_expr_opt()?;
+            if let Some(expr) = &mut expr {
                 if label.is_some()
                     && matches!(
                         expr.kind,
@@ -1749,7 +1748,19 @@ impl<'a> Parser<'a> {
                         BuiltinLintDiagnostics::BreakWithLabelAndLoop(expr.span),
                     );
                 }
+
+                // Recover `break label aaaaa`
+                if self.may_recover()
+                    && let ExprKind::Path(None, p) = &expr.kind
+                    && let [segment] = &*p.segments
+                    && let &ast::PathSegment { ident, args: None, .. } = segment
+                    && let Some(next) = self.parse_expr_opt()?
+                {
+                    label = Some(self.recover_ident_into_label(ident));
+                    *expr = next;
+                }
             }
+
             expr
         } else {
             None
@@ -1758,6 +1769,23 @@ impl<'a> Parser<'a> {
         self.maybe_recover_from_bad_qpath(expr)
     }
 
+    /// Parse `"continue" label?`.
+    fn parse_continue_expr(&mut self, lo: Span) -> PResult<'a, P<Expr>> {
+        let mut label = self.eat_label();
+
+        // Recover `continue label` -> `continue 'label`
+        if self.may_recover()
+            && label.is_none()
+            && let Some((ident, _)) = self.token.ident()
+        {
+            self.bump();
+            label = Some(self.recover_ident_into_label(ident));
+        }
+
+        let kind = ExprKind::Continue(label);
+        Ok(self.mk_expr(lo.to(self.prev_token.span), kind))
+    }
+
     /// Parse `"yield" expr?`.
     fn parse_yield_expr(&mut self) -> PResult<'a, P<Expr>> {
         let lo = self.prev_token.span;
@@ -3046,6 +3074,25 @@ impl<'a> Parser<'a> {
         false
     }
 
+    /// Converts an ident into 'label and emits an "expected a label, found an identifier" error.
+    fn recover_ident_into_label(&mut self, ident: Ident) -> Label {
+        // Convert `label` -> `'label`,
+        // so that nameres doesn't complain about non-existing label
+        let label = format!("'{}", ident.name);
+        let ident = Ident { name: Symbol::intern(&label), span: ident.span };
+
+        self.struct_span_err(ident.span, "expected a label, found an identifier")
+            .span_suggestion(
+                ident.span,
+                "labels start with a tick",
+                label,
+                Applicability::MachineApplicable,
+            )
+            .emit();
+
+        Label { ident }
+    }
+
     /// Parses `ident (COLON expr)?`.
     fn parse_expr_field(&mut self) -> PResult<'a, ExprField> {
         let attrs = self.parse_outer_attributes()?;
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 706002f79b1..7597b8d126a 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -164,6 +164,7 @@ symbols! {
         Capture,
         Center,
         Clone,
+        Context,
         Continue,
         Copy,
         Count,
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 5f649852d0b..225c1050c7c 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -401,12 +401,12 @@ fn resolve_negative_obligation<'tcx>(
     infcx.resolve_regions(&outlives_env).is_empty()
 }
 
+#[instrument(level = "debug", skip(tcx), ret)]
 pub fn trait_ref_is_knowable<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_ref: ty::TraitRef<'tcx>,
 ) -> Result<(), Conflict> {
-    debug!("trait_ref_is_knowable(trait_ref={:?})", trait_ref);
-    if orphan_check_trait_ref(tcx, trait_ref, InCrate::Remote).is_ok() {
+    if orphan_check_trait_ref(trait_ref, InCrate::Remote).is_ok() {
         // A downstream or cousin crate is allowed to implement some
         // substitution of this trait-ref.
         return Err(Conflict::Downstream);
@@ -429,11 +429,9 @@ pub fn trait_ref_is_knowable<'tcx>(
     // and if we are an intermediate owner, then we don't care
     // about future-compatibility, which means that we're OK if
     // we are an owner.
-    if orphan_check_trait_ref(tcx, trait_ref, InCrate::Local).is_ok() {
-        debug!("trait_ref_is_knowable: orphan check passed");
+    if orphan_check_trait_ref(trait_ref, InCrate::Local).is_ok() {
         Ok(())
     } else {
-        debug!("trait_ref_is_knowable: nonlocal, nonfundamental, unowned");
         Err(Conflict::Upstream)
     }
 }
@@ -445,6 +443,7 @@ pub fn trait_ref_is_local_or_fundamental<'tcx>(
     trait_ref.def_id.krate == LOCAL_CRATE || tcx.has_attr(trait_ref.def_id, sym::fundamental)
 }
 
+#[derive(Debug)]
 pub enum OrphanCheckErr<'tcx> {
     NonLocalInputType(Vec<(Ty<'tcx>, bool /* Is this the first input type? */)>),
     UncoveredTy(Ty<'tcx>, Option<Ty<'tcx>>),
@@ -456,13 +455,12 @@ pub enum OrphanCheckErr<'tcx> {
 ///
 /// 1. All type parameters in `Self` must be "covered" by some local type constructor.
 /// 2. Some local type must appear in `Self`.
+#[instrument(level = "debug", skip(tcx), ret)]
 pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanCheckErr<'_>> {
-    debug!("orphan_check({:?})", impl_def_id);
-
     // We only except this routine to be invoked on implementations
     // of a trait, not inherent implementations.
     let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity();
-    debug!("orphan_check: trait_ref={:?}", trait_ref);
+    debug!(?trait_ref);
 
     // If the *trait* is local to the crate, ok.
     if trait_ref.def_id.is_local() {
@@ -470,7 +468,7 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe
         return Ok(());
     }
 
-    orphan_check_trait_ref(tcx, trait_ref, InCrate::Local)
+    orphan_check_trait_ref(trait_ref, InCrate::Local)
 }
 
 /// Checks whether a trait-ref is potentially implementable by a crate.
@@ -559,13 +557,11 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe
 ///
 /// Note that this function is never called for types that have both type
 /// parameters and inference variables.
+#[instrument(level = "trace", ret)]
 fn orphan_check_trait_ref<'tcx>(
-    tcx: TyCtxt<'tcx>,
     trait_ref: ty::TraitRef<'tcx>,
     in_crate: InCrate,
 ) -> Result<(), OrphanCheckErr<'tcx>> {
-    debug!("orphan_check_trait_ref(trait_ref={:?}, in_crate={:?})", trait_ref, in_crate);
-
     if trait_ref.needs_infer() && trait_ref.needs_subst() {
         bug!(
             "can't orphan check a trait ref with both params and inference variables {:?}",
@@ -573,7 +569,7 @@ fn orphan_check_trait_ref<'tcx>(
         );
     }
 
-    let mut checker = OrphanChecker::new(tcx, in_crate);
+    let mut checker = OrphanChecker::new(in_crate);
     match trait_ref.visit_with(&mut checker) {
         ControlFlow::Continue(()) => Err(OrphanCheckErr::NonLocalInputType(checker.non_local_tys)),
         ControlFlow::Break(OrphanCheckEarlyExit::ParamTy(ty)) => {
@@ -592,7 +588,6 @@ fn orphan_check_trait_ref<'tcx>(
 }
 
 struct OrphanChecker<'tcx> {
-    tcx: TyCtxt<'tcx>,
     in_crate: InCrate,
     in_self_ty: bool,
     /// Ignore orphan check failures and exclusively search for the first
@@ -602,9 +597,8 @@ struct OrphanChecker<'tcx> {
 }
 
 impl<'tcx> OrphanChecker<'tcx> {
-    fn new(tcx: TyCtxt<'tcx>, in_crate: InCrate) -> Self {
+    fn new(in_crate: InCrate) -> Self {
         OrphanChecker {
-            tcx,
             in_crate,
             in_self_ty: true,
             search_first_local_ty: false,
@@ -697,13 +691,17 @@ impl<'tcx> TypeVisitor<'tcx> for OrphanChecker<'tcx> {
                 }
             }
             ty::Error(_) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)),
-            ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) => {
-                self.tcx.sess.delay_span_bug(
-                    DUMMY_SP,
-                    format!("ty_is_local invoked on closure or generator: {:?}", ty),
-                );
-                ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
+            ty::Closure(did, ..) | ty::Generator(did, ..) => {
+                if self.def_id_is_local(did) {
+                    ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
+                } else {
+                    self.found_non_local_ty(ty)
+                }
             }
+            // This should only be created when checking whether we have to check whether some
+            // auto trait impl applies. There will never be multiple impls, so we can just
+            // act as if it were a local type here.
+            ty::GeneratorWitness(_) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)),
             ty::Alias(ty::Opaque, ..) => {
                 // This merits some explanation.
                 // Normally, opaque types are not involved when performing
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index b47a70b4e7b..12d4cb4fc69 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -654,7 +654,7 @@ impl<'tcx> WfPredicates<'tcx> {
                     // 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 d457a4a2bea..7d2d8433c93 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -154,10 +154,8 @@ fn implied_bounds_from_components<'tcx>(
             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/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 669f84ae1b4..91a505a72fa 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -108,21 +108,41 @@ fn fn_sig_for_fn_abi<'tcx>(
             // `Generator::resume(...) -> GeneratorState` function in case we
             // have an ordinary generator, or the `Future::poll(...) -> Poll`
             // function in case this is a special generator backing an async construct.
-            let ret_ty = if tcx.generator_is_async(did) {
-                let state_did = tcx.require_lang_item(LangItem::Poll, None);
-                let state_adt_ref = tcx.adt_def(state_did);
-                let state_substs = tcx.intern_substs(&[sig.return_ty.into()]);
-                tcx.mk_adt(state_adt_ref, state_substs)
+            let (resume_ty, ret_ty) = if tcx.generator_is_async(did) {
+                // The signature should be `Future::poll(_, &mut Context<'_>) -> Poll<Output>`
+                let poll_did = tcx.require_lang_item(LangItem::Poll, None);
+                let poll_adt_ref = tcx.adt_def(poll_did);
+                let poll_substs = tcx.intern_substs(&[sig.return_ty.into()]);
+                let ret_ty = tcx.mk_adt(poll_adt_ref, poll_substs);
+
+                // We have to replace the `ResumeTy` that is used for type and borrow checking
+                // with `&mut Context<'_>` which is used in codegen.
+                #[cfg(debug_assertions)]
+                {
+                    if let ty::Adt(resume_ty_adt, _) = sig.resume_ty.kind() {
+                        let expected_adt =
+                            tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, None));
+                        assert_eq!(*resume_ty_adt, expected_adt);
+                    } else {
+                        panic!("expected `ResumeTy`, found `{:?}`", sig.resume_ty);
+                    };
+                }
+                let context_mut_ref = tcx.mk_task_context();
+
+                (context_mut_ref, ret_ty)
             } else {
+                // The signature should be `Generator::resume(_, Resume) -> GeneratorState<Yield, Return>`
                 let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
                 let state_adt_ref = tcx.adt_def(state_did);
                 let state_substs = tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
-                tcx.mk_adt(state_adt_ref, state_substs)
+                let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
+
+                (sig.resume_ty, ret_ty)
             };
 
             ty::Binder::bind_with_vars(
                 tcx.mk_fn_sig(
-                    [env_ty, sig.resume_ty].iter(),
+                    [env_ty, resume_ty].iter(),
                     &ret_ty,
                     false,
                     hir::Unsafety::Normal,
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index afc3a3dc6a8..ca75c3895f4 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -106,6 +106,7 @@
 #![feature(const_size_of_val)]
 #![feature(const_align_of_val)]
 #![feature(const_ptr_read)]
+#![feature(const_maybe_uninit_zeroed)]
 #![feature(const_maybe_uninit_write)]
 #![feature(const_maybe_uninit_as_mut_ptr)]
 #![feature(const_refs_to_cell)]
diff --git a/library/alloc/src/vec/is_zero.rs b/library/alloc/src/vec/is_zero.rs
index 26120270c0c..cb9adf05c25 100644
--- a/library/alloc/src/vec/is_zero.rs
+++ b/library/alloc/src/vec/is_zero.rs
@@ -4,7 +4,8 @@ use crate::boxed::Box;
 
 #[rustc_specialization_trait]
 pub(super) unsafe trait IsZero {
-    /// Whether this value's representation is all zeros
+    /// Whether this value's representation is all zeros,
+    /// or can be represented with all zeroes.
     fn is_zero(&self) -> bool;
 }
 
@@ -147,6 +148,23 @@ impl_is_zero_option_of_nonzero!(
     NonZeroIsize,
 );
 
+macro_rules! impl_is_zero_option_of_num {
+    ($($t:ty,)+) => {$(
+        unsafe impl IsZero for Option<$t> {
+            #[inline]
+            fn is_zero(&self) -> bool {
+                const {
+                    let none: Self = unsafe { core::mem::MaybeUninit::zeroed().assume_init() };
+                    assert!(none.is_none());
+                }
+                self.is_none()
+            }
+        }
+    )+};
+}
+
+impl_is_zero_option_of_num!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize,);
+
 unsafe impl<T: IsZero> IsZero for Wrapping<T> {
     #[inline]
     fn is_zero(&self) -> bool {
diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs
index 5bfe001de46..c4fb3620946 100644
--- a/library/core/src/future/mod.rs
+++ b/library/core/src/future/mod.rs
@@ -112,6 +112,10 @@ pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> {
     unsafe { &mut *cx.0.as_ptr().cast() }
 }
 
+// FIXME(swatinem): This fn is currently needed to work around shortcomings
+// in type and lifetime inference.
+// See the comment at the bottom of `LoweringContext::make_async_expr` and
+// <https://github.com/rust-lang/rust/issues/104826>.
 #[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
 #[inline]
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index a4425fd234a..89adfccd901 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -174,6 +174,7 @@ impl RawWakerVTable {
 /// Currently, `Context` only serves to provide access to a [`&Waker`](Waker)
 /// which can be used to wake the current task.
 #[stable(feature = "futures_api", since = "1.36.0")]
+#[cfg_attr(not(bootstrap), lang = "Context")]
 pub struct Context<'a> {
     waker: &'a Waker,
     // Ensure we future-proof against variance changes by forcing
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index c2c4aa1c9df..3bc17b7754d 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -746,6 +746,8 @@ fn signal_string(signal: i32) -> &'static str {
         libc::SIGWINCH => " (SIGWINCH)",
         #[cfg(not(target_os = "haiku"))]
         libc::SIGIO => " (SIGIO)",
+        #[cfg(target_os = "haiku")]
+        libc::SIGPOLL => " (SIGPOLL)",
         libc::SIGSYS => " (SIGSYS)",
         // For information on Linux signals, run `man 7 signal`
         #[cfg(all(
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index ca3e9916487..bc8badad38e 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -138,7 +138,7 @@ pub(super) fn write_shared(
         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 7db47035967..22068ebe041 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -5,10 +5,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 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 @@ pub(crate) fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut node: hir::HirId) -> bool
     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 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> {
     /// 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 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         // 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 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
     }
 
     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 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         // 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 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         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 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             // 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 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         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 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 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 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         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 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             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 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                             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 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 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 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             | 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
-Subproject a5d47a72595dd6fbe7d4e4f6ec20dc5fe724edd
+Subproject 50eb688c2bbea5de5a2e8496230a7428798089d
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 2aea30870ff..3092c656cd7 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -775,7 +775,7 @@ fn make_test_name(
 ) -> test::TestName {
     // Print the name of the file, relative to the repository root.
     // `src_base` looks like `/path/to/rust/tests/ui`
-    let root_directory = config.src_base.parent().unwrap().parent().unwrap().parent().unwrap();
+    let root_directory = config.src_base.parent().unwrap().parent().unwrap();
     let path = testpaths.file.strip_prefix(root_directory).unwrap();
     let debugger = match config.debugger {
         Some(d) => format!("-{}", d),
diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs
index bc9fd35ecde..5b84b51a035 100644
--- a/src/tools/tidy/src/error_codes.rs
+++ b/src/tools/tidy/src/error_codes.rs
@@ -27,8 +27,7 @@ const ERROR_DOCS_PATH: &str = "compiler/rustc_error_codes/src/error_codes/";
 const ERROR_TESTS_PATH: &str = "tests/ui/error-codes/";
 
 // Error codes that (for some reason) can't have a doctest in their explanation. Error codes are still expected to provide a code example, even if untested.
-const IGNORE_DOCTEST_CHECK: &[&str] =
-    &["E0208", "E0464", "E0570", "E0601", "E0602", "E0640", "E0717"];
+const IGNORE_DOCTEST_CHECK: &[&str] = &["E0464", "E0570", "E0601", "E0602", "E0640", "E0717"];
 
 // Error codes that don't yet have a UI test. This list will eventually be removed.
 const IGNORE_UI_TEST_CHECK: &[&str] =
diff --git a/tests/codegen/vec-calloc.rs b/tests/codegen/vec-calloc.rs
index 442cdd41dc6..4481a9d1e99 100644
--- a/tests/codegen/vec-calloc.rs
+++ b/tests/codegen/vec-calloc.rs
@@ -161,6 +161,23 @@ pub fn vec_option_bool(n: usize) -> Vec<Option<bool>> {
     vec![Some(false); n]
 }
 
+// CHECK-LABEL: @vec_option_i32
+#[no_mangle]
+pub fn vec_option_i32(n: usize) -> Vec<Option<i32>> {
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: call {{.*}}__rust_alloc_zeroed(
+
+    // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+    // CHECK-NOT: call {{.*}}reserve
+    // CHECK-NOT: call {{.*}}__rust_alloc(
+
+    // CHECK: ret void
+    vec![None; n]
+}
+
 // Ensure that __rust_alloc_zeroed gets the right attributes for LLVM to optimize it away.
 // CHECK: declare noalias noundef ptr @__rust_alloc_zeroed(i64 noundef, i64 allocalign noundef) unnamed_addr [[RUST_ALLOC_ZEROED_ATTRS:#[0-9]+]]
 
diff --git a/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir
new file mode 100644
index 00000000000..2a7f90fe947
--- /dev/null
+++ b/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir
@@ -0,0 +1,41 @@
+// MIR for `a::{closure#0}` 0 generator_resume
+/* generator_layout = GeneratorLayout {
+    field_tys: {},
+    variant_fields: {
+        Unresumed(0): [],
+        Returned (1): [],
+        Panicked (2): [],
+    },
+    storage_conflicts: BitMatrix(0x0) {},
+} */
+
+fn a::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:11:14: 11:16]>, _2: &mut Context<'_>) -> Poll<()> {
+    debug _task_context => _4;           // in scope 0 at $DIR/async_await.rs:+0:14: +0:16
+    let mut _0: std::task::Poll<()>;     // return place in scope 0 at $DIR/async_await.rs:+0:14: +0:16
+    let mut _3: ();                      // in scope 0 at $DIR/async_await.rs:+0:14: +0:16
+    let mut _4: &mut std::task::Context<'_>; // in scope 0 at $DIR/async_await.rs:+0:14: +0:16
+    let mut _5: u32;                     // in scope 0 at $DIR/async_await.rs:+0:14: +0:16
+
+    bb0: {
+        _5 = discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:11:14: 11:16]))); // scope 0 at $DIR/async_await.rs:+0:14: +0:16
+        switchInt(move _5) -> [0: bb1, 1: bb2, otherwise: bb3]; // scope 0 at $DIR/async_await.rs:+0:14: +0:16
+    }
+
+    bb1: {
+        _4 = move _2;                    // scope 0 at $DIR/async_await.rs:+0:14: +0:16
+        _3 = const ();                   // scope 0 at $DIR/async_await.rs:+0:14: +0:16
+        Deinit(_0);                      // scope 0 at $DIR/async_await.rs:+0:16: +0:16
+        ((_0 as Ready).0: ()) = move _3; // scope 0 at $DIR/async_await.rs:+0:16: +0:16
+        discriminant(_0) = 0;            // scope 0 at $DIR/async_await.rs:+0:16: +0:16
+        discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:11:14: 11:16]))) = 1; // scope 0 at $DIR/async_await.rs:+0:16: +0:16
+        return;                          // scope 0 at $DIR/async_await.rs:+0:16: +0:16
+    }
+
+    bb2: {
+        assert(const false, "`async fn` resumed after completion") -> bb2; // scope 0 at $DIR/async_await.rs:+0:14: +0:16
+    }
+
+    bb3: {
+        unreachable;                     // scope 0 at $DIR/async_await.rs:+0:14: +0:16
+    }
+}
diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir
new file mode 100644
index 00000000000..05edc4797d4
--- /dev/null
+++ b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir
@@ -0,0 +1,337 @@
+// MIR for `b::{closure#0}` 0 generator_resume
+/* generator_layout = GeneratorLayout {
+    field_tys: {
+        _0: impl std::future::Future<Output = ()>,
+        _1: impl std::future::Future<Output = ()>,
+    },
+    variant_fields: {
+        Unresumed(0): [],
+        Returned (1): [],
+        Panicked (2): [],
+        Suspend0 (3): [_0],
+        Suspend1 (4): [_1],
+    },
+    storage_conflicts: BitMatrix(2x2) {
+        (_0, _0),
+        (_1, _1),
+    },
+} */
+
+fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, _2: &mut Context<'_>) -> Poll<()> {
+    debug _task_context => _38;          // in scope 0 at $DIR/async_await.rs:+0:18: +3:2
+    let mut _0: std::task::Poll<()>;     // return place in scope 0 at $DIR/async_await.rs:+0:18: +3:2
+    let _3: ();                          // in scope 0 at $DIR/async_await.rs:+1:5: +1:14
+    let mut _4: impl std::future::Future<Output = ()>; // in scope 0 at $DIR/async_await.rs:+1:8: +1:14
+    let mut _5: impl std::future::Future<Output = ()>; // in scope 0 at $DIR/async_await.rs:+1:5: +1:8
+    let mut _6: impl std::future::Future<Output = ()>; // in scope 0 at $DIR/async_await.rs:+1:8: +1:14
+    let mut _7: ();                      // in scope 0 at $DIR/async_await.rs:+0:18: +3:2
+    let _8: ();                          // in scope 0 at $DIR/async_await.rs:+1:8: +1:14
+    let mut _9: std::task::Poll<()>;     // in scope 0 at $DIR/async_await.rs:+1:8: +1:14
+    let mut _10: std::pin::Pin<&mut impl std::future::Future<Output = ()>>; // in scope 0 at $DIR/async_await.rs:+1:8: +1:14
+    let mut _11: &mut impl std::future::Future<Output = ()>; // in scope 0 at $DIR/async_await.rs:+1:8: +1:14
+    let mut _12: &mut impl std::future::Future<Output = ()>; // in scope 0 at $DIR/async_await.rs:+1:8: +1:14
+    let mut _13: &mut std::task::Context<'_>; // in scope 0 at $DIR/async_await.rs:+1:5: +1:14
+    let mut _14: &mut std::task::Context<'_>; // in scope 0 at $DIR/async_await.rs:+1:5: +1:14
+    let mut _15: &mut std::task::Context<'_>; // in scope 0 at $DIR/async_await.rs:+1:8: +1:14
+    let mut _16: isize;                  // in scope 0 at $DIR/async_await.rs:+1:8: +1:14
+    let mut _18: !;                      // in scope 0 at $DIR/async_await.rs:+1:5: +1:14
+    let mut _19: &mut std::task::Context<'_>; // in scope 0 at $DIR/async_await.rs:+1:8: +1:14
+    let mut _20: ();                     // in scope 0 at $DIR/async_await.rs:+1:8: +1:14
+    let mut _21: impl std::future::Future<Output = ()>; // in scope 0 at $DIR/async_await.rs:+2:8: +2:14
+    let mut _22: impl std::future::Future<Output = ()>; // in scope 0 at $DIR/async_await.rs:+2:5: +2:8
+    let mut _23: impl std::future::Future<Output = ()>; // in scope 0 at $DIR/async_await.rs:+2:8: +2:14
+    let _24: ();                         // in scope 0 at $DIR/async_await.rs:+2:8: +2:14
+    let mut _25: std::task::Poll<()>;    // in scope 0 at $DIR/async_await.rs:+2:8: +2:14
+    let mut _26: std::pin::Pin<&mut impl std::future::Future<Output = ()>>; // in scope 0 at $DIR/async_await.rs:+2:8: +2:14
+    let mut _27: &mut impl std::future::Future<Output = ()>; // in scope 0 at $DIR/async_await.rs:+2:8: +2:14
+    let mut _28: &mut impl std::future::Future<Output = ()>; // in scope 0 at $DIR/async_await.rs:+2:8: +2:14
+    let mut _29: &mut std::task::Context<'_>; // in scope 0 at $DIR/async_await.rs:+2:5: +2:14
+    let mut _30: &mut std::task::Context<'_>; // in scope 0 at $DIR/async_await.rs:+2:5: +2:14
+    let mut _31: &mut std::task::Context<'_>; // in scope 0 at $DIR/async_await.rs:+2:8: +2:14
+    let mut _32: isize;                  // in scope 0 at $DIR/async_await.rs:+2:8: +2:14
+    let mut _34: !;                      // in scope 0 at $DIR/async_await.rs:+2:5: +2:14
+    let mut _35: &mut std::task::Context<'_>; // in scope 0 at $DIR/async_await.rs:+2:8: +2:14
+    let mut _36: ();                     // in scope 0 at $DIR/async_await.rs:+2:8: +2:14
+    let mut _37: ();                     // in scope 0 at $DIR/async_await.rs:+0:18: +3:2
+    let mut _38: &mut std::task::Context<'_>; // in scope 0 at $DIR/async_await.rs:+0:18: +3:2
+    let mut _39: u32;                    // in scope 0 at $DIR/async_await.rs:+0:18: +3:2
+    scope 1 {
+        debug __awaitee => (((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2])) as variant#3).0: impl std::future::Future<Output = ()>); // in scope 1 at $DIR/async_await.rs:+1:8: +1:14
+        let _17: ();                     // in scope 1 at $DIR/async_await.rs:+1:5: +1:14
+        scope 2 {
+        }
+        scope 3 {
+            debug result => _17;         // in scope 3 at $DIR/async_await.rs:+1:5: +1:14
+        }
+    }
+    scope 4 {
+        debug __awaitee => (((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2])) as variant#4).0: impl std::future::Future<Output = ()>); // in scope 4 at $DIR/async_await.rs:+2:8: +2:14
+        let _33: ();                     // in scope 4 at $DIR/async_await.rs:+2:5: +2:14
+        scope 5 {
+        }
+        scope 6 {
+            debug result => _33;         // in scope 6 at $DIR/async_await.rs:+2:5: +2:14
+        }
+    }
+
+    bb0: {
+        _39 = discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))); // scope 0 at $DIR/async_await.rs:+0:18: +3:2
+        switchInt(move _39) -> [0: bb1, 1: bb29, 3: bb27, 4: bb28, otherwise: bb30]; // scope 0 at $DIR/async_await.rs:+0:18: +3:2
+    }
+
+    bb1: {
+        _38 = move _2;                   // scope 0 at $DIR/async_await.rs:+0:18: +3:2
+        StorageLive(_3);                 // scope 0 at $DIR/async_await.rs:+1:5: +1:14
+        StorageLive(_4);                 // scope 0 at $DIR/async_await.rs:+1:8: +1:14
+        StorageLive(_5);                 // scope 0 at $DIR/async_await.rs:+1:5: +1:8
+        _5 = a() -> bb2;                 // scope 0 at $DIR/async_await.rs:+1:5: +1:8
+                                         // mir::Constant
+                                         // + span: $DIR/async_await.rs:15:5: 15:6
+                                         // + literal: Const { ty: fn() -> impl Future<Output = ()> {a}, val: Value(<ZST>) }
+    }
+
+    bb2: {
+        _4 = <impl Future<Output = ()> as IntoFuture>::into_future(move _5) -> bb3; // scope 0 at $DIR/async_await.rs:+1:8: +1:14
+                                         // mir::Constant
+                                         // + span: $DIR/async_await.rs:15:8: 15:14
+                                         // + literal: Const { ty: fn(impl Future<Output = ()>) -> <impl Future<Output = ()> as IntoFuture>::IntoFuture {<impl Future<Output = ()> as IntoFuture>::into_future}, val: Value(<ZST>) }
+    }
+
+    bb3: {
+        StorageDead(_5);                 // scope 0 at $DIR/async_await.rs:+1:13: +1:14
+        nop;                             // scope 0 at $DIR/async_await.rs:+1:8: +1:14
+        (((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2])) as variant#3).0: impl std::future::Future<Output = ()>) = move _4; // scope 0 at $DIR/async_await.rs:+1:8: +1:14
+        goto -> bb4;                     // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+    }
+
+    bb4: {
+        StorageLive(_8);                 // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+        StorageLive(_9);                 // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+        StorageLive(_10);                // scope 2 at $DIR/async_await.rs:+1:8: +1:14
+        StorageLive(_11);                // scope 2 at $DIR/async_await.rs:+1:8: +1:14
+        StorageLive(_12);                // scope 2 at $DIR/async_await.rs:+1:8: +1:14
+        _12 = &mut (((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2])) as variant#3).0: impl std::future::Future<Output = ()>); // scope 2 at $DIR/async_await.rs:+1:8: +1:14
+        _11 = &mut (*_12);               // scope 2 at $DIR/async_await.rs:+1:8: +1:14
+        _10 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _11) -> bb5; // scope 2 at $DIR/async_await.rs:+1:8: +1:14
+                                         // mir::Constant
+                                         // + span: $DIR/async_await.rs:15:8: 15:14
+                                         // + literal: Const { ty: unsafe fn(&mut impl Future<Output = ()>) -> Pin<&mut impl Future<Output = ()>> {Pin::<&mut impl Future<Output = ()>>::new_unchecked}, val: Value(<ZST>) }
+    }
+
+    bb5: {
+        StorageDead(_11);                // scope 2 at $DIR/async_await.rs:+1:13: +1:14
+        StorageLive(_13);                // scope 2 at $DIR/async_await.rs:+1:5: +1:14
+        StorageLive(_14);                // scope 2 at $DIR/async_await.rs:+1:5: +1:14
+        StorageLive(_15);                // scope 2 at $DIR/async_await.rs:+1:8: +1:14
+        _15 = _38;                       // scope 2 at $DIR/async_await.rs:+1:8: +1:14
+        _14 = move _15;                  // scope 2 at $DIR/async_await.rs:+1:5: +1:14
+        goto -> bb6;                     // scope 2 at $DIR/async_await.rs:+1:5: +1:14
+    }
+
+    bb6: {
+        _13 = &mut (*_14);               // scope 2 at $DIR/async_await.rs:+1:5: +1:14
+        StorageDead(_15);                // scope 2 at $DIR/async_await.rs:+1:13: +1:14
+        _9 = <impl Future<Output = ()> as Future>::poll(move _10, move _13) -> bb7; // scope 2 at $DIR/async_await.rs:+1:8: +1:14
+                                         // mir::Constant
+                                         // + span: $DIR/async_await.rs:15:8: 15:14
+                                         // + literal: Const { ty: for<'a, 'b, 'c> fn(Pin<&'a mut impl Future<Output = ()>>, &'b mut Context<'c>) -> Poll<<impl Future<Output = ()> as Future>::Output> {<impl Future<Output = ()> as Future>::poll}, val: Value(<ZST>) }
+    }
+
+    bb7: {
+        StorageDead(_13);                // scope 2 at $DIR/async_await.rs:+1:13: +1:14
+        StorageDead(_10);                // scope 2 at $DIR/async_await.rs:+1:13: +1:14
+        _16 = discriminant(_9);          // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+        switchInt(move _16) -> [0: bb10, 1: bb8, otherwise: bb9]; // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+    }
+
+    bb8: {
+        _8 = const ();                   // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+        StorageDead(_14);                // scope 1 at $DIR/async_await.rs:+1:13: +1:14
+        StorageDead(_12);                // scope 1 at $DIR/async_await.rs:+1:13: +1:14
+        StorageDead(_9);                 // scope 1 at $DIR/async_await.rs:+1:13: +1:14
+        StorageDead(_8);                 // scope 1 at $DIR/async_await.rs:+1:13: +1:14
+        StorageLive(_19);                // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+        StorageLive(_20);                // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+        _20 = ();                        // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+        Deinit(_0);                      // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+        discriminant(_0) = 1;            // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+        discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))) = 3; // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+        return;                          // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+    }
+
+    bb9: {
+        unreachable;                     // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+    }
+
+    bb10: {
+        StorageLive(_17);                // scope 1 at $DIR/async_await.rs:+1:5: +1:14
+        _17 = ((_9 as Ready).0: ());     // scope 1 at $DIR/async_await.rs:+1:5: +1:14
+        _3 = _17;                        // scope 3 at $DIR/async_await.rs:+1:5: +1:14
+        StorageDead(_17);                // scope 1 at $DIR/async_await.rs:+1:13: +1:14
+        StorageDead(_14);                // scope 1 at $DIR/async_await.rs:+1:13: +1:14
+        StorageDead(_12);                // scope 1 at $DIR/async_await.rs:+1:13: +1:14
+        StorageDead(_9);                 // scope 1 at $DIR/async_await.rs:+1:13: +1:14
+        StorageDead(_8);                 // scope 1 at $DIR/async_await.rs:+1:13: +1:14
+        goto -> bb12;                    // scope 0 at $DIR/async_await.rs:+1:13: +1:14
+    }
+
+    bb11: {
+        StorageDead(_20);                // scope 1 at $DIR/async_await.rs:+1:13: +1:14
+        _38 = move _19;                  // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+        StorageDead(_19);                // scope 1 at $DIR/async_await.rs:+1:13: +1:14
+        _7 = const ();                   // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+        goto -> bb4;                     // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+    }
+
+    bb12: {
+        nop;                             // scope 0 at $DIR/async_await.rs:+1:13: +1:14
+        goto -> bb13;                    // scope 0 at $DIR/async_await.rs:+1:14: +1:15
+    }
+
+    bb13: {
+        StorageDead(_4);                 // scope 0 at $DIR/async_await.rs:+1:14: +1:15
+        StorageDead(_3);                 // scope 0 at $DIR/async_await.rs:+1:14: +1:15
+        StorageLive(_21);                // scope 0 at $DIR/async_await.rs:+2:8: +2:14
+        StorageLive(_22);                // scope 0 at $DIR/async_await.rs:+2:5: +2:8
+        _22 = a() -> bb14;               // scope 0 at $DIR/async_await.rs:+2:5: +2:8
+                                         // mir::Constant
+                                         // + span: $DIR/async_await.rs:16:5: 16:6
+                                         // + literal: Const { ty: fn() -> impl Future<Output = ()> {a}, val: Value(<ZST>) }
+    }
+
+    bb14: {
+        _21 = <impl Future<Output = ()> as IntoFuture>::into_future(move _22) -> bb15; // scope 0 at $DIR/async_await.rs:+2:8: +2:14
+                                         // mir::Constant
+                                         // + span: $DIR/async_await.rs:16:8: 16:14
+                                         // + literal: Const { ty: fn(impl Future<Output = ()>) -> <impl Future<Output = ()> as IntoFuture>::IntoFuture {<impl Future<Output = ()> as IntoFuture>::into_future}, val: Value(<ZST>) }
+    }
+
+    bb15: {
+        StorageDead(_22);                // scope 0 at $DIR/async_await.rs:+2:13: +2:14
+        nop;                             // scope 0 at $DIR/async_await.rs:+2:8: +2:14
+        (((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2])) as variant#4).0: impl std::future::Future<Output = ()>) = move _21; // scope 0 at $DIR/async_await.rs:+2:8: +2:14
+        goto -> bb16;                    // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+    }
+
+    bb16: {
+        StorageLive(_24);                // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+        StorageLive(_25);                // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+        StorageLive(_26);                // scope 5 at $DIR/async_await.rs:+2:8: +2:14
+        StorageLive(_27);                // scope 5 at $DIR/async_await.rs:+2:8: +2:14
+        StorageLive(_28);                // scope 5 at $DIR/async_await.rs:+2:8: +2:14
+        _28 = &mut (((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2])) as variant#4).0: impl std::future::Future<Output = ()>); // scope 5 at $DIR/async_await.rs:+2:8: +2:14
+        _27 = &mut (*_28);               // scope 5 at $DIR/async_await.rs:+2:8: +2:14
+        _26 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _27) -> bb17; // scope 5 at $DIR/async_await.rs:+2:8: +2:14
+                                         // mir::Constant
+                                         // + span: $DIR/async_await.rs:16:8: 16:14
+                                         // + literal: Const { ty: unsafe fn(&mut impl Future<Output = ()>) -> Pin<&mut impl Future<Output = ()>> {Pin::<&mut impl Future<Output = ()>>::new_unchecked}, val: Value(<ZST>) }
+    }
+
+    bb17: {
+        StorageDead(_27);                // scope 5 at $DIR/async_await.rs:+2:13: +2:14
+        StorageLive(_29);                // scope 5 at $DIR/async_await.rs:+2:5: +2:14
+        StorageLive(_30);                // scope 5 at $DIR/async_await.rs:+2:5: +2:14
+        StorageLive(_31);                // scope 5 at $DIR/async_await.rs:+2:8: +2:14
+        _31 = _38;                       // scope 5 at $DIR/async_await.rs:+2:8: +2:14
+        _30 = move _31;                  // scope 5 at $DIR/async_await.rs:+2:5: +2:14
+        goto -> bb18;                    // scope 5 at $DIR/async_await.rs:+2:5: +2:14
+    }
+
+    bb18: {
+        _29 = &mut (*_30);               // scope 5 at $DIR/async_await.rs:+2:5: +2:14
+        StorageDead(_31);                // scope 5 at $DIR/async_await.rs:+2:13: +2:14
+        _25 = <impl Future<Output = ()> as Future>::poll(move _26, move _29) -> bb19; // scope 5 at $DIR/async_await.rs:+2:8: +2:14
+                                         // mir::Constant
+                                         // + span: $DIR/async_await.rs:16:8: 16:14
+                                         // + literal: Const { ty: for<'a, 'b, 'c> fn(Pin<&'a mut impl Future<Output = ()>>, &'b mut Context<'c>) -> Poll<<impl Future<Output = ()> as Future>::Output> {<impl Future<Output = ()> as Future>::poll}, val: Value(<ZST>) }
+    }
+
+    bb19: {
+        StorageDead(_29);                // scope 5 at $DIR/async_await.rs:+2:13: +2:14
+        StorageDead(_26);                // scope 5 at $DIR/async_await.rs:+2:13: +2:14
+        _32 = discriminant(_25);         // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+        switchInt(move _32) -> [0: bb22, 1: bb20, otherwise: bb21]; // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+    }
+
+    bb20: {
+        _24 = const ();                  // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+        StorageDead(_30);                // scope 4 at $DIR/async_await.rs:+2:13: +2:14
+        StorageDead(_28);                // scope 4 at $DIR/async_await.rs:+2:13: +2:14
+        StorageDead(_25);                // scope 4 at $DIR/async_await.rs:+2:13: +2:14
+        StorageDead(_24);                // scope 4 at $DIR/async_await.rs:+2:13: +2:14
+        StorageLive(_35);                // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+        StorageLive(_36);                // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+        _36 = ();                        // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+        Deinit(_0);                      // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+        discriminant(_0) = 1;            // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+        discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))) = 4; // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+        return;                          // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+    }
+
+    bb21: {
+        unreachable;                     // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+    }
+
+    bb22: {
+        StorageLive(_33);                // scope 4 at $DIR/async_await.rs:+2:5: +2:14
+        _33 = ((_25 as Ready).0: ());    // scope 4 at $DIR/async_await.rs:+2:5: +2:14
+        _37 = _33;                       // scope 6 at $DIR/async_await.rs:+2:5: +2:14
+        StorageDead(_33);                // scope 4 at $DIR/async_await.rs:+2:13: +2:14
+        StorageDead(_30);                // scope 4 at $DIR/async_await.rs:+2:13: +2:14
+        StorageDead(_28);                // scope 4 at $DIR/async_await.rs:+2:13: +2:14
+        StorageDead(_25);                // scope 4 at $DIR/async_await.rs:+2:13: +2:14
+        StorageDead(_24);                // scope 4 at $DIR/async_await.rs:+2:13: +2:14
+        goto -> bb24;                    // scope 0 at $DIR/async_await.rs:+2:13: +2:14
+    }
+
+    bb23: {
+        StorageDead(_36);                // scope 4 at $DIR/async_await.rs:+2:13: +2:14
+        _38 = move _35;                  // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+        StorageDead(_35);                // scope 4 at $DIR/async_await.rs:+2:13: +2:14
+        _7 = const ();                   // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+        goto -> bb16;                    // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+    }
+
+    bb24: {
+        nop;                             // scope 0 at $DIR/async_await.rs:+2:13: +2:14
+        goto -> bb25;                    // scope 0 at $DIR/async_await.rs:+3:1: +3:2
+    }
+
+    bb25: {
+        StorageDead(_21);                // scope 0 at $DIR/async_await.rs:+3:1: +3:2
+        goto -> bb26;                    // scope 0 at $DIR/async_await.rs:+3:1: +3:2
+    }
+
+    bb26: {
+        Deinit(_0);                      // scope 0 at $DIR/async_await.rs:+3:2: +3:2
+        ((_0 as Ready).0: ()) = move _37; // scope 0 at $DIR/async_await.rs:+3:2: +3:2
+        discriminant(_0) = 0;            // scope 0 at $DIR/async_await.rs:+3:2: +3:2
+        discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))) = 1; // scope 0 at $DIR/async_await.rs:+3:2: +3:2
+        return;                          // scope 0 at $DIR/async_await.rs:+3:2: +3:2
+    }
+
+    bb27: {
+        StorageLive(_3);                 // scope 0 at $DIR/async_await.rs:+0:18: +3:2
+        StorageLive(_4);                 // scope 0 at $DIR/async_await.rs:+0:18: +3:2
+        StorageLive(_19);                // scope 0 at $DIR/async_await.rs:+0:18: +3:2
+        StorageLive(_20);                // scope 0 at $DIR/async_await.rs:+0:18: +3:2
+        _19 = move _2;                   // scope 0 at $DIR/async_await.rs:+0:18: +3:2
+        goto -> bb11;                    // scope 0 at $DIR/async_await.rs:+0:18: +3:2
+    }
+
+    bb28: {
+        StorageLive(_21);                // scope 0 at $DIR/async_await.rs:+0:18: +3:2
+        StorageLive(_35);                // scope 0 at $DIR/async_await.rs:+0:18: +3:2
+        StorageLive(_36);                // scope 0 at $DIR/async_await.rs:+0:18: +3:2
+        _35 = move _2;                   // scope 0 at $DIR/async_await.rs:+0:18: +3:2
+        goto -> bb23;                    // scope 0 at $DIR/async_await.rs:+0:18: +3:2
+    }
+
+    bb29: {
+        assert(const false, "`async fn` resumed after completion") -> bb29; // scope 0 at $DIR/async_await.rs:+0:18: +3:2
+    }
+
+    bb30: {
+        unreachable;                     // scope 0 at $DIR/async_await.rs:+0:18: +3:2
+    }
+}
diff --git a/tests/mir-opt/building/async_await.rs b/tests/mir-opt/building/async_await.rs
new file mode 100644
index 00000000000..0b991e3b8f8
--- /dev/null
+++ b/tests/mir-opt/building/async_await.rs
@@ -0,0 +1,17 @@
+// This test makes sure that the generator MIR pass eliminates all calls to
+// `get_context`, and that the MIR argument type for an async fn and all locals
+// related to `yield` are `&mut Context`, and its return type is `Poll`.
+
+// edition:2018
+// compile-flags: -C panic=abort
+
+#![crate_type = "lib"]
+
+// EMIT_MIR async_await.a-{closure#0}.generator_resume.0.mir
+async fn a() {}
+
+// EMIT_MIR async_await.b-{closure#0}.generator_resume.0.mir
+pub async fn b() {
+    a().await;
+    a().await
+}
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 939da186fbc..4b1e04234c8 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 aff7402bc91..00000000000
--- 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 ac517257498..ac79582fb3f 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 a61577bd14a..00000000000
--- 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 b44e7135246..00000000000
--- 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/async-await/auxiliary/issue-107036.rs b/tests/ui/async-await/auxiliary/issue-107036.rs
new file mode 100644
index 00000000000..c3f6141b284
--- /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/issue-107036.rs b/tests/ui/async-await/issue-107036.rs
new file mode 100644
index 00000000000..6a22de2c943
--- /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/coherence/coherence-with-generator.rs b/tests/ui/coherence/coherence-with-generator.rs
index 70665ba06f9..5eb8dc2a468 100644
--- a/tests/ui/coherence/coherence-with-generator.rs
+++ b/tests/ui/coherence/coherence-with-generator.rs
@@ -1,5 +1,11 @@
 // Test that encountering closures during coherence does not cause issues.
 #![feature(type_alias_impl_trait, generators)]
+#![cfg_attr(specialized, feature(specialization))]
+#![allow(incomplete_features)]
+
+// revisions: stock specialized
+// [specialized]check-pass
+
 type OpaqueGenerator = impl Sized;
 fn defining_use() -> OpaqueGenerator {
     || {
@@ -13,6 +19,6 @@ struct Wrapper<T>(T);
 trait Trait {}
 impl Trait for Wrapper<OpaqueGenerator> {}
 impl<T: Sync> Trait for Wrapper<T> {}
-//~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
+//[stock]~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
 
 fn main() {}
diff --git a/tests/ui/coherence/coherence-with-generator.stderr b/tests/ui/coherence/coherence-with-generator.stock.stderr
index 6d3be2e16c6..478ac491264 100644
--- a/tests/ui/coherence/coherence-with-generator.stderr
+++ b/tests/ui/coherence/coherence-with-generator.stock.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
-  --> $DIR/coherence-with-generator.rs:15:1
+  --> $DIR/coherence-with-generator.rs:21:1
    |
 LL | impl Trait for Wrapper<OpaqueGenerator> {}
    | --------------------------------------- first implementation here
diff --git a/tests/ui/error-codes/E0208.rs b/tests/ui/error-codes/E0208.rs
new file mode 100644
index 00000000000..c67d42889d6
--- /dev/null
+++ b/tests/ui/error-codes/E0208.rs
@@ -0,0 +1,8 @@
+#![feature(rustc_attrs)]
+
+#[rustc_variance]
+struct Foo<'a, T> { //~ ERROR [-, o]
+    t: &'a mut T,
+}
+
+fn main() {}
diff --git a/tests/ui/error-codes/E0208.stderr b/tests/ui/error-codes/E0208.stderr
new file mode 100644
index 00000000000..dbbb41e7950
--- /dev/null
+++ b/tests/ui/error-codes/E0208.stderr
@@ -0,0 +1,8 @@
+error: [-, o]
+  --> $DIR/E0208.rs:4:1
+   |
+LL | struct Foo<'a, T> {
+   | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/error-codes/E0606.rs b/tests/ui/error-codes/E0606.rs
index cb0d8cfc31e..6f6c6513846 100644
--- a/tests/ui/error-codes/E0606.rs
+++ b/tests/ui/error-codes/E0606.rs
@@ -1,3 +1,4 @@
 fn main() {
-    &0u8 as u8; //~ ERROR E0606
+    let x = &(&0u8 as u8); //~ ERROR E0606
+    x as u8; //~ casting `&u8` as `u8` is invalid [E0606]
 }
diff --git a/tests/ui/error-codes/E0606.stderr b/tests/ui/error-codes/E0606.stderr
index fce24886eb0..2492eb299cc 100644
--- a/tests/ui/error-codes/E0606.stderr
+++ b/tests/ui/error-codes/E0606.stderr
@@ -1,12 +1,26 @@
 error[E0606]: casting `&u8` as `u8` is invalid
-  --> $DIR/E0606.rs:2:5
+  --> $DIR/E0606.rs:2:14
    |
-LL |     &0u8 as u8;
-   |     ----^^^^^^
-   |     |
-   |     cannot cast `&u8` as `u8`
-   |     help: dereference the expression: `*&0u8`
+LL |     let x = &(&0u8 as u8);
+   |              ^^^^^^^^^^^^
+   |
+help: remove the unneeded borrow
+   |
+LL -     let x = &(&0u8 as u8);
+LL +     let x = &(0u8 as u8);
+   |
+
+error[E0606]: casting `&u8` as `u8` is invalid
+  --> $DIR/E0606.rs:3:5
+   |
+LL |     x as u8;
+   |     ^^^^^^^
+   |
+help: dereference the expression
+   |
+LL |     *x as u8;
+   |     +
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0606`.
diff --git a/tests/ui/error-festival.stderr b/tests/ui/error-festival.stderr
index fe9956b70bd..e8ee1d96942 100644
--- a/tests/ui/error-festival.stderr
+++ b/tests/ui/error-festival.stderr
@@ -69,10 +69,12 @@ error[E0606]: casting `&u8` as `u32` is invalid
   --> $DIR/error-festival.rs:37:18
    |
 LL |     let y: u32 = x as u32;
-   |                  -^^^^^^^
-   |                  |
-   |                  cannot cast `&u8` as `u32`
-   |                  help: dereference the expression: `*x`
+   |                  ^^^^^^^^
+   |
+help: dereference the expression
+   |
+LL |     let y: u32 = *x as u32;
+   |                  +
 
 error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
   --> $DIR/error-festival.rs:41:5
diff --git a/tests/ui/mismatched_types/cast-rfc0401.stderr b/tests/ui/mismatched_types/cast-rfc0401.stderr
index eab8e8e80c4..2a36a352c73 100644
--- a/tests/ui/mismatched_types/cast-rfc0401.stderr
+++ b/tests/ui/mismatched_types/cast-rfc0401.stderr
@@ -243,10 +243,12 @@ error[E0606]: casting `&{float}` as `f32` is invalid
   --> $DIR/cast-rfc0401.rs:71:30
    |
 LL |     vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
-   |                              -^^^^^^^
-   |                              |
-   |                              cannot cast `&{float}` as `f32`
-   |                              help: dereference the expression: `*s`
+   |                              ^^^^^^^^
+   |
+help: dereference the expression
+   |
+LL |     vec![0.0].iter().map(|s| *s as f32).collect::<Vec<f32>>();
+   |                              +
 
 error: aborting due to 34 previous errors
 
diff --git a/tests/ui/parser/recover-unticked-labels.fixed b/tests/ui/parser/recover-unticked-labels.fixed
new file mode 100644
index 00000000000..159d995b8da
--- /dev/null
+++ b/tests/ui/parser/recover-unticked-labels.fixed
@@ -0,0 +1,7 @@
+// run-rustfix
+
+fn main() {
+    'label: loop { break 'label };    //~ error: cannot find value `label` in this scope
+    'label: loop { break 'label 0 };  //~ error: expected a label, found an identifier
+    'label: loop { continue 'label }; //~ error: expected a label, found an identifier
+}
diff --git a/tests/ui/parser/recover-unticked-labels.rs b/tests/ui/parser/recover-unticked-labels.rs
new file mode 100644
index 00000000000..56034de6844
--- /dev/null
+++ b/tests/ui/parser/recover-unticked-labels.rs
@@ -0,0 +1,7 @@
+// run-rustfix
+
+fn main() {
+    'label: loop { break label };    //~ error: cannot find value `label` in this scope
+    'label: loop { break label 0 };  //~ error: expected a label, found an identifier
+    'label: loop { continue label }; //~ error: expected a label, found an identifier
+}
diff --git a/tests/ui/parser/recover-unticked-labels.stderr b/tests/ui/parser/recover-unticked-labels.stderr
new file mode 100644
index 00000000000..c115dffb10e
--- /dev/null
+++ b/tests/ui/parser/recover-unticked-labels.stderr
@@ -0,0 +1,25 @@
+error: expected a label, found an identifier
+  --> $DIR/recover-unticked-labels.rs:5:26
+   |
+LL |     'label: loop { break label 0 };
+   |                          ^^^^^ help: labels start with a tick: `'label`
+
+error: expected a label, found an identifier
+  --> $DIR/recover-unticked-labels.rs:6:29
+   |
+LL |     'label: loop { continue label };
+   |                             ^^^^^ help: labels start with a tick: `'label`
+
+error[E0425]: cannot find value `label` in this scope
+  --> $DIR/recover-unticked-labels.rs:4:26
+   |
+LL |     'label: loop { break label };
+   |     ------               ^^^^^
+   |     |                    |
+   |     |                    not found in this scope
+   |     |                    help: use the similarly named label: `'label`
+   |     a label with a similar name exists
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/parser/unicode-chars.rs b/tests/ui/parser/unicode-chars.rs
index f0122561f46..cd25c756689 100644
--- a/tests/ui/parser/unicode-chars.rs
+++ b/tests/ui/parser/unicode-chars.rs
@@ -6,4 +6,7 @@ fn main() {
     //~^ ERROR unknown start of token: \u{a0}
     //~^^ NOTE character appears 3 more times
     //~^^^ HELP Unicode character ' ' (No-Break Space) looks like ' ' (Space), but it is not
+    let _ = 1 ⩵ 2;
+    //~^ ERROR unknown start of token
+    //~^^ HELP Unicode character '⩵' (Two Consecutive Equals Signs) looks like '==' (Double Equals Sign), but it is not
 }
diff --git a/tests/ui/parser/unicode-chars.stderr b/tests/ui/parser/unicode-chars.stderr
index b1d4a0af711..086de5ec099 100644
--- a/tests/ui/parser/unicode-chars.stderr
+++ b/tests/ui/parser/unicode-chars.stderr
@@ -21,5 +21,16 @@ help: Unicode character ' ' (No-Break Space) looks like ' ' (Space), but it is
 LL |         let x = 0;
    |     ++++
 
-error: aborting due to 2 previous errors
+error: unknown start of token: \u{2a75}
+  --> $DIR/unicode-chars.rs:9:15
+   |
+LL |     let _ = 1 ⩵ 2;
+   |               ^
+   |
+help: Unicode character '⩵' (Two Consecutive Equals Signs) looks like '==' (Double Equals Sign), but it is not
+   |
+LL |     let _ = 1 == 2;
+   |               ~~
+
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/issue-104817.rs b/tests/ui/type-alias-impl-trait/issue-104817.rs
new file mode 100644
index 00000000000..0d3bace4db1
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/issue-104817.rs
@@ -0,0 +1,19 @@
+#![feature(type_alias_impl_trait)]
+#![cfg_attr(specialized, feature(specialization))]
+#![allow(incomplete_features)]
+
+// revisions: stock specialized
+// [specialized]check-pass
+
+trait OpaqueTrait {}
+impl<T> OpaqueTrait for T {}
+type OpaqueType = impl OpaqueTrait;
+fn mk_opaque() -> OpaqueType {
+    || 0
+}
+trait AnotherTrait {}
+impl<T: Send> AnotherTrait for T {}
+impl AnotherTrait for OpaqueType {}
+//[stock]~^ conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr
new file mode 100644
index 00000000000..47bae8bd12b
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
+  --> $DIR/issue-104817.rs:16:1
+   |
+LL | impl<T: Send> AnotherTrait for T {}
+   | -------------------------------- first implementation here
+LL | impl AnotherTrait for OpaqueType {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
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 00000000000..b8fac45b76d
--- /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() { }
diff --git a/tests/ui/variance/variance-associated-consts.stderr b/tests/ui/variance/variance-associated-consts.stderr
index f9732d02cb2..4df2d8da3d6 100644
--- a/tests/ui/variance/variance-associated-consts.stderr
+++ b/tests/ui/variance/variance-associated-consts.stderr
@@ -1,4 +1,4 @@
-error[E0208]: [o]
+error: [o]
   --> $DIR/variance-associated-consts.rs:13:1
    |
 LL | struct Foo<T: Trait> {
@@ -6,4 +6,3 @@ LL | struct Foo<T: Trait> {
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0208`.
diff --git a/tests/ui/variance/variance-associated-types.stderr b/tests/ui/variance/variance-associated-types.stderr
index 5ce62884e1d..51f17c7c228 100644
--- a/tests/ui/variance/variance-associated-types.stderr
+++ b/tests/ui/variance/variance-associated-types.stderr
@@ -1,10 +1,10 @@
-error[E0208]: [-, +]
+error: [-, +]
   --> $DIR/variance-associated-types.rs:13:1
    |
 LL | struct Foo<'a, T : Trait<'a>> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [o, o]
+error: [o, o]
   --> $DIR/variance-associated-types.rs:18:1
    |
 LL | struct Bar<'a, T : Trait<'a>> {
@@ -12,4 +12,3 @@ LL | struct Bar<'a, T : Trait<'a>> {
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0208`.
diff --git a/tests/ui/variance/variance-object-types.stderr b/tests/ui/variance/variance-object-types.stderr
index 1c3c1a6d1f2..55a760425ee 100644
--- a/tests/ui/variance/variance-object-types.stderr
+++ b/tests/ui/variance/variance-object-types.stderr
@@ -1,4 +1,4 @@
-error[E0208]: [o]
+error: [o]
   --> $DIR/variance-object-types.rs:7:1
    |
 LL | struct Foo<'a> {
@@ -6,4 +6,3 @@ LL | struct Foo<'a> {
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0208`.
diff --git a/tests/ui/variance/variance-regions-direct.stderr b/tests/ui/variance/variance-regions-direct.stderr
index 27d69b6e825..eda02e9b03b 100644
--- a/tests/ui/variance/variance-regions-direct.stderr
+++ b/tests/ui/variance/variance-regions-direct.stderr
@@ -1,40 +1,40 @@
-error[E0208]: [-, -, -]
+error: [-, -, -]
   --> $DIR/variance-regions-direct.rs:9:1
    |
 LL | struct Test2<'a, 'b, 'c> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [+, +, +]
+error: [+, +, +]
   --> $DIR/variance-regions-direct.rs:18:1
    |
 LL | struct Test3<'a, 'b, 'c> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [-, o]
+error: [-, o]
   --> $DIR/variance-regions-direct.rs:27:1
    |
 LL | struct Test4<'a, 'b:'a> {
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [+, o]
+error: [+, o]
   --> $DIR/variance-regions-direct.rs:35:1
    |
 LL | struct Test5<'a, 'b:'a> {
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [-, o]
+error: [-, o]
   --> $DIR/variance-regions-direct.rs:45:1
    |
 LL | struct Test6<'a, 'b:'a> {
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [*]
+error: [*]
   --> $DIR/variance-regions-direct.rs:52:1
    |
 LL | struct Test7<'a> {
    | ^^^^^^^^^^^^^^^^
 
-error[E0208]: [+, -, o]
+error: [+, -, o]
   --> $DIR/variance-regions-direct.rs:59:1
    |
 LL | enum Test8<'a, 'b, 'c:'b> {
@@ -42,4 +42,3 @@ LL | enum Test8<'a, 'b, 'c:'b> {
 
 error: aborting due to 7 previous errors
 
-For more information about this error, try `rustc --explain E0208`.
diff --git a/tests/ui/variance/variance-regions-indirect.stderr b/tests/ui/variance/variance-regions-indirect.stderr
index 535e97db3fb..fa2f4d507f3 100644
--- a/tests/ui/variance/variance-regions-indirect.stderr
+++ b/tests/ui/variance/variance-regions-indirect.stderr
@@ -1,28 +1,28 @@
-error[E0208]: [+, -, o, *]
+error: [+, -, o, *]
   --> $DIR/variance-regions-indirect.rs:8:1
    |
 LL | enum Base<'a, 'b, 'c:'b, 'd> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [*, o, -, +]
+error: [*, o, -, +]
   --> $DIR/variance-regions-indirect.rs:15:1
    |
 LL | struct Derived1<'w, 'x:'y, 'y, 'z> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [o, o, *]
+error: [o, o, *]
   --> $DIR/variance-regions-indirect.rs:20:1
    |
 LL | struct Derived2<'a, 'b:'a, 'c> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [o, -, *]
+error: [o, -, *]
   --> $DIR/variance-regions-indirect.rs:25:1
    |
 LL | struct Derived3<'a:'b, 'b, 'c> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [+, -, o]
+error: [+, -, o]
   --> $DIR/variance-regions-indirect.rs:30:1
    |
 LL | struct Derived4<'a, 'b, 'c:'b> {
@@ -30,4 +30,3 @@ LL | struct Derived4<'a, 'b, 'c:'b> {
 
 error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0208`.
diff --git a/tests/ui/variance/variance-trait-bounds.stderr b/tests/ui/variance/variance-trait-bounds.stderr
index 3f6ca62a640..5a73e541c3a 100644
--- a/tests/ui/variance/variance-trait-bounds.stderr
+++ b/tests/ui/variance/variance-trait-bounds.stderr
@@ -1,22 +1,22 @@
-error[E0208]: [+, +]
+error: [+, +]
   --> $DIR/variance-trait-bounds.rs:16:1
    |
 LL | struct TestStruct<U,T:Setter<U>> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [*, +]
+error: [*, +]
   --> $DIR/variance-trait-bounds.rs:21:1
    |
 LL | enum TestEnum<U,T:Setter<U>> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [*, +]
+error: [*, +]
   --> $DIR/variance-trait-bounds.rs:26:1
    |
 LL | struct TestContraStruct<U,T:Setter<U>> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [*, +]
+error: [*, +]
   --> $DIR/variance-trait-bounds.rs:31:1
    |
 LL | struct TestBox<U,T:Getter<U>+Setter<U>> {
@@ -24,4 +24,3 @@ LL | struct TestBox<U,T:Getter<U>+Setter<U>> {
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0208`.
diff --git a/tests/ui/variance/variance-trait-object-bound.stderr b/tests/ui/variance/variance-trait-object-bound.stderr
index 9a2c924b96a..7c46b553f43 100644
--- a/tests/ui/variance/variance-trait-object-bound.stderr
+++ b/tests/ui/variance/variance-trait-object-bound.stderr
@@ -1,4 +1,4 @@
-error[E0208]: [-]
+error: [-]
   --> $DIR/variance-trait-object-bound.rs:14:1
    |
 LL | struct TOption<'a> {
@@ -6,4 +6,3 @@ LL | struct TOption<'a> {
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0208`.
diff --git a/tests/ui/variance/variance-types-bounds.stderr b/tests/ui/variance/variance-types-bounds.stderr
index 523763b8a07..bb816443476 100644
--- a/tests/ui/variance/variance-types-bounds.stderr
+++ b/tests/ui/variance/variance-types-bounds.stderr
@@ -1,28 +1,28 @@
-error[E0208]: [+, +]
+error: [+, +]
   --> $DIR/variance-types-bounds.rs:7:1
    |
 LL | struct TestImm<A, B> {
    | ^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [+, o]
+error: [+, o]
   --> $DIR/variance-types-bounds.rs:13:1
    |
 LL | struct TestMut<A, B:'static> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [+, o]
+error: [+, o]
   --> $DIR/variance-types-bounds.rs:19:1
    |
 LL | struct TestIndirect<A:'static, B:'static> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [o, o]
+error: [o, o]
   --> $DIR/variance-types-bounds.rs:24:1
    |
 LL | struct TestIndirect2<A:'static, B:'static> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [o, o]
+error: [o, o]
   --> $DIR/variance-types-bounds.rs:38:1
    |
 LL | struct TestObject<A, R> {
@@ -30,4 +30,3 @@ LL | struct TestObject<A, R> {
 
 error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0208`.
diff --git a/tests/ui/variance/variance-types.stderr b/tests/ui/variance/variance-types.stderr
index 5a5aaecffc5..9f7f1d9b0e3 100644
--- a/tests/ui/variance/variance-types.stderr
+++ b/tests/ui/variance/variance-types.stderr
@@ -1,34 +1,34 @@
-error[E0208]: [-, o, o]
+error: [-, o, o]
   --> $DIR/variance-types.rs:10:1
    |
 LL | struct InvariantMut<'a,A:'a,B:'a> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [o]
+error: [o]
   --> $DIR/variance-types.rs:15:1
    |
 LL | struct InvariantCell<A> {
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [o]
+error: [o]
   --> $DIR/variance-types.rs:20:1
    |
 LL | struct InvariantIndirect<A> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [+]
+error: [+]
   --> $DIR/variance-types.rs:25:1
    |
 LL | struct Covariant<A> {
    | ^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [-]
+error: [-]
   --> $DIR/variance-types.rs:30:1
    |
 LL | struct Contravariant<A> {
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0208]: [+, -, o]
+error: [+, -, o]
   --> $DIR/variance-types.rs:35:1
    |
 LL | enum Enum<A,B,C> {
@@ -36,4 +36,3 @@ LL | enum Enum<A,B,C> {
 
 error: aborting due to 6 previous errors
 
-For more information about this error, try `rustc --explain E0208`.