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:
bors 2024-02-06 00:45:11 +00:00
commit f3b9d47a46
30 changed files with 516 additions and 62 deletions

View File

@ -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);

View File

@ -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

View File

@ -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,
}

View File

@ -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 =

View File

@ -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),
)

View File

@ -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) }
}

View File

@ -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
}
}
}

View File

@ -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());
}
}

View File

@ -141,6 +141,7 @@ impl<'a> ExtCtxt<'a> {
} else {
ast::BoundConstness::Never
},
asyncness: ast::BoundAsyncness::Normal,
},
)
}

View File

@ -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

View File

@ -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 {

View File

@ -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:

View File

@ -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",
}
}
}

View File

@ -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,

View 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() {}

View 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`.

View File

@ -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() {}

View 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() {}

View 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`.

View File

@ -0,0 +1,8 @@
// edition:2018
struct F;
impl async Fn<()> for F {}
//~^ ERROR expected type, found keyword `async`
fn main() {}

View 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

View 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() {}

View File

@ -0,0 +1,7 @@
// edition:2018
fn main() {
<_ as async Fn()>(|| async {});
//~^ ERROR expected identifier, found keyword `async`
//~| ERROR expected one of
}

View 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

View 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() {}

View 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`.

View 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 });
}

View 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() {}

View 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

View File

@ -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