Skip to content

Commit

Permalink
Rollup merge of rust-lang#63399 - estebank:vec-in-pat, r=Centril
Browse files Browse the repository at this point in the history
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 rust-lang#61933.
  • Loading branch information
Centril committed Aug 10, 2019
2 parents 45d089a + 75c5ad2 commit 9ece794
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 8 deletions.
15 changes: 9 additions & 6 deletions src/libsyntax/ext/expand.rs
Expand Up @@ -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::*;
Expand Down Expand Up @@ -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) => {
Expand All @@ -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)
Expand Down
40 changes: 39 additions & 1 deletion src/libsyntax/ext/tt/macro_rules.rs
Expand Up @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -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
}));

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/proc-macro/lifetimes.stderr
Expand Up @@ -2,7 +2,7 @@ error: expected type, found `'`
--> $DIR/lifetimes.rs:9:10
|
LL | type A = single_quote_alone!();
| ^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^ this macro call doesn't expand to a type

error: aborting due to previous error

8 changes: 8 additions & 0 deletions src/test/ui/suggestions/vec-macro-in-pattern.fixed
@@ -0,0 +1,8 @@
// run-rustfix
fn main() {
// everything after `.as_ref` should be suggested
match Some(vec![3]).as_ref().map(|v| v.as_slice()) {
Some([_x]) => (), //~ ERROR unexpected `(` after qualified path
_ => (),
}
}
8 changes: 8 additions & 0 deletions src/test/ui/suggestions/vec-macro-in-pattern.rs
@@ -0,0 +1,8 @@
// run-rustfix
fn main() {
// everything after `.as_ref` should be suggested
match Some(vec![3]).as_ref().map(|v| v.as_slice()) {
Some(vec![_x]) => (), //~ ERROR unexpected `(` after qualified path
_ => (),
}
}
15 changes: 15 additions & 0 deletions src/test/ui/suggestions/vec-macro-in-pattern.stderr
@@ -0,0 +1,15 @@
error: unexpected `(` after qualified path
--> $DIR/vec-macro-in-pattern.rs:5:14
|
LL | Some(vec![_x]) => (),
| ^^^^^^^^
| |
| unexpected `(` after qualified path
| in this macro invocation
| help: use a slice pattern here instead: `[_x]`
|
= 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)

error: aborting due to previous error

1 change: 1 addition & 0 deletions src/test/ui/type/ascription/issue-47666.stderr
Expand Up @@ -6,6 +6,7 @@ LL | let _ = Option:Some(vec![0, 1]);
| | |
| | expected type
| | in this macro invocation
| | this macro call doesn't expand to a type
| help: maybe write a path separator here: `::`
|
= note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
Expand Down

0 comments on commit 9ece794

Please sign in to comment.