about summary refs log tree commit diff
path: root/src/libsyntax/parse/parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
-rw-r--r--src/libsyntax/parse/parser.rs27
1 files changed, 17 insertions, 10 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 7b19bb760e0..d97d1e2f0f4 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -50,7 +50,10 @@ use crate::symbol::{Symbol, keywords};
 
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId, FatalError};
 use rustc_target::spec::abi::{self, Abi};
-use syntax_pos::{Span, MultiSpan, BytePos, FileName};
+use syntax_pos::{
+    Span, MultiSpan, BytePos, FileName,
+    hygiene::CompilerDesugaringKind,
+};
 use log::{debug, trace};
 
 use std::borrow::Cow;
@@ -8772,6 +8775,10 @@ impl<'a> Parser<'a> {
     /// 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: &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;
@@ -8786,6 +8793,15 @@ impl<'a> Parser<'a> {
                 // 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 = self.sess.source_map().mark_span_with_reason(
+                            CompilerDesugaringKind::Async, span, None);
+
                         (binding_mode, ident, true)
                     }
                     _ => (BindingMode::ByValue(Mutability::Mutable), ident, false),
@@ -8855,15 +8871,6 @@ impl<'a> Parser<'a> {
                     })
                 };
 
-                // Remove mutability from arguments. If this is not a simple pattern,
-                // those arguments are replaced by `__argN`, so there is no need to do this.
-                if let PatKind::Ident(BindingMode::ByValue(mutability @ Mutability::Mutable), ..) =
-                    &mut input.pat.node
-                {
-                    assert!(is_simple_pattern);
-                    *mutability = Mutability::Immutable;
-                }
-
                 let move_stmt = Stmt { id, node: StmtKind::Local(P(move_local)), span };
                 arguments.push(AsyncArgument { ident, arg, pat_stmt, move_stmt });
             }