about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/hir/lowering.rs44
-rw-r--r--src/libsyntax/parse/parser.rs27
-rw-r--r--src/libsyntax/source_map.rs21
-rw-r--r--src/test/ui/async-await/auxiliary/issue-60674.rs12
-rw-r--r--src/test/ui/async-await/issue-60674.rs14
-rw-r--r--src/test/ui/async-await/issue-60674.stdout1
6 files changed, 76 insertions, 43 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 848e9ca58e5..4d5707560b0 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -50,7 +50,6 @@ use errors::Applicability;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::thin_vec::ThinVec;
-use rustc_data_structures::sync::Lrc;
 
 use std::collections::{BTreeSet, BTreeMap};
 use std::mem;
@@ -59,10 +58,10 @@ use syntax::attr;
 use syntax::ast;
 use syntax::ast::*;
 use syntax::errors;
-use syntax::ext::hygiene::{Mark, SyntaxContext};
+use syntax::ext::hygiene::Mark;
 use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::source_map::{self, respan, CompilerDesugaringKind, Spanned};
+use syntax::source_map::{respan, CompilerDesugaringKind, Spanned};
 use syntax::std_inject;
 use syntax::symbol::{keywords, Symbol};
 use syntax::tokenstream::{TokenStream, TokenTree};
@@ -854,27 +853,6 @@ impl<'a> LoweringContext<'a> {
         Ident::with_empty_ctxt(Symbol::gensym(s))
     }
 
-    /// Reuses the span but adds information like the kind of the desugaring and features that are
-    /// allowed inside this span.
-    fn mark_span_with_reason(
-        &self,
-        reason: CompilerDesugaringKind,
-        span: Span,
-        allow_internal_unstable: Option<Lrc<[Symbol]>>,
-    ) -> Span {
-        let mark = Mark::fresh(Mark::root());
-        mark.set_expn_info(source_map::ExpnInfo {
-            call_site: span,
-            def_site: Some(span),
-            format: source_map::CompilerDesugaring(reason),
-            allow_internal_unstable,
-            allow_internal_unsafe: false,
-            local_inner_macros: false,
-            edition: source_map::hygiene::default_edition(),
-        });
-        span.with_ctxt(SyntaxContext::empty().apply_mark(mark))
-    }
-
     fn with_anonymous_lifetime_mode<R>(
         &mut self,
         anonymous_lifetime_mode: AnonymousLifetimeMode,
@@ -1162,7 +1140,7 @@ impl<'a> LoweringContext<'a> {
             attrs: ThinVec::new(),
         };
 
-        let unstable_span = self.mark_span_with_reason(
+        let unstable_span = self.sess.source_map().mark_span_with_reason(
             CompilerDesugaringKind::Async,
             span,
             Some(vec![
@@ -1569,7 +1547,7 @@ impl<'a> LoweringContext<'a> {
         // desugaring that explicitly states that we don't want to track that.
         // Not tracking it makes lints in rustc and clippy very fragile as
         // frequently opened issues show.
-        let exist_ty_span = self.mark_span_with_reason(
+        let exist_ty_span = self.sess.source_map().mark_span_with_reason(
             CompilerDesugaringKind::ExistentialReturnType,
             span,
             None,
@@ -2443,7 +2421,7 @@ impl<'a> LoweringContext<'a> {
     ) -> hir::FunctionRetTy {
         let span = output.span();
 
-        let exist_ty_span = self.mark_span_with_reason(
+        let exist_ty_span = self.sess.source_map().mark_span_with_reason(
             CompilerDesugaringKind::Async,
             span,
             None,
@@ -4179,7 +4157,7 @@ impl<'a> LoweringContext<'a> {
             }),
             ExprKind::TryBlock(ref body) => {
                 self.with_catch_scope(body.id, |this| {
-                    let unstable_span = this.mark_span_with_reason(
+                    let unstable_span = this.sess.source_map().mark_span_with_reason(
                         CompilerDesugaringKind::TryBlock,
                         body.span,
                         Some(vec![
@@ -4612,7 +4590,7 @@ impl<'a> LoweringContext<'a> {
                 // expand <head>
                 let mut head = self.lower_expr(head);
                 let head_sp = head.span;
-                let desugared_span = self.mark_span_with_reason(
+                let desugared_span = self.sess.source_map().mark_span_with_reason(
                     CompilerDesugaringKind::ForLoop,
                     head_sp,
                     None,
@@ -4773,7 +4751,7 @@ impl<'a> LoweringContext<'a> {
                 //                 return Try::from_error(From::from(err)),
                 // }
 
-                let unstable_span = self.mark_span_with_reason(
+                let unstable_span = self.sess.source_map().mark_span_with_reason(
                     CompilerDesugaringKind::QuestionMark,
                     e.span,
                     Some(vec![
@@ -4781,7 +4759,7 @@ impl<'a> LoweringContext<'a> {
                     ].into()),
                 );
                 let try_span = self.sess.source_map().end_point(e.span);
-                let try_span = self.mark_span_with_reason(
+                let try_span = self.sess.source_map().mark_span_with_reason(
                     CompilerDesugaringKind::QuestionMark,
                     try_span,
                     Some(vec![
@@ -5566,12 +5544,12 @@ impl<'a> LoweringContext<'a> {
             );
             self.sess.abort_if_errors();
         }
-        let span = self.mark_span_with_reason(
+        let span = self.sess.source_map().mark_span_with_reason(
             CompilerDesugaringKind::Await,
             await_span,
             None,
         );
-        let gen_future_span = self.mark_span_with_reason(
+        let gen_future_span = self.sess.source_map().mark_span_with_reason(
             CompilerDesugaringKind::Await,
             await_span,
             Some(vec![Symbol::intern("gen_future")].into()),
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 });
             }
diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs
index 08abbf5e8a4..215618bd09c 100644
--- a/src/libsyntax/source_map.rs
+++ b/src/libsyntax/source_map.rs
@@ -930,6 +930,27 @@ impl SourceMap {
 
         None
     }
+
+    /// Reuses the span but adds information like the kind of the desugaring and features that are
+    /// allowed inside this span.
+    pub fn mark_span_with_reason(
+        &self,
+        reason: hygiene::CompilerDesugaringKind,
+        span: Span,
+        allow_internal_unstable: Option<Lrc<[symbol::Symbol]>>,
+    ) -> Span {
+        let mark = Mark::fresh(Mark::root());
+        mark.set_expn_info(ExpnInfo {
+            call_site: span,
+            def_site: Some(span),
+            format: CompilerDesugaring(reason),
+            allow_internal_unstable,
+            allow_internal_unsafe: false,
+            local_inner_macros: false,
+            edition: hygiene::default_edition(),
+        });
+        span.with_ctxt(SyntaxContext::empty().apply_mark(mark))
+    }
 }
 
 impl SourceMapper for SourceMap {
diff --git a/src/test/ui/async-await/auxiliary/issue-60674.rs b/src/test/ui/async-await/auxiliary/issue-60674.rs
new file mode 100644
index 00000000000..680c6e55e56
--- /dev/null
+++ b/src/test/ui/async-await/auxiliary/issue-60674.rs
@@ -0,0 +1,12 @@
+// force-host
+// no-prefer-dynamic
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn attr(_args: TokenStream, input: TokenStream) -> TokenStream {
+    println!("{}", input);
+    TokenStream::new()
+}
diff --git a/src/test/ui/async-await/issue-60674.rs b/src/test/ui/async-await/issue-60674.rs
new file mode 100644
index 00000000000..37e356e5baf
--- /dev/null
+++ b/src/test/ui/async-await/issue-60674.rs
@@ -0,0 +1,14 @@
+// aux-build:issue-60674.rs
+// compile-pass
+// edition:2018
+#![feature(async_await)]
+
+// This is a regression test that ensures that `mut` patterns are not lost when provided as input
+// to a proc macro.
+
+extern crate issue_60674;
+
+#[issue_60674::attr]
+async fn f(mut x: u8) {}
+
+fn main() {}
diff --git a/src/test/ui/async-await/issue-60674.stdout b/src/test/ui/async-await/issue-60674.stdout
new file mode 100644
index 00000000000..a93944db1c5
--- /dev/null
+++ b/src/test/ui/async-await/issue-60674.stdout
@@ -0,0 +1 @@
+async fn f(mut x: u8) { }