From d0c78dd7aa692a9338b2085e8d227cde73d2a5f9 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 29 May 2019 04:10:49 +0300 Subject: [PATCH] syntax: revert `ast::AsyncArgument` and associated changes. Here follows the main reverts applied in order to make this commit: Revert "Rollup merge of #60676 - davidtwco:issue-60674, r=cramertj" This reverts commit 45b09453dbf120cc23d889435aac3ed7d2ec8eb7, reversing changes made to f6df1f6c30b469cb9e65c5453a0efa03cbb6005e. Revert "Rollup merge of #60437 - davidtwco:issue-60236, r=nikomatsakis" This reverts commit 16939a50ea440e72cb6ecefdaabb988addb1ec0e, reversing changes made to 12bf98155249783583a91863c5dccf9e346f1226. Revert "Rollup merge of #59823 - davidtwco:issue-54716, r=cramertj" This reverts commit 62d1574876f5531bce1b267e62dff520d7adcbbb, reversing changes made to 4eff8526a789e0dfa8b97f7dec91b7b5c18e8544. --- src/librustc/hir/lowering.rs | 187 +++++--------------------- src/librustc/hir/map/def_collector.rs | 41 ++---- src/librustc/lint/context.rs | 24 ---- src/librustc_passes/ast_validation.rs | 6 +- src/librustc_resolve/lib.rs | 72 +++------- src/librustc_save_analysis/sig.rs | 2 +- src/libsyntax/ast.rs | 55 +------- src/libsyntax/ext/build.rs | 6 +- src/libsyntax/ext/placeholders.rs | 23 +--- src/libsyntax/mut_visit.rs | 42 +----- src/libsyntax/parse/diagnostics.rs | 2 +- src/libsyntax/parse/parser.rs | 141 ++----------------- src/libsyntax/print/pprust.rs | 23 ++-- src/libsyntax/visit.rs | 3 - src/libsyntax_ext/deriving/debug.rs | 1 - 15 files changed, 108 insertions(+), 520 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 08fbd0d20d7..a61bdeb8299 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -465,32 +465,6 @@ impl<'a> LoweringContext<'a> { visit::walk_pat(self, p) } - fn visit_fn(&mut self, fk: visit::FnKind<'lcx>, fd: &'lcx FnDecl, s: Span, _: NodeId) { - if fk.header().map(|h| h.asyncness.node.is_async()).unwrap_or(false) { - // Don't visit the original pattern for async functions as it will be - // replaced. - for arg in &fd.inputs { - if let ArgSource::AsyncFn(pat) = &arg.source { self.visit_pat(pat); } - self.visit_ty(&arg.ty) - } - self.visit_fn_ret_ty(&fd.output); - - match fk { - visit::FnKind::ItemFn(_, decl, _, body) => { - self.visit_fn_header(decl); - self.visit_block(body) - }, - visit::FnKind::Method(_, sig, _, body) => { - self.visit_fn_header(&sig.header); - self.visit_block(body) - }, - visit::FnKind::Closure(body) => self.visit_expr(body), - } - } else { - visit::walk_fn(self, fk, fd, s) - } - } - fn visit_item(&mut self, item: &'lcx Item) { let hir_id = self.lctx.allocate_hir_id_counter(item.id); @@ -2266,17 +2240,10 @@ impl<'a> LoweringContext<'a> { init: l.init.as_ref().map(|e| P(self.lower_expr(e))), span: l.span, attrs: l.attrs.clone(), - source: self.lower_local_source(l.source), + source: hir::LocalSource::Normal, }, ids) } - fn lower_local_source(&mut self, ls: LocalSource) -> hir::LocalSource { - match ls { - LocalSource::Normal => hir::LocalSource::Normal, - LocalSource::AsyncFn => hir::LocalSource::AsyncFn, - } - } - fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability { match m { Mutability::Mutable => hir::MutMutable, @@ -2292,14 +2259,7 @@ impl<'a> LoweringContext<'a> { hir::Arg { hir_id: self.lower_node_id(arg.id), pat: self.lower_pat(&arg.pat), - source: self.lower_arg_source(&arg.source), - } - } - - fn lower_arg_source(&mut self, source: &ArgSource) -> hir::ArgSource { - match source { - ArgSource::Normal => hir::ArgSource::Normal, - ArgSource::AsyncFn(pat) => hir::ArgSource::AsyncFn(self.lower_pat(pat)), + source: hir::ArgSource::Normal, } } @@ -3028,44 +2988,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, ref arguments, .. } = asyncness { - let mut body = body.clone(); - - // Async function arguments are lowered into the closure body so that they are - // captured and so that the drop order matches the equivalent non-async functions. - // - // async fn foo(: , : , : ) { - // async move { - // } - // } - // - // // ...becomes... - // fn foo(__arg0: , __arg1: , __arg2: ) { - // async move { - // let __arg2 = __arg2; - // let = __arg2; - // let __arg1 = __arg1; - // let = __arg1; - // let __arg0 = __arg0; - // let = __arg0; - // } - // } - // - // If `` is a simple ident, then it is lowered to a single - // `let = ;` statement as an optimization. - for a in arguments.iter().rev() { - if let Some(pat_stmt) = a.pat_stmt.clone() { - body.stmts.insert(0, pat_stmt); - } - body.stmts.insert(0, a.move_stmt.clone()); - } - + if let IsAsync::Async { closure_id, .. } = asyncness { let async_expr = this.make_async_expr( - CaptureBy::Value, *closure_id, None, body.span, + CaptureBy::Value, closure_id, None, body.span, |this| { let body = this.lower_block(&body, false); this.expr_block(body, ThinVec::new()) @@ -3126,47 +3055,26 @@ impl<'a> LoweringContext<'a> { value ) } - ItemKind::Fn(ref decl, ref header, ref generics, ref body) => { + ItemKind::Fn(ref decl, 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` 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 (generics, fn_decl) = this.add_in_band_defs( + generics, + fn_def_id, + AnonymousLifetimeMode::PassThrough, + |this, idty| this.lower_fn_decl( + decl, + Some((fn_def_id, idty)), + true, + header.asyncness.node.opt_return_id() + ), + ); this.current_item = Some(ident.span); - let mut lower_fn = |decl: &FnDecl| { - // Note: we don't need to change the return type from `T` to - // `impl Future` 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 (generics, fn_decl) = this.add_in_band_defs( - generics, - fn_def_id, - AnonymousLifetimeMode::PassThrough, - |this, idty| this.lower_fn_decl( - &decl, - Some((fn_def_id, idty)), - true, - header.asyncness.node.opt_return_id() - ), - ); - - (body_id, generics, fn_decl) - }; - - let (body_id, generics, fn_decl) = if let IsAsync::Async { - arguments, .. - } = &header.asyncness.node { - let mut decl = decl.clone(); - // Replace the arguments of this async function with the generated - // arguments that will be moved into the closure. - for (i, a) in arguments.clone().drain(..).enumerate() { - if let Some(arg) = a.arg { - decl.inputs[i] = arg; - } - } - lower_fn(&decl) - } else { - lower_fn(decl) - }; hir::ItemKind::Fn( fn_decl, @@ -3638,36 +3546,15 @@ impl<'a> LoweringContext<'a> { ) } ImplItemKind::Method(ref sig, ref body) => { - let mut lower_method = |sig: &MethodSig| { - 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, - sig, - impl_item_def_id, - impl_trait_return_allow, - sig.header.asyncness.node.opt_return_id(), - ); - (body_id, generics, sig) - }; - - let (body_id, generics, sig) = if let IsAsync::Async { - ref arguments, .. - } = sig.header.asyncness.node { - let mut sig = sig.clone(); - // Replace the arguments of this async function with the generated - // arguments that will be moved into the closure. - for (i, a) in arguments.clone().drain(..).enumerate() { - if let Some(arg) = a.arg { - sig.decl.inputs[i] = arg; - } - } - lower_method(&sig) - } else { - lower_method(sig) - }; + 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, + sig, + impl_item_def_id, + impl_trait_return_allow, + sig.header.asyncness.node.opt_return_id(), + ); self.current_item = Some(i.span); (generics, hir::ImplItemKind::Method(sig, body_id)) @@ -3860,7 +3747,7 @@ impl<'a> LoweringContext<'a> { impl_trait_return_allow: bool, is_async: Option, ) -> (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, @@ -3882,10 +3769,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, } @@ -3905,7 +3792,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, @@ -4222,7 +4109,7 @@ impl<'a> LoweringContext<'a> { } ExprKind::Await(_origin, ref expr) => self.lower_await(e.span, expr), ExprKind::Closure( - capture_clause, ref asyncness, movability, ref decl, ref body, fn_decl_span + capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span ) => { if let IsAsync::Async { closure_id, .. } = asyncness { let outer_decl = FnDecl { @@ -4260,7 +4147,7 @@ impl<'a> LoweringContext<'a> { Some(&**ty) } else { None }; let async_body = this.make_async_expr( - capture_clause, *closure_id, async_ret_ty, body.span, + capture_clause, closure_id, async_ret_ty, body.span, |this| { this.with_new_scopes(|this| this.lower_expr(body)) }); diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index bde27c71f9a..a4484c81738 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -64,17 +64,16 @@ impl<'a> DefCollector<'a> { id: NodeId, name: Name, span: Span, - header: &'a FnHeader, + header: &FnHeader, generics: &'a Generics, decl: &'a FnDecl, body: &'a Block, ) { - let (closure_id, return_impl_trait_id, arguments) = match &header.asyncness.node { + let (closure_id, return_impl_trait_id) = match header.asyncness.node { IsAsync::Async { closure_id, return_impl_trait_id, - arguments, - } => (closure_id, return_impl_trait_id, arguments), + } => (closure_id, return_impl_trait_id), _ => unreachable!(), }; @@ -83,38 +82,16 @@ impl<'a> DefCollector<'a> { let fn_def_data = DefPathData::ValueNs(name.as_interned_str()); let fn_def = self.create_def(id, fn_def_data, span); return self.with_parent(fn_def, |this| { - this.create_def(*return_impl_trait_id, DefPathData::ImplTrait, span); + this.create_def(return_impl_trait_id, DefPathData::ImplTrait, span); visit::walk_generics(this, generics); - - // Walk the generated arguments for the `async fn`. - for (i, a) in arguments.iter().enumerate() { - use visit::Visitor; - if let Some(arg) = &a.arg { - this.visit_ty(&arg.ty); - } else { - this.visit_ty(&decl.inputs[i].ty); - } - } - - // We do not invoke `walk_fn_decl` as this will walk the arguments that are being - // replaced. - visit::walk_fn_ret_ty(this, &decl.output); + visit::walk_fn_decl(this, decl); let closure_def = this.create_def( - *closure_id, DefPathData::ClosureExpr, span, + closure_id, DefPathData::ClosureExpr, span, ); this.with_parent(closure_def, |this| { - use visit::Visitor; - // Walk each of the generated statements before the regular block body. - for a in arguments { - this.visit_stmt(&a.move_stmt); - if let Some(pat_stmt) = &a.pat_stmt { - this.visit_stmt(&pat_stmt); - } - } - - visit::walk_block(this, &body); + visit::walk_block(this, body); }) }) } @@ -302,7 +279,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { match expr.node { ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id), - ExprKind::Closure(_, ref asyncness, ..) => { + ExprKind::Closure(_, asyncness, ..) => { let closure_def = self.create_def(expr.id, DefPathData::ClosureExpr, expr.span); @@ -311,7 +288,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, expr.span); self.parent_def = Some(async_def); diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index c6583dd7a27..c5c6c4b9447 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -1335,30 +1335,6 @@ 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.. - if let Some(arg) = &a.arg { - self.visit_pat(&arg.pat); - if let ast::ArgSource::AsyncFn(pat) = &arg.source { - self.visit_pat(pat); - } - self.visit_ty(&arg.ty); - } - - // ..and the statement. - self.visit_stmt(&a.move_stmt); - if let Some(pat_stmt) = &a.pat_stmt { - self.visit_stmt(&pat_stmt); - } - } - } - } } struct LateLintPassObjects<'a> { diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 2afcbe8a151..89c4a9106a4 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -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() @@ -561,7 +561,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); } } } @@ -633,7 +633,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| { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 21e759ccc65..99abe69017d 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -855,15 +855,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { _: NodeId) { debug!("(resolving function) entering function"); - let (rib_kind, asyncness) = match function_kind { - FnKind::ItemFn(_, ref header, ..) => - (FnItemRibKind, &header.asyncness.node), - FnKind::Method(_, ref sig, _, _) => - (AssocItemRibKind, &sig.header.asyncness.node), - FnKind::Closure(_) => - // Async closures aren't resolved through `visit_fn`-- they're - // processed separately - (NormalRibKind, &IsAsync::NotAsync), + let rib_kind = match function_kind { + FnKind::ItemFn(..) => FnItemRibKind, + FnKind::Method(..) => AssocItemRibKind, + FnKind::Closure(_) => NormalRibKind, }; // Create a value rib for the function. @@ -874,45 +869,20 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { // Add each argument to the rib. let mut bindings_list = FxHashMap::default(); - let mut add_argument = |argument: &ast::Arg| { + 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"); - }; - - // Walk the generated async arguments if this is an `async fn`, otherwise walk the - // normal arguments. - if let IsAsync::Async { ref arguments, .. } = asyncness { - for (i, a) in arguments.iter().enumerate() { - if let Some(arg) = &a.arg { - add_argument(&arg); - } else { - add_argument(&declaration.inputs[i]); - } - } - } else { - for a in &declaration.inputs { add_argument(a); } } - visit::walk_fn_ret_ty(self, &declaration.output); // Resolve the function body, potentially inside the body of an async closure match function_kind { - FnKind::ItemFn(.., body) | FnKind::Method(.., body) => { - if let IsAsync::Async { ref arguments, .. } = asyncness { - let mut body = body.clone(); - // Insert the generated statements into the body before attempting to - // resolve names. - for a in arguments.iter().rev() { - if let Some(pat_stmt) = a.pat_stmt.clone() { - body.stmts.insert(0, pat_stmt); - } - body.stmts.insert(0, a.move_stmt.clone()); - } - self.visit_block(&body); - } else { - self.visit_block(body); - } + FnKind::ItemFn(.., body) | + FnKind::Method(.., body) => { + self.visit_block(body); } FnKind::Closure(body) => { self.visit_expr(body); @@ -4178,7 +4148,7 @@ impl<'a> Resolver<'a> { let add_module_candidates = |module: Module<'_>, names: &mut Vec| { for (&(ident, _), resolution) in module.resolutions.borrow().iter() { if let Some(binding) = resolution.borrow().binding { - if !ident.is_gensymed() && filter_fn(binding.res()) { + if filter_fn(binding.res()) { names.push(TypoSuggestion { candidate: ident.name, article: binding.res().article(), @@ -4196,7 +4166,7 @@ impl<'a> Resolver<'a> { for rib in self.ribs[ns].iter().rev() { // Locals and type parameters for (ident, &res) in &rib.bindings { - if !ident.is_gensymed() && filter_fn(res) { + if filter_fn(res) { names.push(TypoSuggestion { candidate: ident.name, article: res.article(), @@ -4226,7 +4196,7 @@ impl<'a> Resolver<'a> { }, ); - if !ident.is_gensymed() && filter_fn(crate_mod) { + if filter_fn(crate_mod) { Some(TypoSuggestion { candidate: ident.name, article: "a", @@ -4249,15 +4219,13 @@ impl<'a> Resolver<'a> { // Add primitive types to the mix if filter_fn(Res::PrimTy(Bool)) { names.extend( - self.primitive_type_table.primitive_types - .iter() - .map(|(name, _)| { - TypoSuggestion { - candidate: *name, - article: "a", - kind: "primitive type", - } - }) + self.primitive_type_table.primitive_types.iter().map(|(name, _)| { + TypoSuggestion { + candidate: *name, + article: "a", + kind: "primitive type", + } + }) ) } } else { diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 109863f8a56..db8b5eacd94 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -374,7 +374,7 @@ impl Sig for ast::Item { Ok(extend_sig(ty, text, defs, vec![])) } - ast::ItemKind::Fn(ref decl, ref header, ref generics, _) => { + ast::ItemKind::Fn(ref decl, header, ref generics, _) => { let mut text = String::new(); if header.constness.node == ast::Constness::Const { text.push_str("const "); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 75e83bd9f9c..b8a10d90c3c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -879,17 +879,6 @@ pub struct Local { pub id: NodeId, pub span: Span, pub attrs: ThinVec, - /// Origin of this local variable. - pub source: LocalSource, -} - -#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] -pub enum LocalSource { - /// Local was parsed from source. - Normal, - /// Within `ast::IsAsync::Async`, a local is generated that will contain the moved arguments - /// of an `async fn`. - AsyncFn, } /// An arm of a 'match'. @@ -1770,16 +1759,6 @@ pub struct Arg { pub ty: P, pub pat: P, pub id: NodeId, - pub source: ArgSource, -} - -/// The source of an argument in a function header. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum ArgSource { - /// Argument as written by the user. - Normal, - /// Argument from `async fn` lowering, contains the original binding pattern. - AsyncFn(P), } /// Alternative representation for `Arg`s describing `self` parameter of methods. @@ -1839,7 +1818,6 @@ impl Arg { }), ty, id: DUMMY_NODE_ID, - source: ArgSource::Normal, }; match eself.node { SelfKind::Explicit(ty, mutbl) => arg(mutbl, ty), @@ -1894,39 +1872,18 @@ pub enum Unsafety { Normal, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct AsyncArgument { - /// `__arg0` - pub ident: Ident, - /// `__arg0: ` argument to replace existing function argument `: `. Only if - /// argument is not a simple binding. - pub arg: Option, - /// `let __arg0 = __arg0;` statement to be inserted at the start of the block. - pub move_stmt: Stmt, - /// `let = __arg0;` statement to be inserted at the start of the block, after matching - /// move statement. Only if argument is not a simple binding. - pub pat_stmt: Option, -} - -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Copy, 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, }, 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 @@ -1934,12 +1891,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 { + pub fn opt_return_id(self) -> Option { match self { IsAsync::Async { return_impl_trait_id, .. - } => Some(*return_impl_trait_id), + } => Some(return_impl_trait_id), IsAsync::NotAsync => None, } } @@ -2279,7 +2236,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, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] pub struct FnHeader { pub unsafety: Unsafety, pub asyncness: Spanned, diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 9c0ffc1f6e8..47c79f8466a 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -516,7 +516,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> { id: ast::DUMMY_NODE_ID, span: sp, attrs: ThinVec::new(), - source: ast::LocalSource::Normal, }); ast::Stmt { id: ast::DUMMY_NODE_ID, @@ -545,7 +544,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> { id: ast::DUMMY_NODE_ID, span: sp, attrs: ThinVec::new(), - source: ast::LocalSource::Normal, }); ast::Stmt { id: ast::DUMMY_NODE_ID, @@ -563,7 +561,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> { id: ast::DUMMY_NODE_ID, span, attrs: ThinVec::new(), - source: ast::LocalSource::Normal, }); ast::Stmt { id: ast::DUMMY_NODE_ID, @@ -971,8 +968,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { ast::Arg { ty, pat: arg_pat, - id: ast::DUMMY_NODE_ID, - source: ast::ArgSource::Normal, + id: ast::DUMMY_NODE_ID } } diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs index 8f24d11cfd5..c56c156182b 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -101,13 +101,6 @@ 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> { @@ -189,19 +182,9 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> { noop_visit_block(block, self); for stmt in block.stmts.iter_mut() { - 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.move_stmt.id); - if let Some(ref mut pat_stmt) = &mut argument.pat_stmt { - self.next_id(&mut pat_stmt.id); - } + if self.monotonic { + assert_eq!(stmt.id, ast::DUMMY_NODE_ID); + stmt.id = self.cx.resolver.next_node_id(); } } } diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 0016c0d4d7e..75751309899 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -207,10 +207,6 @@ pub trait MutVisitor: Sized { noop_visit_local(l, self); } - fn visit_local_source(&mut self, l: &mut LocalSource) { - noop_visit_local_source(l, self); - } - fn visit_mac(&mut self, _mac: &mut Mac) { panic!("visit_mac disabled by default"); // N.B., see note about macros above. If you really want a visitor that @@ -234,10 +230,6 @@ pub trait MutVisitor: Sized { noop_visit_arg(a, self); } - fn visit_arg_source(&mut self, a: &mut ArgSource) { - noop_visit_arg_source(a, self); - } - fn visit_generics(&mut self, generics: &mut Generics) { noop_visit_generics(generics, self); } @@ -522,17 +514,13 @@ pub fn noop_visit_parenthesized_parameter_data(args: &mut Parenth } pub fn noop_visit_local(local: &mut P, vis: &mut T) { - let Local { id, pat, ty, init, span, attrs, source } = local.deref_mut(); + let Local { id, pat, ty, init, span, attrs } = local.deref_mut(); vis.visit_id(id); vis.visit_pat(pat); visit_opt(ty, |ty| vis.visit_ty(ty)); visit_opt(init, |init| vis.visit_expr(init)); vis.visit_span(span); visit_thin_attrs(attrs, vis); - vis.visit_local_source(source); -} - -pub fn noop_visit_local_source(_local_source: &mut LocalSource, _vis: &mut T) { } pub fn noop_visit_attribute(attr: &mut Attribute, vis: &mut T) { @@ -571,18 +559,10 @@ pub fn noop_visit_meta_item(mi: &mut MetaItem, vis: &mut T) { vis.visit_span(span); } -pub fn noop_visit_arg(Arg { id, pat, ty, source }: &mut Arg, vis: &mut T) { +pub fn noop_visit_arg(Arg { id, pat, ty }: &mut Arg, vis: &mut T) { vis.visit_id(id); vis.visit_pat(pat); vis.visit_ty(ty); - vis.visit_arg_source(source); -} - -pub fn noop_visit_arg_source(source: &mut ArgSource, vis: &mut T) { - match source { - ArgSource::Normal => {}, - ArgSource::AsyncFn(pat) => vis.visit_pat(pat), - } } pub fn noop_visit_tt(tt: &mut TokenTree, vis: &mut T) { @@ -690,25 +670,9 @@ pub fn noop_visit_interpolated(nt: &mut token::Nonterminal, vis: pub fn noop_visit_asyncness(asyncness: &mut IsAsync, vis: &mut T) { match asyncness { - IsAsync::Async { closure_id, return_impl_trait_id, ref mut arguments } => { + IsAsync::Async { closure_id, return_impl_trait_id } => { vis.visit_id(closure_id); vis.visit_id(return_impl_trait_id); - for AsyncArgument { ident, arg, pat_stmt, move_stmt } in arguments.iter_mut() { - vis.visit_ident(ident); - if let Some(arg) = arg { - vis.visit_arg(arg); - } - visit_clobber(move_stmt, |stmt| { - vis.flat_map_stmt(stmt) - .expect_one("expected visitor to produce exactly one item") - }); - visit_opt(pat_stmt, |stmt| { - visit_clobber(stmt, |stmt| { - vis.flat_map_stmt(stmt) - .expect_one("expected visitor to produce exactly one item") - }) - }); - } } IsAsync::NotAsync => {} } diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index af9092dd5b0..5df22f28797 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -27,7 +27,7 @@ crate fn dummy_arg(ident: Ident) -> Arg { span: ident.span, id: ast::DUMMY_NODE_ID }; - Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID, source: ast::ArgSource::Normal } + Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID } } pub enum Error { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f200d3ec8d5..d8891816c9e 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1,9 +1,9 @@ // ignore-tidy-filelength -use crate::ast::{AngleBracketedArgs, AsyncArgument, ParenthesizedArgs, AttrStyle, BareFnTy}; +use crate::ast::{AngleBracketedArgs, ParenthesizedArgs, AttrStyle, BareFnTy}; use crate::ast::{GenericBound, TraitBoundModifier}; use crate::ast::Unsafety; -use crate::ast::{Mod, AnonConst, Arg, ArgSource, Arm, Guard, Attribute, BindingMode, TraitItemKind}; +use crate::ast::{Mod, AnonConst, Arg, Arm, Guard, Attribute, BindingMode, TraitItemKind}; use crate::ast::Block; use crate::ast::{BlockCheckMode, CaptureBy, Movability}; use crate::ast::{Constness, Crate}; @@ -16,7 +16,7 @@ use crate::ast::{GenericParam, GenericParamKind}; use crate::ast::GenericArg; use crate::ast::{Ident, ImplItem, IsAsync, IsAuto, Item, ItemKind}; use crate::ast::{Label, Lifetime}; -use crate::ast::{Local, LocalSource}; +use crate::ast::Local; use crate::ast::MacStmtStyle; use crate::ast::{Mac, Mac_, MacDelimiter}; use crate::ast::{MutTy, Mutability}; @@ -51,7 +51,7 @@ use crate::parse::diagnostics::{Error, dummy_arg}; use errors::{Applicability, DiagnosticBuilder, DiagnosticId, FatalError}; use rustc_target::spec::abi::{self, Abi}; -use syntax_pos::{Span, BytePos, DUMMY_SP, FileName, hygiene::CompilerDesugaringKind}; +use syntax_pos::{Span, BytePos, DUMMY_SP, FileName}; use log::debug; use std::borrow::Cow; @@ -1126,7 +1126,6 @@ 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 @@ -1185,12 +1184,12 @@ impl<'a> Parser<'a> { // trait item macro. (Ident::invalid(), ast::TraitItemKind::Macro(mac), ast::Generics::default()) } else { - let (constness, unsafety, mut asyncness, abi) = self.parse_fn_front_matter()?; + let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?; let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; - let mut decl = self.parse_fn_decl_with_self(|p: &mut Parser<'a>| { + let decl = self.parse_fn_decl_with_self(|p: &mut Parser<'a>| { // This is somewhat dubious; We don't want to allow // argument names to be left off if there is a // definition... @@ -1199,7 +1198,6 @@ 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, &mut decl); let sig = ast::MethodSig { header: FnHeader { @@ -1563,7 +1561,7 @@ impl<'a> Parser<'a> { } }; - Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID, source: ast::ArgSource::Normal }) + Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID }) } /// Parses an argument in a lambda header (e.g., `|arg, arg|`). @@ -1581,8 +1579,7 @@ impl<'a> Parser<'a> { Ok(Arg { ty: t, pat, - id: ast::DUMMY_NODE_ID, - source: ast::ArgSource::Normal, + id: ast::DUMMY_NODE_ID }) } @@ -4213,7 +4210,6 @@ impl<'a> Parser<'a> { id: ast::DUMMY_NODE_ID, span: lo.to(hi), attrs, - source: LocalSource::Normal, })) } @@ -5660,16 +5656,15 @@ impl<'a> Parser<'a> { /// Parses an item-position function declaration. fn parse_item_fn(&mut self, unsafety: Unsafety, - mut asyncness: Spanned, + asyncness: Spanned, constness: Spanned, abi: Abi) -> PResult<'a, ItemInfo> { let (ident, mut generics) = self.parse_fn_header()?; let allow_c_variadic = abi == Abi::C && unsafety == Unsafety::Unsafe; - let mut decl = self.parse_fn_decl(allow_c_variadic)?; + 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, &mut decl); let header = FnHeader { unsafety, asyncness, constness, abi }; Ok((ident, ItemKind::Fn(decl, header, generics, body), Some(inner_attrs))) } @@ -5849,14 +5844,13 @@ impl<'a> Parser<'a> { Ok((Ident::invalid(), vec![], ast::Generics::default(), ast::ImplItemKind::Macro(mac))) } else { - let (constness, unsafety, mut asyncness, abi) = self.parse_fn_front_matter()?; + let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?; let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; - let mut decl = self.parse_fn_decl_with_self(|p| { + let decl = self.parse_fn_decl_with_self(|p| { p.parse_arg_general(true, true, false) })?; generics.where_clause = self.parse_where_clause()?; - self.construct_async_arguments(&mut asyncness, &mut decl); *at_end = true; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; let header = ast::FnHeader { abi, unsafety, constness, asyncness }; @@ -7218,7 +7212,6 @@ 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)?; @@ -7849,116 +7842,6 @@ impl<'a> Parser<'a> { Applicability::MaybeIncorrect, ).emit(); } - - /// 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, decl: &mut FnDecl) { - // FIXME(davidtwco): This function should really live in the HIR lowering but because - // the types constructed here need to be used in parts of resolve so that the correct - // locals are considered upvars, it is currently easier for it to live here in the parser, - // where it can be constructed once. - if let IsAsync::Async { ref mut arguments, .. } = asyncness.node { - for (index, input) in decl.inputs.iter_mut().enumerate() { - let id = ast::DUMMY_NODE_ID; - let span = input.pat.span; - let desugared_span = self.sess.source_map() - .mark_span_with_reason(CompilerDesugaringKind::Async, span, None); - - // Construct a name for our temporary argument. - let name = format!("__arg{}", index); - let ident = Ident::from_str(&name).gensym(); - - // Check if this is a ident pattern, if so, we can optimize and avoid adding a - // `let = __argN;` statement, instead just adding a `let = ;` - // statement. - let (binding_mode, ident, is_simple_pattern) = match input.pat.node { - PatKind::Ident(binding_mode @ BindingMode::ByValue(_), ident, _) => { - // Simple patterns like this don't have a generated argument, but they are - // moved into the closure with a statement, so any `mut` bindings on the - // argument will be unused. This binding mode can't be removed, because - // this would affect the input to procedural macros, but they can have - // their span marked as being the result of a compiler desugaring so - // that they aren't linted against. - input.pat.span = desugared_span; - - (binding_mode, ident, true) - } - _ => (BindingMode::ByValue(Mutability::Mutable), ident, false), - }; - - // Construct an argument representing `__argN: ` to replace the argument of the - // async function if it isn't a simple pattern. - let arg = if is_simple_pattern { - None - } else { - Some(Arg { - ty: input.ty.clone(), - id, - pat: P(Pat { - id, - node: PatKind::Ident( - BindingMode::ByValue(Mutability::Immutable), ident, None, - ), - span: desugared_span, - }), - source: ArgSource::AsyncFn(input.pat.clone()), - }) - }; - - // Construct a `let __argN = __argN;` statement to insert at the top of the - // async closure. This makes sure that the argument is captured by the closure and - // that the drop order is correct. - let move_local = Local { - pat: P(Pat { - id, - node: PatKind::Ident(binding_mode, ident, None), - span: desugared_span, - }), - // We explicitly do not specify the type for this statement. When the user's - // argument type is `impl Trait` then this would require the - // `impl_trait_in_bindings` feature to also be present for that same type to - // be valid in this binding. At the time of writing (13 Mar 19), - // `impl_trait_in_bindings` is not stable. - ty: None, - 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, - }; - - // Construct a `let = __argN;` statement to insert at the top of the - // async closure if this isn't a simple pattern. - let pat_stmt = if is_simple_pattern { - None - } else { - Some(Stmt { - id, - node: StmtKind::Local(P(Local { - pat: input.pat.clone(), - ..move_local.clone() - })), - span, - }) - }; - - let move_stmt = Stmt { id, node: StmtKind::Local(P(move_local)), span }; - arguments.push(AsyncArgument { ident, arg, pat_stmt, move_stmt }); - } - } - } } pub fn emit_unclosed_delims(unclosed_delims: &mut Vec, handler: &errors::Handler) { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index cf546332c2c..b81dc53ef68 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -357,7 +357,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 { @@ -1040,7 +1040,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 @@ -1170,7 +1170,7 @@ impl<'a> State<'a> { self.s.word(";")?; self.end()?; // end the outer cbox } - ast::ItemKind::Fn(ref decl, ref header, ref param_names, ref body) => { + ast::ItemKind::Fn(ref decl, header, ref param_names, ref body) => { self.head("")?; self.print_fn( decl, @@ -1522,7 +1522,7 @@ impl<'a> State<'a> { vis: &ast::Visibility) -> io::Result<()> { self.print_fn(&m.decl, - &m.header, + m.header, Some(ident), &generics, vis) @@ -2113,7 +2113,7 @@ impl<'a> State<'a> { self.bclose_(expr.span, INDENT_UNIT)?; } ast::ExprKind::Closure( - capture_clause, ref asyncness, movability, ref decl, ref body, _) => { + capture_clause, asyncness, movability, ref decl, ref body, _) => { self.print_movability(movability)?; self.print_asyncness(asyncness)?; self.print_capture_clause(capture_clause)?; @@ -2710,7 +2710,7 @@ impl<'a> State<'a> { pub fn print_fn(&mut self, decl: &ast::FnDecl, - header: &ast::FnHeader, + header: ast::FnHeader, name: Option, generics: &ast::Generics, vis: &ast::Visibility) -> io::Result<()> { @@ -2765,7 +2765,8 @@ 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")?; } @@ -3037,7 +3038,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))?; @@ -3100,7 +3101,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, ""))?; @@ -3109,7 +3110,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 { @@ -3158,7 +3159,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), diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 4e096d68235..eb516b5c7c6 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -544,9 +544,6 @@ pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FunctionR pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &'a FnDecl) { for argument in &function_declaration.inputs { visitor.visit_pat(&argument.pat); - if let ArgSource::AsyncFn(pat) = &argument.source { - visitor.visit_pat(pat); - } visitor.visit_ty(&argument.ty) } visitor.visit_fn_ret_ty(&function_declaration.output) diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index dec4c2dfc3b..44ddbb98809 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -129,7 +129,6 @@ fn stmt_let_undescore(cx: &mut ExtCtxt<'_>, sp: Span, expr: P) -> ast id: ast::DUMMY_NODE_ID, span: sp, attrs: ThinVec::new(), - source: ast::LocalSource::Normal, }); ast::Stmt { id: ast::DUMMY_NODE_ID,