about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-08-10 08:13:22 +0200
committerGitHub <noreply@github.com>2019-08-10 08:13:22 +0200
commit9e613c74be901b86860aa2f6987228e6328e7a18 (patch)
tree0ef9fcd21d37b54db2b07b855e8dcba28880616e /src/libsyntax
parent5ed195baaa7d8753053c13a8bb932385becf64a6 (diff)
parent75c5ad2e827a077c3738dee11d9e0dc99962f384 (diff)
downloadrust-9e613c74be901b86860aa2f6987228e6328e7a18.tar.gz
rust-9e613c74be901b86860aa2f6987228e6328e7a18.zip
Rollup merge of #63399 - estebank:vec-in-pat, r=Centril
More explicit diagnostic when using a `vec![]` in a pattern

```
error: unexpected `(` after qualified path
  --> $DIR/vec-macro-in-pattern.rs:3:14
   |
LL |         Some(vec![x]) => (),
   |              ^^^^^^^
   |              |
   |              unexpected `(` after qualified path
   |              in this macro invocation
   |              use a slice pattern here instead
   |
   = help: for more information, see https://doc.rust-lang.org/edition-guide/rust-2018/slice-patterns.html
   = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
```

Fix #61933.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/expand.rs15
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs40
2 files changed, 48 insertions, 7 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 964c81dd466..9a3195b1165 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -6,6 +6,7 @@ use crate::config::StripUnconfigured;
 use crate::ext::base::*;
 use crate::ext::proc_macro::collect_derives;
 use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnInfo, ExpnKind};
+use crate::ext::tt::macro_rules::annotate_err_with_kind;
 use crate::ext::placeholders::{placeholder, PlaceholderExpander};
 use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
 use crate::mut_visit::*;
@@ -686,12 +687,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         );
     }
 
-    fn parse_ast_fragment(&mut self,
-                          toks: TokenStream,
-                          kind: AstFragmentKind,
-                          path: &Path,
-                          span: Span)
-                          -> AstFragment {
+    fn parse_ast_fragment(
+        &mut self,
+        toks: TokenStream,
+        kind: AstFragmentKind,
+        path: &Path,
+        span: Span,
+    ) -> AstFragment {
         let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::<Vec<_>>());
         match parser.parse_ast_fragment(kind, false) {
             Ok(fragment) => {
@@ -700,6 +702,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             }
             Err(mut err) => {
                 err.set_span(span);
+                annotate_err_with_kind(&mut err, kind, span);
                 err.emit();
                 self.cx.trace_macros_diag();
                 kind.dummy(span)
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 7401f256412..b057a9ad44d 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -17,7 +17,7 @@ use crate::symbol::{kw, sym, Symbol};
 use crate::tokenstream::{DelimSpan, TokenStream, TokenTree};
 use crate::{ast, attr, attr::TransparencyError};
 
-use errors::FatalError;
+use errors::{DiagnosticBuilder, FatalError};
 use log::debug;
 use syntax_pos::Span;
 
@@ -43,6 +43,18 @@ pub struct ParserAnyMacro<'a> {
     arm_span: Span,
 }
 
+pub fn annotate_err_with_kind(err: &mut DiagnosticBuilder<'_>, kind: AstFragmentKind, span: Span) {
+    match kind {
+        AstFragmentKind::Ty => {
+            err.span_label(span, "this macro call doesn't expand to a type");
+        }
+        AstFragmentKind::Pat => {
+            err.span_label(span, "this macro call doesn't expand to a pattern");
+        }
+        _ => {}
+    };
+}
+
 impl<'a> ParserAnyMacro<'a> {
     pub fn make(mut self: Box<ParserAnyMacro<'a>>, kind: AstFragmentKind) -> AstFragment {
         let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self;
@@ -70,6 +82,32 @@ impl<'a> ParserAnyMacro<'a> {
             } else if !parser.sess.source_map().span_to_filename(parser.token.span).is_real() {
                 e.span_label(site_span, "in this macro invocation");
             }
+            match kind {
+                AstFragmentKind::Pat if macro_ident.name == sym::vec => {
+                    let mut suggestion = None;
+                    if let Ok(code) = parser.sess.source_map().span_to_snippet(site_span) {
+                        if let Some(bang) = code.find('!') {
+                            suggestion = Some(code[bang + 1..].to_string());
+                        }
+                    }
+                    if let Some(suggestion) = suggestion {
+                        e.span_suggestion(
+                            site_span,
+                            "use a slice pattern here instead",
+                            suggestion,
+                            Applicability::MachineApplicable,
+                        );
+                    } else {
+                        e.span_label(
+                            site_span,
+                            "use a slice pattern here instead",
+                        );
+                    }
+                    e.help("for more information, see https://doc.rust-lang.org/edition-guide/\
+                            rust-2018/slice-patterns.html");
+                }
+                _ => annotate_err_with_kind(&mut e, kind, site_span),
+            };
             e
         }));