Add async bound modifier to enable async Fn bounds
This commit is contained in:
parent
cdaa12e3df
commit
0eb2adb7e8
12 changed files with 199 additions and 59 deletions
|
@ -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);
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -343,14 +343,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),
|
||||
)
|
||||
|
|
|
@ -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) }
|
||||
}
|
||||
|
||||
|
|
|
@ -6,12 +6,14 @@ 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 +26,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 +37,27 @@ 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 {
|
||||
if let Res::Def(DefKind::Trait, def_id) = res {
|
||||
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 {
|
||||
panic!();
|
||||
}
|
||||
} else {
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
|
||||
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 +96,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 +108,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 +153,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
ParenthesizedGenericArgs::Err,
|
||||
itctx,
|
||||
None,
|
||||
None,
|
||||
));
|
||||
let qpath = hir::QPath::TypeRelative(ty, hir_segment);
|
||||
|
||||
|
@ -166,6 +195,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
ParenthesizedGenericArgs::Err,
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
})),
|
||||
span: self.lower_span(p.span),
|
||||
|
@ -180,6 +210,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 +222,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 +394,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 +430,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 +479,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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -141,6 +141,7 @@ impl<'a> ExtCtxt<'a> {
|
|||
} else {
|
||||
ast::BoundConstness::Never
|
||||
},
|
||||
asyncness: ast::BoundAsyncness::Normal,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -8,14 +8,13 @@ use crate::errors::{
|
|||
};
|
||||
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,13 @@ 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 {
|
||||
BoundAsyncness::Normal
|
||||
};
|
||||
|
||||
let polarity = if self.eat(&token::Question) {
|
||||
BoundPolarity::Maybe(self.prev_token.span)
|
||||
} else if self.eat(&token::Not) {
|
||||
|
@ -889,7 +895,7 @@ impl<'a> Parser<'a> {
|
|||
BoundPolarity::Positive
|
||||
};
|
||||
|
||||
Ok(TraitBoundModifiers { constness, polarity })
|
||||
Ok(TraitBoundModifiers { constness, asyncness, polarity })
|
||||
}
|
||||
|
||||
/// Parses a type bound according to:
|
||||
|
|
|
@ -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",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
14
tests/ui/async-await/async-fn/sugar.rs
Normal file
14
tests/ui/async-await/async-fn/sugar.rs
Normal file
|
@ -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 });
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue