diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 4eb8169d0c3..296a570de6b 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -291,12 +291,16 @@ pub use crate::node_id::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
 #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
 pub struct TraitBoundModifiers {
     pub constness: BoundConstness,
+    pub asyncness: BoundAsyncness,
     pub polarity: BoundPolarity,
 }
 
 impl TraitBoundModifiers {
-    pub const NONE: Self =
-        Self { constness: BoundConstness::Never, polarity: BoundPolarity::Positive };
+    pub const NONE: Self = Self {
+        constness: BoundConstness::Never,
+        asyncness: BoundAsyncness::Normal,
+        polarity: BoundPolarity::Positive,
+    };
 }
 
 /// The AST represents all type param bounds as types.
@@ -2562,6 +2566,25 @@ impl BoundConstness {
     }
 }
 
+/// The asyncness of a trait bound.
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
+#[derive(HashStable_Generic)]
+pub enum BoundAsyncness {
+    /// `Type: Trait`
+    Normal,
+    /// `Type: async Trait`
+    Async(Span),
+}
+
+impl BoundAsyncness {
+    pub fn as_str(self) -> &'static str {
+        match self {
+            Self::Normal => "",
+            Self::Async(_) => "async",
+        }
+    }
+}
+
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub enum FnRetTy {
     /// Returns type is not specified.
@@ -3300,7 +3323,7 @@ mod size_asserts {
     static_assert_size!(ForeignItem, 96);
     static_assert_size!(ForeignItemKind, 24);
     static_assert_size!(GenericArg, 24);
-    static_assert_size!(GenericBound, 72);
+    static_assert_size!(GenericBound, 88);
     static_assert_size!(Generics, 40);
     static_assert_size!(Impl, 136);
     static_assert_size!(Item, 136);
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index 8615016cda5..e0dc227ca4c 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -11,6 +11,12 @@ ast_lowering_argument = argument
 ast_lowering_assoc_ty_parentheses =
     parenthesized generic arguments cannot be used in associated type constraints
 
+ast_lowering_async_bound_not_on_trait =
+    `async` bound modifier only allowed on trait, not `{$descr}`
+
+ast_lowering_async_bound_only_for_fn_traits =
+    `async` bound modifier only allowed on `Fn`/`FnMut`/`FnOnce` traits
+
 ast_lowering_async_coroutines_not_supported =
     `async` coroutines are not yet supported
 
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 51bb8a96fad..7658dfa5d5f 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -395,3 +395,18 @@ pub(crate) struct GenericParamDefaultInBinder {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(ast_lowering_async_bound_not_on_trait)]
+pub(crate) struct AsyncBoundNotOnTrait {
+    #[primary_span]
+    pub span: Span,
+    pub descr: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_lowering_async_bound_only_for_fn_traits)]
+pub(crate) struct AsyncBoundOnlyForFnTraits {
+    #[primary_span]
+    pub span: Span,
+}
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 0ad4a59c17e..3b00a84e67e 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -100,6 +100,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         ParenthesizedGenericArgs::Err,
                         &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                         None,
+                        // Method calls can't have bound modifiers
+                        None,
                     ));
                     let receiver = self.lower_expr(receiver);
                     let args =
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 6b772c1295f..987f74af0a4 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -340,14 +340,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 let itctx = ImplTraitContext::Universal;
                 let (generics, (trait_ref, lowered_ty)) =
                     self.lower_generics(ast_generics, *constness, id, &itctx, |this| {
-                        let constness = match *constness {
-                            Const::Yes(span) => BoundConstness::Maybe(span),
-                            Const::No => BoundConstness::Never,
+                        let modifiers = TraitBoundModifiers {
+                            constness: match *constness {
+                                Const::Yes(span) => BoundConstness::Maybe(span),
+                                Const::No => BoundConstness::Never,
+                            },
+                            asyncness: BoundAsyncness::Normal,
+                            // we don't use this in bound lowering
+                            polarity: BoundPolarity::Positive,
                         };
 
                         let trait_ref = trait_ref.as_ref().map(|trait_ref| {
                             this.lower_trait_ref(
-                                constness,
+                                modifiers,
                                 trait_ref,
                                 &ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
                             )
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index f26b1331ef3..c0b6922fc05 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -131,6 +131,7 @@ struct LoweringContext<'a, 'hir> {
     allow_gen_future: Lrc<[Symbol]>,
     allow_async_iterator: Lrc<[Symbol]>,
     allow_for_await: Lrc<[Symbol]>,
+    allow_async_fn_traits: Lrc<[Symbol]>,
 
     /// Mapping from generics `def_id`s to TAIT generics `def_id`s.
     /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic
@@ -176,6 +177,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 [sym::gen_future].into()
             },
             allow_for_await: [sym::async_iterator].into(),
+            allow_async_fn_traits: [sym::async_fn_traits].into(),
             // FIXME(gen_blocks): how does `closure_track_caller`/`async_fn_track_caller`
             // interact with `gen`/`async gen` blocks
             allow_async_iterator: [sym::gen_future, sym::async_iterator].into(),
@@ -1311,7 +1313,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         span: t.span,
                     },
                     itctx,
-                    ast::BoundConstness::Never,
+                    TraitBoundModifiers::NONE,
                 );
                 let bounds = this.arena.alloc_from_iter([bound]);
                 let lifetime_bound = this.elided_dyn_bound(t.span);
@@ -1426,7 +1428,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                                         itctx,
                                         // Still, don't pass along the constness here; we don't want to
                                         // synthesize any host effect args, it'd only cause problems.
-                                        ast::BoundConstness::Never,
+                                        TraitBoundModifiers {
+                                            constness: BoundConstness::Never,
+                                            ..*modifiers
+                                        },
                                     ))
                                 }
                                 BoundPolarity::Maybe(_) => None,
@@ -2019,7 +2024,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     ) -> hir::GenericBound<'hir> {
         match tpb {
             GenericBound::Trait(p, modifiers) => hir::GenericBound::Trait(
-                self.lower_poly_trait_ref(p, itctx, modifiers.constness.into()),
+                self.lower_poly_trait_ref(p, itctx, *modifiers),
                 self.lower_trait_bound_modifiers(*modifiers),
             ),
             GenericBound::Outlives(lifetime) => {
@@ -2192,7 +2197,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
     fn lower_trait_ref(
         &mut self,
-        constness: ast::BoundConstness,
+        modifiers: ast::TraitBoundModifiers,
         p: &TraitRef,
         itctx: &ImplTraitContext,
     ) -> hir::TraitRef<'hir> {
@@ -2202,7 +2207,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             &p.path,
             ParamMode::Explicit,
             itctx,
-            Some(constness),
+            Some(modifiers),
         ) {
             hir::QPath::Resolved(None, path) => path,
             qpath => panic!("lower_trait_ref: unexpected QPath `{qpath:?}`"),
@@ -2215,11 +2220,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         &mut self,
         p: &PolyTraitRef,
         itctx: &ImplTraitContext,
-        constness: ast::BoundConstness,
+        modifiers: ast::TraitBoundModifiers,
     ) -> hir::PolyTraitRef<'hir> {
         let bound_generic_params =
             self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
-        let trait_ref = self.lower_trait_ref(constness, &p.trait_ref, itctx);
+        let trait_ref = self.lower_trait_ref(modifiers, &p.trait_ref, itctx);
         hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
     }
 
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index c679ee56fcd..b58ac5c3dae 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -1,17 +1,21 @@
 use crate::ImplTraitPosition;
 
-use super::errors::{GenericTypeWithParentheses, UseAngleBrackets};
+use super::errors::{
+    AsyncBoundNotOnTrait, AsyncBoundOnlyForFnTraits, GenericTypeWithParentheses, UseAngleBrackets,
+};
 use super::ResolverAstLoweringExt;
 use super::{GenericArgsCtor, LifetimeRes, ParenthesizedGenericArgs};
 use super::{ImplTraitContext, LoweringContext, ParamMode};
 
 use rustc_ast::{self as ast, *};
+use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, PartialRes, Res};
+use rustc_hir::def_id::DefId;
 use rustc_hir::GenericArg;
 use rustc_middle::span_bug;
 use rustc_span::symbol::{kw, sym, Ident};
-use rustc_span::{BytePos, Span, DUMMY_SP};
+use rustc_span::{BytePos, DesugaringKind, Span, Symbol, DUMMY_SP};
 
 use smallvec::{smallvec, SmallVec};
 
@@ -24,8 +28,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         p: &Path,
         param_mode: ParamMode,
         itctx: &ImplTraitContext,
-        // constness of the impl/bound if this is a trait path
-        constness: Option<ast::BoundConstness>,
+        // modifiers of the impl/bound if this is a trait path
+        modifiers: Option<ast::TraitBoundModifiers>,
     ) -> hir::QPath<'hir> {
         let qself_position = qself.as_ref().map(|q| q.position);
         let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx));
@@ -35,10 +39,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let base_res = partial_res.base_res();
         let unresolved_segments = partial_res.unresolved_segments();
 
+        let mut res = self.lower_res(base_res);
+
+        // When we have an `async` kw on a bound, map the trait it resolves to.
+        let mut bound_modifier_allowed_features = None;
+        if let Some(TraitBoundModifiers { asyncness: BoundAsyncness::Async(_), .. }) = modifiers {
+            match res {
+                Res::Def(DefKind::Trait, def_id) => {
+                    if let Some((async_def_id, features)) = self.map_trait_to_async_trait(def_id) {
+                        res = Res::Def(DefKind::Trait, async_def_id);
+                        bound_modifier_allowed_features = Some(features);
+                    } else {
+                        self.dcx().emit_err(AsyncBoundOnlyForFnTraits { span: p.span });
+                    }
+                }
+                Res::Err => {
+                    // No additional error.
+                }
+                _ => {
+                    // This error isn't actually emitted AFAICT, but it's best to keep
+                    // it around in case the resolver doesn't always check the defkind
+                    // of an item or something.
+                    self.dcx().emit_err(AsyncBoundNotOnTrait { span: p.span, descr: res.descr() });
+                }
+            }
+        }
+
         let path_span_lo = p.span.shrink_to_lo();
         let proj_start = p.segments.len() - unresolved_segments;
         let path = self.arena.alloc(hir::Path {
-            res: self.lower_res(base_res),
+            res,
             segments: self.arena.alloc_from_iter(p.segments[..proj_start].iter().enumerate().map(
                 |(i, segment)| {
                     let param_mode = match (qself_position, param_mode) {
@@ -77,7 +107,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         parenthesized_generic_args,
                         itctx,
                         // if this is the last segment, add constness to the trait path
-                        if i == proj_start - 1 { constness } else { None },
+                        if i == proj_start - 1 { modifiers.map(|m| m.constness) } else { None },
+                        bound_modifier_allowed_features.clone(),
                     )
                 },
             )),
@@ -88,6 +119,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             ),
         });
 
+        if let Some(bound_modifier_allowed_features) = bound_modifier_allowed_features {
+            path.span = self.mark_span_with_reason(
+                DesugaringKind::BoundModifier,
+                path.span,
+                Some(bound_modifier_allowed_features),
+            );
+        }
+
         // Simple case, either no projections, or only fully-qualified.
         // E.g., `std::mem::size_of` or `<I as Iterator>::Item`.
         if unresolved_segments == 0 {
@@ -125,6 +164,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 ParenthesizedGenericArgs::Err,
                 itctx,
                 None,
+                None,
             ));
             let qpath = hir::QPath::TypeRelative(ty, hir_segment);
 
@@ -166,6 +206,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     ParenthesizedGenericArgs::Err,
                     &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                     None,
+                    None,
                 )
             })),
             span: self.lower_span(p.span),
@@ -180,6 +221,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         parenthesized_generic_args: ParenthesizedGenericArgs,
         itctx: &ImplTraitContext,
         constness: Option<ast::BoundConstness>,
+        // Additional features ungated with a bound modifier like `async`.
+        // This is passed down to the implicit associated type binding in
+        // parenthesized bounds.
+        bound_modifier_allowed_features: Option<Lrc<[Symbol]>>,
     ) -> hir::PathSegment<'hir> {
         debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment);
         let (mut generic_args, infer_args) = if let Some(generic_args) = segment.args.as_deref() {
@@ -188,9 +233,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
                 }
                 GenericArgs::Parenthesized(data) => match parenthesized_generic_args {
-                    ParenthesizedGenericArgs::ParenSugar => {
-                        self.lower_parenthesized_parameter_data(data, itctx)
-                    }
+                    ParenthesizedGenericArgs::ParenSugar => self
+                        .lower_parenthesized_parameter_data(
+                            data,
+                            itctx,
+                            bound_modifier_allowed_features,
+                        ),
                     ParenthesizedGenericArgs::Err => {
                         // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`
                         let sub = if !data.inputs.is_empty() {
@@ -357,6 +405,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         &mut self,
         data: &ParenthesizedArgs,
         itctx: &ImplTraitContext,
+        bound_modifier_allowed_features: Option<Lrc<[Symbol]>>,
     ) -> (GenericArgsCtor<'hir>, bool) {
         // Switch to `PassThrough` mode for anonymous lifetimes; this
         // means that we permit things like `&Ref<T>`, where `Ref` has
@@ -392,7 +441,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])),
         };
         let args = smallvec![GenericArg::Type(self.arena.alloc(self.ty_tup(*inputs_span, inputs)))];
-        let binding = self.assoc_ty_binding(sym::Output, output_ty.span, output_ty);
+
+        // If we have a bound like `async Fn() -> T`, make sure that we mark the
+        // `Output = T` associated type bound with the right feature gates.
+        let mut output_span = output_ty.span;
+        if let Some(bound_modifier_allowed_features) = bound_modifier_allowed_features {
+            output_span = self.mark_span_with_reason(
+                DesugaringKind::BoundModifier,
+                output_span,
+                Some(bound_modifier_allowed_features),
+            );
+        }
+        let binding = self.assoc_ty_binding(sym::Output, output_span, output_ty);
+
         (
             GenericArgsCtor {
                 args,
@@ -429,4 +490,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             kind,
         }
     }
+
+    /// When a bound is annotated with `async`, it signals to lowering that the trait
+    /// that the bound refers to should be mapped to the "async" flavor of the trait.
+    ///
+    /// This only needs to be done until we unify `AsyncFn` and `Fn` traits into one
+    /// that is generic over `async`ness, if that's ever possible, or modify the
+    /// lowering of `async Fn()` bounds to desugar to another trait like `LendingFn`.
+    fn map_trait_to_async_trait(&self, def_id: DefId) -> Option<(DefId, Lrc<[Symbol]>)> {
+        let lang_items = self.tcx.lang_items();
+        if Some(def_id) == lang_items.fn_trait() {
+            Some((lang_items.async_fn_trait()?, self.allow_async_fn_traits.clone()))
+        } else if Some(def_id) == lang_items.fn_mut_trait() {
+            Some((lang_items.async_fn_mut_trait()?, self.allow_async_fn_traits.clone()))
+        } else if Some(def_id) == lang_items.fn_once_trait() {
+            Some((lang_items.async_fn_once_trait()?, self.allow_async_fn_traits.clone()))
+        } else {
+            None
+        }
+    }
 }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index a6f6f0b29a0..731232bce65 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -8,6 +8,7 @@ mod item;
 use crate::pp::Breaks::{Consistent, Inconsistent};
 use crate::pp::{self, Breaks};
 use crate::pprust::state::expr::FixupContext;
+use ast::TraitBoundModifiers;
 use rustc_ast::attr::AttrIdGenerator;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, BinOpToken, CommentKind, Delimiter, Nonterminal, Token, TokenKind};
@@ -1590,18 +1591,28 @@ impl<'a> State<'a> {
             }
 
             match bound {
-                GenericBound::Trait(tref, modifier) => {
-                    match modifier.constness {
+                GenericBound::Trait(
+                    tref,
+                    TraitBoundModifiers { constness, asyncness, polarity },
+                ) => {
+                    match constness {
                         ast::BoundConstness::Never => {}
                         ast::BoundConstness::Always(_) | ast::BoundConstness::Maybe(_) => {
-                            self.word_space(modifier.constness.as_str());
+                            self.word_space(constness.as_str());
                         }
                     }
 
-                    match modifier.polarity {
+                    match asyncness {
+                        ast::BoundAsyncness::Normal => {}
+                        ast::BoundAsyncness::Async(_) => {
+                            self.word_space(asyncness.as_str());
+                        }
+                    }
+
+                    match polarity {
                         ast::BoundPolarity::Positive => {}
                         ast::BoundPolarity::Negative(_) | ast::BoundPolarity::Maybe(_) => {
-                            self.word(modifier.polarity.as_str());
+                            self.word(polarity.as_str());
                         }
                     }
 
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index f9bfebee12e..5879e025e7d 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -141,6 +141,7 @@ impl<'a> ExtCtxt<'a> {
                 } else {
                     ast::BoundConstness::Never
                 },
+                asyncness: ast::BoundAsyncness::Normal,
             },
         )
     }
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index aac8c0b3103..7c2ecf34c17 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -22,6 +22,8 @@ parse_associated_static_item_not_allowed = associated `static` items are not all
 
 parse_async_block_in_2015 = `async` blocks are only allowed in Rust 2018 or later
 
+parse_async_bound_modifier_in_2015 = `async` trait bounds are only allowed in Rust 2018 or later
+
 parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015
     .label = to use `async fn`, switch to Rust 2018 or later
 
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 4e4bf9bdad9..86a64d90deb 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -1588,6 +1588,15 @@ pub(crate) struct AsyncMoveBlockIn2015 {
     pub span: Span,
 }
 
+#[derive(Diagnostic)]
+#[diag(parse_async_bound_modifier_in_2015)]
+pub(crate) struct AsyncBoundModifierIn2015 {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub help: HelpUseLatestEdition,
+}
+
 #[derive(Diagnostic)]
 #[diag(parse_self_argument_pointer)]
 pub(crate) struct SelfArgumentPointer {
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index a4fb92c67ac..5fe54a536a7 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -3,19 +3,18 @@ use super::{Parser, PathStyle, TokenType};
 use crate::errors::{
     self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
     FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg,
-    InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, NestedCVariadicType,
-    ReturnTypesUseThinArrow,
+    HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
+    NestedCVariadicType, ReturnTypesUseThinArrow,
 };
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
 
-use ast::DUMMY_NODE_ID;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, Token, TokenKind};
 use rustc_ast::util::case::Case;
 use rustc_ast::{
-    self as ast, BareFnTy, BoundConstness, BoundPolarity, FnRetTy, GenericBound, GenericBounds,
-    GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef,
-    TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind,
+    self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, FnRetTy, GenericBound,
+    GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef,
+    TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, DUMMY_NODE_ID,
 };
 use rustc_errors::{Applicability, PResult};
 use rustc_span::symbol::{kw, sym, Ident};
@@ -880,6 +879,24 @@ impl<'a> Parser<'a> {
             BoundConstness::Never
         };
 
+        let asyncness = if self.token.span.at_least_rust_2018() && self.eat_keyword(kw::Async) {
+            self.sess.gated_spans.gate(sym::async_closure, self.prev_token.span);
+            BoundAsyncness::Async(self.prev_token.span)
+        } else if self.may_recover()
+            && self.token.span.is_rust_2015()
+            && self.is_kw_followed_by_ident(kw::Async)
+        {
+            self.bump(); // eat `async`
+            self.dcx().emit_err(errors::AsyncBoundModifierIn2015 {
+                span: self.prev_token.span,
+                help: HelpUseLatestEdition::new(),
+            });
+            self.sess.gated_spans.gate(sym::async_closure, self.prev_token.span);
+            BoundAsyncness::Async(self.prev_token.span)
+        } else {
+            BoundAsyncness::Normal
+        };
+
         let polarity = if self.eat(&token::Question) {
             BoundPolarity::Maybe(self.prev_token.span)
         } else if self.eat(&token::Not) {
@@ -889,7 +906,7 @@ impl<'a> Parser<'a> {
             BoundPolarity::Positive
         };
 
-        Ok(TraitBoundModifiers { constness, polarity })
+        Ok(TraitBoundModifiers { constness, asyncness, polarity })
     }
 
     /// Parses a type bound according to:
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 3d26efec5a6..527938daae4 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -1154,6 +1154,8 @@ pub enum DesugaringKind {
     Await,
     ForLoop,
     WhileLoop,
+    /// `async Fn()` bound modifier
+    BoundModifier,
 }
 
 impl DesugaringKind {
@@ -1169,6 +1171,7 @@ impl DesugaringKind {
             DesugaringKind::OpaqueTy => "`impl Trait`",
             DesugaringKind::ForLoop => "`for` loop",
             DesugaringKind::WhileLoop => "`while` loop",
+            DesugaringKind::BoundModifier => "trait bound modifier",
         }
     }
 }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index dbfc89c2d49..2dca9808ada 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -423,6 +423,7 @@ symbols! {
         async_fn_mut,
         async_fn_once,
         async_fn_track_caller,
+        async_fn_traits,
         async_for_loop,
         async_iterator,
         async_iterator_poll_next,
diff --git a/tests/ui/async-await/async-fn/dyn-pos.rs b/tests/ui/async-await/async-fn/dyn-pos.rs
new file mode 100644
index 00000000000..3201fb8dbf3
--- /dev/null
+++ b/tests/ui/async-await/async-fn/dyn-pos.rs
@@ -0,0 +1,14 @@
+// edition:2018
+
+#![feature(async_closure)]
+
+fn foo(x: &dyn async Fn()) {}
+//~^ ERROR the trait `AsyncFn` cannot be made into an object
+//~| ERROR the trait `AsyncFn` cannot be made into an object
+//~| ERROR the trait `AsyncFn` cannot be made into an object
+//~| ERROR the trait `AsyncFn` cannot be made into an object
+//~| ERROR the trait `AsyncFnMut` cannot be made into an object
+//~| ERROR the trait `AsyncFnMut` cannot be made into an object
+//~| ERROR the trait `AsyncFnMut` cannot be made into an object
+
+fn main() {}
diff --git a/tests/ui/async-await/async-fn/dyn-pos.stderr b/tests/ui/async-await/async-fn/dyn-pos.stderr
new file mode 100644
index 00000000000..c9323526516
--- /dev/null
+++ b/tests/ui/async-await/async-fn/dyn-pos.stderr
@@ -0,0 +1,87 @@
+error[E0038]: the trait `AsyncFn` cannot be made into an object
+  --> $DIR/dyn-pos.rs:5:16
+   |
+LL | fn foo(x: &dyn async Fn()) {}
+   |                ^^^^^^^^^^ `AsyncFn` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL
+   |
+   = note: the trait cannot be made into an object because it contains the generic associated type `CallFuture`
+
+error[E0038]: the trait `AsyncFnMut` cannot be made into an object
+  --> $DIR/dyn-pos.rs:5:16
+   |
+LL | fn foo(x: &dyn async Fn()) {}
+   |                ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL
+   |
+   = note: the trait cannot be made into an object because it contains the generic associated type `CallMutFuture`
+
+error[E0038]: the trait `AsyncFn` cannot be made into an object
+  --> $DIR/dyn-pos.rs:5:16
+   |
+LL | fn foo(x: &dyn async Fn()) {}
+   |                ^^^^^^^^^^ `AsyncFn` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL
+   |
+   = note: the trait cannot be made into an object because it contains the generic associated type `CallFuture`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0038]: the trait `AsyncFnMut` cannot be made into an object
+  --> $DIR/dyn-pos.rs:5:16
+   |
+LL | fn foo(x: &dyn async Fn()) {}
+   |                ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL
+   |
+   = note: the trait cannot be made into an object because it contains the generic associated type `CallMutFuture`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0038]: the trait `AsyncFn` cannot be made into an object
+  --> $DIR/dyn-pos.rs:5:16
+   |
+LL | fn foo(x: &dyn async Fn()) {}
+   |                ^^^^^^^^^^ `AsyncFn` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL
+   |
+   = note: the trait cannot be made into an object because it contains the generic associated type `CallFuture`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0038]: the trait `AsyncFnMut` cannot be made into an object
+  --> $DIR/dyn-pos.rs:5:16
+   |
+LL | fn foo(x: &dyn async Fn()) {}
+   |                ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL
+   |
+   = note: the trait cannot be made into an object because it contains the generic associated type `CallMutFuture`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0038]: the trait `AsyncFn` cannot be made into an object
+  --> $DIR/dyn-pos.rs:5:12
+   |
+LL | fn foo(x: &dyn async Fn()) {}
+   |            ^^^^^^^^^^^^^^ `AsyncFn` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL
+   |
+   = note: the trait cannot be made into an object because it contains the generic associated type `CallFuture`
+  ::: $SRC_DIR/core/src/ops/async_function.rs:LL:COL
+   |
+   = note: the trait cannot be made into an object because it contains the generic associated type `CallMutFuture`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs b/tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs
new file mode 100644
index 00000000000..6436787b665
--- /dev/null
+++ b/tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs
@@ -0,0 +1,10 @@
+// check-pass
+// Make sure that we don't eagerly recover `async ::Bound` in edition 2015.
+
+mod async {
+    pub trait Foo {}
+}
+
+fn test(x: impl async ::Foo) {}
+
+fn main() {}
diff --git a/tests/ui/async-await/async-fn/edition-2015.rs b/tests/ui/async-await/async-fn/edition-2015.rs
new file mode 100644
index 00000000000..83b9d415dda
--- /dev/null
+++ b/tests/ui/async-await/async-fn/edition-2015.rs
@@ -0,0 +1,7 @@
+fn foo(x: impl async Fn()) -> impl async Fn() { x }
+//~^ ERROR `async` trait bounds are only allowed in Rust 2018 or later
+//~| ERROR `async` trait bounds are only allowed in Rust 2018 or later
+//~| ERROR async closures are unstable
+//~| ERROR async closures are unstable
+
+fn main() {}
diff --git a/tests/ui/async-await/async-fn/edition-2015.stderr b/tests/ui/async-await/async-fn/edition-2015.stderr
new file mode 100644
index 00000000000..0029d53868d
--- /dev/null
+++ b/tests/ui/async-await/async-fn/edition-2015.stderr
@@ -0,0 +1,43 @@
+error: `async` trait bounds are only allowed in Rust 2018 or later
+  --> $DIR/edition-2015.rs:1:16
+   |
+LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
+   |                ^^^^^
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error: `async` trait bounds are only allowed in Rust 2018 or later
+  --> $DIR/edition-2015.rs:1:36
+   |
+LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
+   |                                    ^^^^^
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0658]: async closures are unstable
+  --> $DIR/edition-2015.rs:1:16
+   |
+LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
+   |                ^^^^^
+   |
+   = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
+   = help: add `#![feature(async_closure)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: to use an async block, remove the `||`: `async {`
+
+error[E0658]: async closures are unstable
+  --> $DIR/edition-2015.rs:1:36
+   |
+LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
+   |                                    ^^^^^
+   |
+   = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
+   = help: add `#![feature(async_closure)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: to use an async block, remove the `||`: `async {`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/async-await/async-fn/impl-header.rs b/tests/ui/async-await/async-fn/impl-header.rs
new file mode 100644
index 00000000000..fb1844384ae
--- /dev/null
+++ b/tests/ui/async-await/async-fn/impl-header.rs
@@ -0,0 +1,8 @@
+// edition:2018
+
+struct F;
+
+impl async Fn<()> for F {}
+//~^ ERROR expected type, found keyword `async`
+
+fn main() {}
diff --git a/tests/ui/async-await/async-fn/impl-header.stderr b/tests/ui/async-await/async-fn/impl-header.stderr
new file mode 100644
index 00000000000..02cb4326242
--- /dev/null
+++ b/tests/ui/async-await/async-fn/impl-header.stderr
@@ -0,0 +1,8 @@
+error: expected type, found keyword `async`
+  --> $DIR/impl-header.rs:5:6
+   |
+LL | impl async Fn<()> for F {}
+   |      ^^^^^ expected type
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/async-await/async-fn/impl-trait.rs b/tests/ui/async-await/async-fn/impl-trait.rs
new file mode 100644
index 00000000000..97f6696fe14
--- /dev/null
+++ b/tests/ui/async-await/async-fn/impl-trait.rs
@@ -0,0 +1,15 @@
+// edition:2018
+// check-pass
+
+#![feature(async_closure, type_alias_impl_trait)]
+
+type Tait = impl async Fn();
+fn tait() -> Tait {
+    || async {}
+}
+
+fn foo(x: impl async Fn()) -> impl async Fn() { x }
+
+fn param<T: async Fn()>() {}
+
+fn main() {}
diff --git a/tests/ui/async-await/async-fn/method-call-pos.rs b/tests/ui/async-await/async-fn/method-call-pos.rs
new file mode 100644
index 00000000000..aaa0245b986
--- /dev/null
+++ b/tests/ui/async-await/async-fn/method-call-pos.rs
@@ -0,0 +1,7 @@
+// edition:2018
+
+fn main() {
+    <_ as async Fn()>(|| async {});
+    //~^ ERROR expected identifier, found keyword `async`
+    //~| ERROR expected one of
+}
diff --git a/tests/ui/async-await/async-fn/method-call-pos.stderr b/tests/ui/async-await/async-fn/method-call-pos.stderr
new file mode 100644
index 00000000000..527515a1b44
--- /dev/null
+++ b/tests/ui/async-await/async-fn/method-call-pos.stderr
@@ -0,0 +1,14 @@
+error: expected identifier, found keyword `async`
+  --> $DIR/method-call-pos.rs:4:11
+   |
+LL |     <_ as async Fn()>(|| async {});
+   |           ^^^^^ expected identifier, found keyword
+
+error: expected one of `(`, `::`, `<`, or `>`, found `Fn`
+  --> $DIR/method-call-pos.rs:4:17
+   |
+LL |     <_ as async Fn()>(|| async {});
+   |                 ^^ expected one of `(`, `::`, `<`, or `>`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/async-await/async-fn/not-a-trait.rs b/tests/ui/async-await/async-fn/not-a-trait.rs
new file mode 100644
index 00000000000..a8fa21e5568
--- /dev/null
+++ b/tests/ui/async-await/async-fn/not-a-trait.rs
@@ -0,0 +1,13 @@
+// edition:2018
+
+#![feature(async_closure)]
+
+struct S;
+
+fn test(x: impl async S) {}
+//~^ ERROR expected trait, found struct `S`
+
+fn missing(x: impl async Missing) {}
+//~^ ERROR cannot find trait `Missing` in this scope
+
+fn main() {}
diff --git a/tests/ui/async-await/async-fn/not-a-trait.stderr b/tests/ui/async-await/async-fn/not-a-trait.stderr
new file mode 100644
index 00000000000..d49f7d7d2fc
--- /dev/null
+++ b/tests/ui/async-await/async-fn/not-a-trait.stderr
@@ -0,0 +1,16 @@
+error[E0404]: expected trait, found struct `S`
+  --> $DIR/not-a-trait.rs:7:23
+   |
+LL | fn test(x: impl async S) {}
+   |                       ^ not a trait
+
+error[E0405]: cannot find trait `Missing` in this scope
+  --> $DIR/not-a-trait.rs:10:26
+   |
+LL | fn missing(x: impl async Missing) {}
+   |                          ^^^^^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0404, E0405.
+For more information about an error, try `rustc --explain E0404`.
diff --git a/tests/ui/async-await/async-fn/sugar.rs b/tests/ui/async-await/async-fn/sugar.rs
new file mode 100644
index 00000000000..868fb799ae4
--- /dev/null
+++ b/tests/ui/async-await/async-fn/sugar.rs
@@ -0,0 +1,14 @@
+// edition: 2021
+// check-pass
+
+#![feature(async_closure)]
+
+async fn foo() {}
+
+async fn call_asyncly(f: impl async Fn(i32) -> i32) -> i32 {
+    f(1).await
+}
+
+fn main() {
+    let fut = call_asyncly(|x| async move { x + 1 });
+}
diff --git a/tests/ui/async-await/async-fn/wrong-trait.rs b/tests/ui/async-await/async-fn/wrong-trait.rs
new file mode 100644
index 00000000000..c431a362b1e
--- /dev/null
+++ b/tests/ui/async-await/async-fn/wrong-trait.rs
@@ -0,0 +1,10 @@
+// edition:2018
+
+#![feature(async_closure)]
+
+trait Foo {}
+
+fn test(x: impl async Foo) {}
+//~^ ERROR `async` bound modifier only allowed on `Fn`/`FnMut`/`FnOnce` traits
+
+fn main() {}
diff --git a/tests/ui/async-await/async-fn/wrong-trait.stderr b/tests/ui/async-await/async-fn/wrong-trait.stderr
new file mode 100644
index 00000000000..b39f5aa623c
--- /dev/null
+++ b/tests/ui/async-await/async-fn/wrong-trait.stderr
@@ -0,0 +1,8 @@
+error: `async` bound modifier only allowed on `Fn`/`FnMut`/`FnOnce` traits
+  --> $DIR/wrong-trait.rs:7:23
+   |
+LL | fn test(x: impl async Foo) {}
+   |                       ^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr
index 8b9ec30db63..2c21c25d7c7 100644
--- a/tests/ui/stats/hir-stats.stderr
+++ b/tests/ui/stats/hir-stats.stderr
@@ -5,8 +5,8 @@ ast-stats-1 GenericArgs               40 ( 0.6%)             1            40
 ast-stats-1 - AngleBracketed            40 ( 0.6%)             1
 ast-stats-1 Crate                     40 ( 0.6%)             1            40
 ast-stats-1 ExprField                 48 ( 0.7%)             1            48
-ast-stats-1 WherePredicate            56 ( 0.9%)             1            56
-ast-stats-1 - BoundPredicate            56 ( 0.9%)             1
+ast-stats-1 WherePredicate            56 ( 0.8%)             1            56
+ast-stats-1 - BoundPredicate            56 ( 0.8%)             1
 ast-stats-1 Attribute                 64 ( 1.0%)             2            32
 ast-stats-1 - Normal                    32 ( 0.5%)             1
 ast-stats-1 - DocComment                32 ( 0.5%)             1
@@ -22,38 +22,38 @@ ast-stats-1 - MacCall                   32 ( 0.5%)             1
 ast-stats-1 - Expr                      96 ( 1.5%)             3
 ast-stats-1 Param                    160 ( 2.4%)             4            40
 ast-stats-1 Block                    192 ( 2.9%)             6            32
-ast-stats-1 Variant                  208 ( 3.2%)             2           104
-ast-stats-1 GenericBound             288 ( 4.4%)             4            72
-ast-stats-1 - Trait                    288 ( 4.4%)             4
-ast-stats-1 AssocItem                352 ( 5.4%)             4            88
+ast-stats-1 Variant                  208 ( 3.1%)             2           104
+ast-stats-1 GenericBound             352 ( 5.3%)             4            88
+ast-stats-1 - Trait                    352 ( 5.3%)             4
+ast-stats-1 AssocItem                352 ( 5.3%)             4            88
 ast-stats-1 - Type                     176 ( 2.7%)             2
 ast-stats-1 - Fn                       176 ( 2.7%)             2
 ast-stats-1 GenericParam             480 ( 7.3%)             5            96
-ast-stats-1 Pat                      504 ( 7.7%)             7            72
+ast-stats-1 Pat                      504 ( 7.6%)             7            72
 ast-stats-1 - Struct                    72 ( 1.1%)             1
 ast-stats-1 - Wild                      72 ( 1.1%)             1
-ast-stats-1 - Ident                    360 ( 5.5%)             5
-ast-stats-1 Expr                     576 ( 8.8%)             8            72
+ast-stats-1 - Ident                    360 ( 5.4%)             5
+ast-stats-1 Expr                     576 ( 8.7%)             8            72
 ast-stats-1 - Path                      72 ( 1.1%)             1
 ast-stats-1 - Match                     72 ( 1.1%)             1
 ast-stats-1 - Struct                    72 ( 1.1%)             1
 ast-stats-1 - Lit                      144 ( 2.2%)             2
 ast-stats-1 - Block                    216 ( 3.3%)             3
-ast-stats-1 PathSegment              720 (11.0%)            30            24
-ast-stats-1 Ty                       896 (13.7%)            14            64
+ast-stats-1 PathSegment              720 (10.9%)            30            24
+ast-stats-1 Ty                       896 (13.5%)            14            64
 ast-stats-1 - Ptr                       64 ( 1.0%)             1
 ast-stats-1 - Ref                       64 ( 1.0%)             1
-ast-stats-1 - ImplicitSelf             128 ( 2.0%)             2
-ast-stats-1 - Path                     640 ( 9.8%)            10
-ast-stats-1 Item                   1_224 (18.7%)             9           136
+ast-stats-1 - ImplicitSelf             128 ( 1.9%)             2
+ast-stats-1 - Path                     640 ( 9.7%)            10
+ast-stats-1 Item                   1_224 (18.5%)             9           136
 ast-stats-1 - Trait                    136 ( 2.1%)             1
 ast-stats-1 - Enum                     136 ( 2.1%)             1
 ast-stats-1 - ForeignMod               136 ( 2.1%)             1
 ast-stats-1 - Impl                     136 ( 2.1%)             1
-ast-stats-1 - Fn                       272 ( 4.2%)             2
+ast-stats-1 - Fn                       272 ( 4.1%)             2
 ast-stats-1 - Use                      408 ( 6.2%)             3
 ast-stats-1 ----------------------------------------------------------------
-ast-stats-1 Total                  6_552
+ast-stats-1 Total                  6_616
 ast-stats-1
 ast-stats-2 POST EXPANSION AST STATS
 ast-stats-2 Name                Accumulated Size         Count     Item Size
@@ -81,39 +81,39 @@ ast-stats-2 - Expr                      96 ( 1.3%)             3
 ast-stats-2 Param                    160 ( 2.2%)             4            40
 ast-stats-2 Block                    192 ( 2.7%)             6            32
 ast-stats-2 Variant                  208 ( 2.9%)             2           104
-ast-stats-2 GenericBound             288 ( 4.0%)             4            72
-ast-stats-2 - Trait                    288 ( 4.0%)             4
+ast-stats-2 GenericBound             352 ( 4.9%)             4            88
+ast-stats-2 - Trait                    352 ( 4.9%)             4
 ast-stats-2 AssocItem                352 ( 4.9%)             4            88
-ast-stats-2 - Type                     176 ( 2.5%)             2
-ast-stats-2 - Fn                       176 ( 2.5%)             2
+ast-stats-2 - Type                     176 ( 2.4%)             2
+ast-stats-2 - Fn                       176 ( 2.4%)             2
 ast-stats-2 GenericParam             480 ( 6.7%)             5            96
 ast-stats-2 Pat                      504 ( 7.0%)             7            72
 ast-stats-2 - Struct                    72 ( 1.0%)             1
 ast-stats-2 - Wild                      72 ( 1.0%)             1
 ast-stats-2 - Ident                    360 ( 5.0%)             5
-ast-stats-2 Expr                     648 ( 9.1%)             9            72
+ast-stats-2 Expr                     648 ( 9.0%)             9            72
 ast-stats-2 - Path                      72 ( 1.0%)             1
 ast-stats-2 - Match                     72 ( 1.0%)             1
 ast-stats-2 - Struct                    72 ( 1.0%)             1
 ast-stats-2 - InlineAsm                 72 ( 1.0%)             1
 ast-stats-2 - Lit                      144 ( 2.0%)             2
 ast-stats-2 - Block                    216 ( 3.0%)             3
-ast-stats-2 PathSegment              792 (11.1%)            33            24
-ast-stats-2 Ty                       896 (12.5%)            14            64
+ast-stats-2 PathSegment              792 (11.0%)            33            24
+ast-stats-2 Ty                       896 (12.4%)            14            64
 ast-stats-2 - Ptr                       64 ( 0.9%)             1
 ast-stats-2 - Ref                       64 ( 0.9%)             1
 ast-stats-2 - ImplicitSelf             128 ( 1.8%)             2
 ast-stats-2 - Path                     640 ( 8.9%)            10
-ast-stats-2 Item                   1_496 (20.9%)            11           136
+ast-stats-2 Item                   1_496 (20.7%)            11           136
 ast-stats-2 - Trait                    136 ( 1.9%)             1
 ast-stats-2 - Enum                     136 ( 1.9%)             1
 ast-stats-2 - ExternCrate              136 ( 1.9%)             1
 ast-stats-2 - ForeignMod               136 ( 1.9%)             1
 ast-stats-2 - Impl                     136 ( 1.9%)             1
 ast-stats-2 - Fn                       272 ( 3.8%)             2
-ast-stats-2 - Use                      544 ( 7.6%)             4
+ast-stats-2 - Use                      544 ( 7.5%)             4
 ast-stats-2 ----------------------------------------------------------------
-ast-stats-2 Total                  7_152
+ast-stats-2 Total                  7_216
 ast-stats-2
 hir-stats HIR STATS
 hir-stats Name                Accumulated Size         Count     Item Size