Add AsyncArgument
to AST.
This commit adds an `AsyncArgument` struct to the AST that contains the generated argument and statement that will be used in HIR lowering, name resolution and def collection.
This commit is contained in:
parent
41c6bb1096
commit
879abb1641
12 changed files with 171 additions and 53 deletions
|
@ -58,10 +58,10 @@ impl<'a> FnKind<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn header(&self) -> Option<FnHeader> {
|
||||
pub fn header(&self) -> Option<&FnHeader> {
|
||||
match *self {
|
||||
FnKind::ItemFn(_, _, header, _, _) => Some(header),
|
||||
FnKind::Method(_, sig, _, _) => Some(sig.header),
|
||||
FnKind::ItemFn(_, _, ref header, _, _) => Some(header),
|
||||
FnKind::Method(_, ref sig, _, _) => Some(&sig.header),
|
||||
FnKind::Closure(_) => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3000,13 +3000,13 @@ impl<'a> LoweringContext<'a> {
|
|||
fn lower_async_body(
|
||||
&mut self,
|
||||
decl: &FnDecl,
|
||||
asyncness: IsAsync,
|
||||
asyncness: &IsAsync,
|
||||
body: &Block,
|
||||
) -> hir::BodyId {
|
||||
self.lower_body(Some(decl), |this| {
|
||||
if let IsAsync::Async { closure_id, .. } = asyncness {
|
||||
let async_expr = this.make_async_expr(
|
||||
CaptureBy::Value, closure_id, None,
|
||||
CaptureBy::Value, *closure_id, None,
|
||||
|this| {
|
||||
let body = this.lower_block(body, false);
|
||||
this.expr_block(body, ThinVec::new())
|
||||
|
@ -3067,14 +3067,14 @@ impl<'a> LoweringContext<'a> {
|
|||
value
|
||||
)
|
||||
}
|
||||
ItemKind::Fn(ref decl, header, ref generics, ref body) => {
|
||||
ItemKind::Fn(ref decl, ref header, ref generics, ref body) => {
|
||||
let fn_def_id = self.resolver.definitions().local_def_id(id);
|
||||
self.with_new_scopes(|this| {
|
||||
// Note: we don't need to change the return type from `T` to
|
||||
// `impl Future<Output = T>` here because lower_body
|
||||
// only cares about the input argument patterns in the function
|
||||
// declaration (decl), not the return types.
|
||||
let body_id = this.lower_async_body(decl, header.asyncness.node, body);
|
||||
let body_id = this.lower_async_body(decl, &header.asyncness.node, body);
|
||||
|
||||
let (generics, fn_decl) = this.add_in_band_defs(
|
||||
generics,
|
||||
|
@ -3565,7 +3565,7 @@ impl<'a> LoweringContext<'a> {
|
|||
)
|
||||
}
|
||||
ImplItemKind::Method(ref sig, ref body) => {
|
||||
let body_id = self.lower_async_body(&sig.decl, sig.header.asyncness.node, body);
|
||||
let body_id = self.lower_async_body(&sig.decl, &sig.header.asyncness.node, body);
|
||||
let impl_trait_return_allow = !self.is_in_trait_impl;
|
||||
let (generics, sig) = self.lower_method_sig(
|
||||
&i.generics,
|
||||
|
@ -3767,7 +3767,7 @@ impl<'a> LoweringContext<'a> {
|
|||
impl_trait_return_allow: bool,
|
||||
is_async: Option<NodeId>,
|
||||
) -> (hir::Generics, hir::MethodSig) {
|
||||
let header = self.lower_fn_header(sig.header);
|
||||
let header = self.lower_fn_header(&sig.header);
|
||||
let (generics, decl) = self.add_in_band_defs(
|
||||
generics,
|
||||
fn_def_id,
|
||||
|
@ -3789,10 +3789,10 @@ impl<'a> LoweringContext<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
|
||||
fn lower_fn_header(&mut self, h: &FnHeader) -> hir::FnHeader {
|
||||
hir::FnHeader {
|
||||
unsafety: self.lower_unsafety(h.unsafety),
|
||||
asyncness: self.lower_asyncness(h.asyncness.node),
|
||||
asyncness: self.lower_asyncness(&h.asyncness.node),
|
||||
constness: self.lower_constness(h.constness),
|
||||
abi: h.abi,
|
||||
}
|
||||
|
@ -3812,7 +3812,7 @@ impl<'a> LoweringContext<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_asyncness(&mut self, a: IsAsync) -> hir::IsAsync {
|
||||
fn lower_asyncness(&mut self, a: &IsAsync) -> hir::IsAsync {
|
||||
match a {
|
||||
IsAsync::Async { .. } => hir::IsAsync::Async,
|
||||
IsAsync::NotAsync => hir::IsAsync::NotAsync,
|
||||
|
@ -4125,7 +4125,7 @@ impl<'a> LoweringContext<'a> {
|
|||
})
|
||||
}
|
||||
ExprKind::Closure(
|
||||
capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span
|
||||
capture_clause, ref asyncness, movability, ref decl, ref body, fn_decl_span
|
||||
) => {
|
||||
if let IsAsync::Async { closure_id, .. } = asyncness {
|
||||
let outer_decl = FnDecl {
|
||||
|
@ -4163,7 +4163,7 @@ impl<'a> LoweringContext<'a> {
|
|||
Some(&**ty)
|
||||
} else { None };
|
||||
let async_body = this.make_async_expr(
|
||||
capture_clause, closure_id, async_ret_ty,
|
||||
capture_clause, *closure_id, async_ret_ty,
|
||||
|this| {
|
||||
this.with_new_scopes(|this| this.lower_expr(body))
|
||||
});
|
||||
|
|
|
@ -68,7 +68,7 @@ impl<'a> DefCollector<'a> {
|
|||
id: NodeId,
|
||||
name: Name,
|
||||
span: Span,
|
||||
header: &FnHeader,
|
||||
header: &'a FnHeader,
|
||||
generics: &'a Generics,
|
||||
decl: &'a FnDecl,
|
||||
body: &'a Block,
|
||||
|
@ -77,6 +77,7 @@ impl<'a> DefCollector<'a> {
|
|||
IsAsync::Async {
|
||||
closure_id,
|
||||
return_impl_trait_id,
|
||||
..
|
||||
} => (closure_id, return_impl_trait_id),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
@ -290,7 +291,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
|||
|
||||
match expr.node {
|
||||
ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id),
|
||||
ExprKind::Closure(_, asyncness, ..) => {
|
||||
ExprKind::Closure(_, ref asyncness, ..) => {
|
||||
let closure_def = self.create_def(expr.id,
|
||||
DefPathData::ClosureExpr,
|
||||
REGULAR_SPACE,
|
||||
|
@ -300,7 +301,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
|||
// Async closures desugar to closures inside of closures, so
|
||||
// we must create two defs.
|
||||
if let IsAsync::Async { closure_id, .. } = asyncness {
|
||||
let async_def = self.create_def(closure_id,
|
||||
let async_def = self.create_def(*closure_id,
|
||||
DefPathData::ClosureExpr,
|
||||
REGULAR_SPACE,
|
||||
expr.span);
|
||||
|
|
|
@ -1328,6 +1328,22 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
|
||||
run_early_pass!(self, check_mac, mac);
|
||||
}
|
||||
|
||||
fn visit_fn_header(&mut self, header: &'a ast::FnHeader) {
|
||||
// Unlike in HIR lowering and name resolution, the `AsyncArgument` statements are not added
|
||||
// to the function body and the arguments do not replace those in the declaration. They are
|
||||
// still visited manually here so that buffered lints can be emitted.
|
||||
if let ast::IsAsync::Async { ref arguments, .. } = header.asyncness.node {
|
||||
for a in arguments {
|
||||
// Visit the argument..
|
||||
self.visit_pat(&a.arg.pat);
|
||||
self.visit_ty(&a.arg.ty);
|
||||
|
||||
// ..and the statement.
|
||||
self.visit_stmt(&a.stmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct LateLintPassObjects<'a> {
|
||||
|
|
|
@ -222,7 +222,7 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_trait_fn_not_async(&self, span: Span, asyncness: IsAsync) {
|
||||
fn check_trait_fn_not_async(&self, span: Span, asyncness: &IsAsync) {
|
||||
if asyncness.is_async() {
|
||||
struct_span_err!(self.session, span, E0706,
|
||||
"trait fns cannot be declared `async`").emit()
|
||||
|
@ -570,7 +570,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
self.invalid_visibility(&impl_item.vis, None);
|
||||
if let ImplItemKind::Method(ref sig, _) = impl_item.node {
|
||||
self.check_trait_fn_not_const(sig.header.constness);
|
||||
self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness.node);
|
||||
self.check_trait_fn_not_async(impl_item.span, &sig.header.asyncness.node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -642,7 +642,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
self.no_questions_in_bounds(bounds, "supertraits", true);
|
||||
for trait_item in trait_items {
|
||||
if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
|
||||
self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness.node);
|
||||
self.check_trait_fn_not_async(trait_item.span, &sig.header.asyncness.node);
|
||||
self.check_trait_fn_not_const(sig.header.constness);
|
||||
if block.is_none() {
|
||||
self.check_decl_no_pat(&sig.decl, |span, mut_ident| {
|
||||
|
|
|
@ -817,13 +817,13 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
|
|||
debug!("(resolving function) entering function");
|
||||
let (rib_kind, asyncness) = match function_kind {
|
||||
FnKind::ItemFn(_, ref header, ..) =>
|
||||
(FnItemRibKind, header.asyncness.node),
|
||||
(FnItemRibKind, &header.asyncness.node),
|
||||
FnKind::Method(_, ref sig, _, _) =>
|
||||
(TraitOrImplItemRibKind, sig.header.asyncness.node),
|
||||
(TraitOrImplItemRibKind, &sig.header.asyncness.node),
|
||||
FnKind::Closure(_) =>
|
||||
// Async closures aren't resolved through `visit_fn`-- they're
|
||||
// processed separately
|
||||
(ClosureRibKind(node_id), IsAsync::NotAsync),
|
||||
(ClosureRibKind(node_id), &IsAsync::NotAsync),
|
||||
};
|
||||
|
||||
// Create a value rib for the function.
|
||||
|
@ -836,16 +836,14 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
|
|||
let mut bindings_list = FxHashMap::default();
|
||||
for argument in &declaration.inputs {
|
||||
self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list);
|
||||
|
||||
self.visit_ty(&argument.ty);
|
||||
|
||||
debug!("(resolving function) recorded argument");
|
||||
}
|
||||
visit::walk_fn_ret_ty(self, &declaration.output);
|
||||
|
||||
// Resolve the function body, potentially inside the body of an async closure
|
||||
if let IsAsync::Async { closure_id, .. } = asyncness {
|
||||
let rib_kind = ClosureRibKind(closure_id);
|
||||
let rib_kind = ClosureRibKind(*closure_id);
|
||||
self.ribs[ValueNS].push(Rib::new(rib_kind));
|
||||
self.label_ribs.push(Rib::new(rib_kind));
|
||||
}
|
||||
|
|
|
@ -374,7 +374,7 @@ impl Sig for ast::Item {
|
|||
|
||||
Ok(extend_sig(ty, text, defs, vec![]))
|
||||
}
|
||||
ast::ItemKind::Fn(ref decl, header, ref generics, _) => {
|
||||
ast::ItemKind::Fn(ref decl, ref header, ref generics, _) => {
|
||||
let mut text = String::new();
|
||||
if header.constness.node == ast::Constness::Const {
|
||||
text.push_str("const ");
|
||||
|
|
|
@ -1849,18 +1849,35 @@ pub enum Unsafety {
|
|||
Normal,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct AsyncArgument {
|
||||
/// `__arg0`
|
||||
pub ident: Ident,
|
||||
/// `__arg0: <ty>` argument to replace existing function argument `<pat>: <ty>`.
|
||||
pub arg: Arg,
|
||||
/// `let <pat>: <ty> = __arg0;` statement to be inserted at the start of the block.
|
||||
pub stmt: Stmt,
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub enum IsAsync {
|
||||
Async {
|
||||
closure_id: NodeId,
|
||||
return_impl_trait_id: NodeId,
|
||||
/// This field stores the arguments and statements that are used in HIR lowering to
|
||||
/// ensure that `async fn` arguments are dropped at the correct time.
|
||||
///
|
||||
/// The argument and statements here are generated at parse time as they are required in
|
||||
/// both the hir lowering, def collection and name resolution and this stops them needing
|
||||
/// to be created in each place.
|
||||
arguments: Vec<AsyncArgument>,
|
||||
},
|
||||
NotAsync,
|
||||
}
|
||||
|
||||
impl IsAsync {
|
||||
pub fn is_async(self) -> bool {
|
||||
if let IsAsync::Async { .. } = self {
|
||||
pub fn is_async(&self) -> bool {
|
||||
if let IsAsync::Async { .. } = *self {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
@ -1868,12 +1885,12 @@ impl IsAsync {
|
|||
}
|
||||
|
||||
/// In ths case this is an `async` return, the `NodeId` for the generated `impl Trait` item.
|
||||
pub fn opt_return_id(self) -> Option<NodeId> {
|
||||
pub fn opt_return_id(&self) -> Option<NodeId> {
|
||||
match self {
|
||||
IsAsync::Async {
|
||||
return_impl_trait_id,
|
||||
..
|
||||
} => Some(return_impl_trait_id),
|
||||
} => Some(*return_impl_trait_id),
|
||||
IsAsync::NotAsync => None,
|
||||
}
|
||||
}
|
||||
|
@ -2213,7 +2230,7 @@ impl Item {
|
|||
///
|
||||
/// All the information between the visibility and the name of the function is
|
||||
/// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`).
|
||||
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct FnHeader {
|
||||
pub unsafety: Unsafety,
|
||||
pub asyncness: Spanned<IsAsync>,
|
||||
|
|
|
@ -102,6 +102,13 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> {
|
|||
fn remove(&mut self, id: ast::NodeId) -> AstFragment {
|
||||
self.expanded_fragments.remove(&id).unwrap()
|
||||
}
|
||||
|
||||
fn next_id(&mut self, id: &mut ast::NodeId) {
|
||||
if self.monotonic {
|
||||
assert_eq!(*id, ast::DUMMY_NODE_ID);
|
||||
*id = self.cx.resolver.next_node_id()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
|
||||
|
@ -183,9 +190,16 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
|
|||
noop_visit_block(block, self);
|
||||
|
||||
for stmt in block.stmts.iter_mut() {
|
||||
if self.monotonic {
|
||||
assert_eq!(stmt.id, ast::DUMMY_NODE_ID);
|
||||
stmt.id = self.cx.resolver.next_node_id();
|
||||
self.next_id(&mut stmt.id);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_asyncness(&mut self, a: &mut ast::IsAsync) {
|
||||
noop_visit_asyncness(a, self);
|
||||
|
||||
if let ast::IsAsync::Async { ref mut arguments, .. } = a {
|
||||
for argument in arguments.iter_mut() {
|
||||
self.next_id(&mut argument.stmt.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -679,9 +679,17 @@ pub fn noop_visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis:
|
|||
|
||||
pub fn noop_visit_asyncness<T: MutVisitor>(asyncness: &mut IsAsync, vis: &mut T) {
|
||||
match asyncness {
|
||||
IsAsync::Async { closure_id, return_impl_trait_id } => {
|
||||
IsAsync::Async { closure_id, return_impl_trait_id, ref mut arguments } => {
|
||||
vis.visit_id(closure_id);
|
||||
vis.visit_id(return_impl_trait_id);
|
||||
for AsyncArgument { ident, arg, stmt } in arguments.iter_mut() {
|
||||
vis.visit_ident(ident);
|
||||
vis.visit_arg(arg);
|
||||
visit_clobber(stmt, |stmt| {
|
||||
vis.flat_map_stmt(stmt)
|
||||
.expect_one("expected visitor to produce exactly one item")
|
||||
});
|
||||
}
|
||||
}
|
||||
IsAsync::NotAsync => {}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::ast::{AngleBracketedArgs, ParenthesizedArgs, AttrStyle, BareFnTy};
|
||||
use crate::ast::{AngleBracketedArgs, AsyncArgument, ParenthesizedArgs, AttrStyle, BareFnTy};
|
||||
use crate::ast::{GenericBound, TraitBoundModifier};
|
||||
use crate::ast::Unsafety;
|
||||
use crate::ast::{Mod, AnonConst, Arg, Arm, Guard, Attribute, BindingMode, TraitItemKind};
|
||||
|
@ -1517,6 +1517,7 @@ impl<'a> Parser<'a> {
|
|||
IsAsync::Async {
|
||||
closure_id: ast::DUMMY_NODE_ID,
|
||||
return_impl_trait_id: ast::DUMMY_NODE_ID,
|
||||
arguments: Vec::new(),
|
||||
}
|
||||
} else {
|
||||
IsAsync::NotAsync
|
||||
|
@ -1575,7 +1576,7 @@ impl<'a> Parser<'a> {
|
|||
// trait item macro.
|
||||
(keywords::Invalid.ident(), ast::TraitItemKind::Macro(mac), ast::Generics::default())
|
||||
} else {
|
||||
let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
|
||||
let (constness, unsafety, mut asyncness, abi) = self.parse_fn_front_matter()?;
|
||||
|
||||
let ident = self.parse_ident()?;
|
||||
let mut generics = self.parse_generics()?;
|
||||
|
@ -1589,6 +1590,7 @@ impl<'a> Parser<'a> {
|
|||
p.parse_arg_general(p.span.rust_2018(), true, false)
|
||||
})?;
|
||||
generics.where_clause = self.parse_where_clause()?;
|
||||
self.construct_async_arguments(&mut asyncness, &d);
|
||||
|
||||
let sig = ast::MethodSig {
|
||||
header: FnHeader {
|
||||
|
@ -6567,7 +6569,7 @@ impl<'a> Parser<'a> {
|
|||
/// Parses an item-position function declaration.
|
||||
fn parse_item_fn(&mut self,
|
||||
unsafety: Unsafety,
|
||||
asyncness: Spanned<IsAsync>,
|
||||
mut asyncness: Spanned<IsAsync>,
|
||||
constness: Spanned<Constness>,
|
||||
abi: Abi)
|
||||
-> PResult<'a, ItemInfo> {
|
||||
|
@ -6576,6 +6578,7 @@ impl<'a> Parser<'a> {
|
|||
let decl = self.parse_fn_decl(allow_c_variadic)?;
|
||||
generics.where_clause = self.parse_where_clause()?;
|
||||
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
self.construct_async_arguments(&mut asyncness, &decl);
|
||||
let header = FnHeader { unsafety, asyncness, constness, abi };
|
||||
Ok((ident, ItemKind::Fn(decl, header, generics, body), Some(inner_attrs)))
|
||||
}
|
||||
|
@ -6751,11 +6754,12 @@ impl<'a> Parser<'a> {
|
|||
Ok((keywords::Invalid.ident(), vec![], ast::Generics::default(),
|
||||
ast::ImplItemKind::Macro(mac)))
|
||||
} else {
|
||||
let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
|
||||
let (constness, unsafety, mut asyncness, abi) = self.parse_fn_front_matter()?;
|
||||
let ident = self.parse_ident()?;
|
||||
let mut generics = self.parse_generics()?;
|
||||
let decl = self.parse_fn_decl_with_self(|p| p.parse_arg())?;
|
||||
generics.where_clause = self.parse_where_clause()?;
|
||||
self.construct_async_arguments(&mut asyncness, &decl);
|
||||
*at_end = true;
|
||||
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
let header = ast::FnHeader { abi, unsafety, constness, asyncness };
|
||||
|
@ -8177,6 +8181,7 @@ impl<'a> Parser<'a> {
|
|||
respan(async_span, IsAsync::Async {
|
||||
closure_id: ast::DUMMY_NODE_ID,
|
||||
return_impl_trait_id: ast::DUMMY_NODE_ID,
|
||||
arguments: Vec::new(),
|
||||
}),
|
||||
respan(fn_span, Constness::NotConst),
|
||||
Abi::Rust)?;
|
||||
|
@ -8822,6 +8827,66 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// When lowering a `async fn` to the HIR, we need to move all of the arguments of the function
|
||||
/// into the generated closure so that they are dropped when the future is polled and not when
|
||||
/// it is created.
|
||||
///
|
||||
/// The arguments of the function are replaced in HIR lowering with the arguments created by
|
||||
/// this function and the statements created here are inserted at the top of the closure body.
|
||||
fn construct_async_arguments(&mut self, asyncness: &mut Spanned<IsAsync>, decl: &FnDecl) {
|
||||
if let IsAsync::Async { ref mut arguments, .. } = asyncness.node {
|
||||
for (index, input) in decl.inputs.iter().enumerate() {
|
||||
let id = ast::DUMMY_NODE_ID;
|
||||
let span = input.pat.span;
|
||||
|
||||
// Construct a name for our temporary argument.
|
||||
let name = format!("__arg{}", index);
|
||||
let ident = Ident::from_str(&name);
|
||||
|
||||
// Construct an argument representing `__argN: <ty>` to replace the argument of the
|
||||
// async function.
|
||||
let arg = Arg {
|
||||
ty: input.ty.clone(),
|
||||
id,
|
||||
pat: P(Pat {
|
||||
id,
|
||||
node: PatKind::Ident(
|
||||
BindingMode::ByValue(Mutability::Immutable), ident, None,
|
||||
),
|
||||
span,
|
||||
}),
|
||||
};
|
||||
|
||||
// Construct a `let <pat>: <ty> = __argN;` statement to insert at the top of the
|
||||
// async closure.
|
||||
let local = P(Local {
|
||||
pat: input.pat.clone(),
|
||||
ty: Some(P(Ty {
|
||||
id,
|
||||
node: input.ty.node.clone(),
|
||||
span: input.ty.span,
|
||||
})),
|
||||
init: Some(P(Expr {
|
||||
id,
|
||||
node: ExprKind::Path(None, ast::Path {
|
||||
span,
|
||||
segments: vec![PathSegment { ident, id, args: None }],
|
||||
}),
|
||||
span,
|
||||
attrs: ThinVec::new(),
|
||||
})),
|
||||
id,
|
||||
span,
|
||||
attrs: ThinVec::new(),
|
||||
source: LocalSource::AsyncFn,
|
||||
});
|
||||
let stmt = Stmt { id, node: StmtKind::Local(local), span, };
|
||||
|
||||
arguments.push(AsyncArgument { ident, arg, stmt });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, handler: &errors::Handler) {
|
||||
|
|
|
@ -372,7 +372,7 @@ pub fn vis_to_string(v: &ast::Visibility) -> String {
|
|||
}
|
||||
|
||||
pub fn fun_to_string(decl: &ast::FnDecl,
|
||||
header: ast::FnHeader,
|
||||
header: &ast::FnHeader,
|
||||
name: ast::Ident,
|
||||
generics: &ast::Generics)
|
||||
-> String {
|
||||
|
@ -1133,7 +1133,7 @@ impl<'a> State<'a> {
|
|||
match item.node {
|
||||
ast::ForeignItemKind::Fn(ref decl, ref generics) => {
|
||||
self.head("")?;
|
||||
self.print_fn(decl, ast::FnHeader::default(),
|
||||
self.print_fn(decl, &ast::FnHeader::default(),
|
||||
Some(item.ident),
|
||||
generics, &item.vis)?;
|
||||
self.end()?; // end head-ibox
|
||||
|
@ -1263,7 +1263,7 @@ impl<'a> State<'a> {
|
|||
self.s.word(";")?;
|
||||
self.end()?; // end the outer cbox
|
||||
}
|
||||
ast::ItemKind::Fn(ref decl, header, ref param_names, ref body) => {
|
||||
ast::ItemKind::Fn(ref decl, ref header, ref param_names, ref body) => {
|
||||
self.head("")?;
|
||||
self.print_fn(
|
||||
decl,
|
||||
|
@ -1615,7 +1615,7 @@ impl<'a> State<'a> {
|
|||
vis: &ast::Visibility)
|
||||
-> io::Result<()> {
|
||||
self.print_fn(&m.decl,
|
||||
m.header,
|
||||
&m.header,
|
||||
Some(ident),
|
||||
&generics,
|
||||
vis)
|
||||
|
@ -2213,7 +2213,7 @@ impl<'a> State<'a> {
|
|||
self.bclose_(expr.span, INDENT_UNIT)?;
|
||||
}
|
||||
ast::ExprKind::Closure(
|
||||
capture_clause, asyncness, movability, ref decl, ref body, _) => {
|
||||
capture_clause, ref asyncness, movability, ref decl, ref body, _) => {
|
||||
self.print_movability(movability)?;
|
||||
self.print_asyncness(asyncness)?;
|
||||
self.print_capture_clause(capture_clause)?;
|
||||
|
@ -2798,7 +2798,7 @@ impl<'a> State<'a> {
|
|||
|
||||
pub fn print_fn(&mut self,
|
||||
decl: &ast::FnDecl,
|
||||
header: ast::FnHeader,
|
||||
header: &ast::FnHeader,
|
||||
name: Option<ast::Ident>,
|
||||
generics: &ast::Generics,
|
||||
vis: &ast::Visibility) -> io::Result<()> {
|
||||
|
@ -2853,8 +2853,7 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn print_asyncness(&mut self, asyncness: ast::IsAsync)
|
||||
-> io::Result<()> {
|
||||
pub fn print_asyncness(&mut self, asyncness: &ast::IsAsync) -> io::Result<()> {
|
||||
if asyncness.is_async() {
|
||||
self.word_nbsp("async")?;
|
||||
}
|
||||
|
@ -3126,7 +3125,7 @@ impl<'a> State<'a> {
|
|||
span: syntax_pos::DUMMY_SP,
|
||||
};
|
||||
self.print_fn(decl,
|
||||
ast::FnHeader { unsafety, abi, ..ast::FnHeader::default() },
|
||||
&ast::FnHeader { unsafety, abi, ..ast::FnHeader::default() },
|
||||
name,
|
||||
&generics,
|
||||
&source_map::dummy_spanned(ast::VisibilityKind::Inherited))?;
|
||||
|
@ -3189,7 +3188,7 @@ impl<'a> State<'a> {
|
|||
}
|
||||
|
||||
pub fn print_fn_header_info(&mut self,
|
||||
header: ast::FnHeader,
|
||||
header: &ast::FnHeader,
|
||||
vis: &ast::Visibility) -> io::Result<()> {
|
||||
self.s.word(visibility_qualified(vis, ""))?;
|
||||
|
||||
|
@ -3198,7 +3197,7 @@ impl<'a> State<'a> {
|
|||
ast::Constness::Const => self.word_nbsp("const")?
|
||||
}
|
||||
|
||||
self.print_asyncness(header.asyncness.node)?;
|
||||
self.print_asyncness(&header.asyncness.node)?;
|
||||
self.print_unsafety(header.unsafety)?;
|
||||
|
||||
if header.abi != Abi::Rust {
|
||||
|
@ -3247,7 +3246,7 @@ mod tests {
|
|||
assert_eq!(
|
||||
fun_to_string(
|
||||
&decl,
|
||||
ast::FnHeader {
|
||||
&ast::FnHeader {
|
||||
unsafety: ast::Unsafety::Normal,
|
||||
constness: source_map::dummy_spanned(ast::Constness::NotConst),
|
||||
asyncness: source_map::dummy_spanned(ast::IsAsync::NotAsync),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue