mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-17 06:26:55 +00:00
Auto merge of #120392 - compiler-errors:async-bound-modifier, r=davidtwco,fmease
Introduce support for `async` bound modifier on `Fn*` traits Adds `async` to the list of `TraitBoundModifiers`, which instructs AST lowering to map the trait to an async flavor of the trait. For now, this is only supported for `Fn*` to `AsyncFn*`, and I expect that this manual mapping via lang items will be replaced with a better system in the future. The motivation for adding these bounds is to separate the users of async closures from the exact trait desugaring of their callable bounds. Instead of users needing to be concerned with the `AsyncFn` trait, they should be able to write `async Fn()` and it will desugar to whatever underlying trait we decide is best for the lowering of async closures. Note: rustfmt support can be done in the rustfmt repo after a subtree sync.
This commit is contained in:
commit
f3b9d47a46
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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 =
|
||||
|
@ -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),
|
||||
)
|
||||
|
@ -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) }
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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:
|
||||
|
@ -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/dyn-pos.rs
Normal file
14
tests/ui/async-await/async-fn/dyn-pos.rs
Normal file
@ -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() {}
|
87
tests/ui/async-await/async-fn/dyn-pos.stderr
Normal file
87
tests/ui/async-await/async-fn/dyn-pos.stderr
Normal file
@ -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`.
|
@ -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() {}
|
7
tests/ui/async-await/async-fn/edition-2015.rs
Normal file
7
tests/ui/async-await/async-fn/edition-2015.rs
Normal file
@ -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() {}
|
43
tests/ui/async-await/async-fn/edition-2015.stderr
Normal file
43
tests/ui/async-await/async-fn/edition-2015.stderr
Normal file
@ -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`.
|
8
tests/ui/async-await/async-fn/impl-header.rs
Normal file
8
tests/ui/async-await/async-fn/impl-header.rs
Normal file
@ -0,0 +1,8 @@
|
||||
// edition:2018
|
||||
|
||||
struct F;
|
||||
|
||||
impl async Fn<()> for F {}
|
||||
//~^ ERROR expected type, found keyword `async`
|
||||
|
||||
fn main() {}
|
8
tests/ui/async-await/async-fn/impl-header.stderr
Normal file
8
tests/ui/async-await/async-fn/impl-header.stderr
Normal file
@ -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
|
||||
|
15
tests/ui/async-await/async-fn/impl-trait.rs
Normal file
15
tests/ui/async-await/async-fn/impl-trait.rs
Normal file
@ -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() {}
|
7
tests/ui/async-await/async-fn/method-call-pos.rs
Normal file
7
tests/ui/async-await/async-fn/method-call-pos.rs
Normal file
@ -0,0 +1,7 @@
|
||||
// edition:2018
|
||||
|
||||
fn main() {
|
||||
<_ as async Fn()>(|| async {});
|
||||
//~^ ERROR expected identifier, found keyword `async`
|
||||
//~| ERROR expected one of
|
||||
}
|
14
tests/ui/async-await/async-fn/method-call-pos.stderr
Normal file
14
tests/ui/async-await/async-fn/method-call-pos.stderr
Normal file
@ -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
|
||||
|
13
tests/ui/async-await/async-fn/not-a-trait.rs
Normal file
13
tests/ui/async-await/async-fn/not-a-trait.rs
Normal file
@ -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() {}
|
16
tests/ui/async-await/async-fn/not-a-trait.stderr
Normal file
16
tests/ui/async-await/async-fn/not-a-trait.stderr
Normal file
@ -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`.
|
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 });
|
||||
}
|
10
tests/ui/async-await/async-fn/wrong-trait.rs
Normal file
10
tests/ui/async-await/async-fn/wrong-trait.rs
Normal file
@ -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() {}
|
8
tests/ui/async-await/async-fn/wrong-trait.stderr
Normal file
8
tests/ui/async-await/async-fn/wrong-trait.stderr
Normal file
@ -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
|
||||
|
@ -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…
Reference in New Issue
Block a user