diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-08-10 08:13:22 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-08-10 08:13:22 +0200 |
| commit | 9e613c74be901b86860aa2f6987228e6328e7a18 (patch) | |
| tree | 0ef9fcd21d37b54db2b07b855e8dcba28880616e /src/libsyntax | |
| parent | 5ed195baaa7d8753053c13a8bb932385becf64a6 (diff) | |
| parent | 75c5ad2e827a077c3738dee11d9e0dc99962f384 (diff) | |
| download | rust-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.rs | 15 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/macro_rules.rs | 40 |
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 })); |
