mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-06 15:07:36 +00:00
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.
This commit is contained in:
commit
9e613c74be
@ -6,6 +6,7 @@ use crate::config::StripUnconfigured;
|
|||||||
use crate::ext::base::*;
|
use crate::ext::base::*;
|
||||||
use crate::ext::proc_macro::collect_derives;
|
use crate::ext::proc_macro::collect_derives;
|
||||||
use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnInfo, ExpnKind};
|
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::ext::placeholders::{placeholder, PlaceholderExpander};
|
||||||
use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
|
use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
|
||||||
use crate::mut_visit::*;
|
use crate::mut_visit::*;
|
||||||
@ -686,12 +687,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_ast_fragment(&mut self,
|
fn parse_ast_fragment(
|
||||||
toks: TokenStream,
|
&mut self,
|
||||||
kind: AstFragmentKind,
|
toks: TokenStream,
|
||||||
path: &Path,
|
kind: AstFragmentKind,
|
||||||
span: Span)
|
path: &Path,
|
||||||
-> AstFragment {
|
span: Span,
|
||||||
|
) -> AstFragment {
|
||||||
let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::<Vec<_>>());
|
let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::<Vec<_>>());
|
||||||
match parser.parse_ast_fragment(kind, false) {
|
match parser.parse_ast_fragment(kind, false) {
|
||||||
Ok(fragment) => {
|
Ok(fragment) => {
|
||||||
@ -700,6 +702,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||||||
}
|
}
|
||||||
Err(mut err) => {
|
Err(mut err) => {
|
||||||
err.set_span(span);
|
err.set_span(span);
|
||||||
|
annotate_err_with_kind(&mut err, kind, span);
|
||||||
err.emit();
|
err.emit();
|
||||||
self.cx.trace_macros_diag();
|
self.cx.trace_macros_diag();
|
||||||
kind.dummy(span)
|
kind.dummy(span)
|
||||||
|
@ -17,7 +17,7 @@ use crate::symbol::{kw, sym, Symbol};
|
|||||||
use crate::tokenstream::{DelimSpan, TokenStream, TokenTree};
|
use crate::tokenstream::{DelimSpan, TokenStream, TokenTree};
|
||||||
use crate::{ast, attr, attr::TransparencyError};
|
use crate::{ast, attr, attr::TransparencyError};
|
||||||
|
|
||||||
use errors::FatalError;
|
use errors::{DiagnosticBuilder, FatalError};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
|
||||||
@ -43,6 +43,18 @@ pub struct ParserAnyMacro<'a> {
|
|||||||
arm_span: Span,
|
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> {
|
impl<'a> ParserAnyMacro<'a> {
|
||||||
pub fn make(mut self: Box<ParserAnyMacro<'a>>, kind: AstFragmentKind) -> AstFragment {
|
pub fn make(mut self: Box<ParserAnyMacro<'a>>, kind: AstFragmentKind) -> AstFragment {
|
||||||
let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self;
|
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() {
|
} else if !parser.sess.source_map().span_to_filename(parser.token.span).is_real() {
|
||||||
e.span_label(site_span, "in this macro invocation");
|
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
|
e
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ error: expected type, found `'`
|
|||||||
--> $DIR/lifetimes.rs:9:10
|
--> $DIR/lifetimes.rs:9:10
|
||||||
|
|
|
|
||||||
LL | type A = single_quote_alone!();
|
LL | type A = single_quote_alone!();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^ this macro call doesn't expand to a type
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
8
src/test/ui/suggestions/vec-macro-in-pattern.fixed
Normal file
8
src/test/ui/suggestions/vec-macro-in-pattern.fixed
Normal file
@ -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
src/test/ui/suggestions/vec-macro-in-pattern.rs
Normal file
8
src/test/ui/suggestions/vec-macro-in-pattern.rs
Normal file
@ -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
src/test/ui/suggestions/vec-macro-in-pattern.stderr
Normal file
15
src/test/ui/suggestions/vec-macro-in-pattern.stderr
Normal file
@ -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
|
||||||
|
|
@ -6,6 +6,7 @@ LL | let _ = Option:Some(vec![0, 1]);
|
|||||||
| | |
|
| | |
|
||||||
| | expected type
|
| | expected type
|
||||||
| | in this macro invocation
|
| | in this macro invocation
|
||||||
|
| | this macro call doesn't expand to a type
|
||||||
| help: maybe write a path separator here: `::`
|
| help: maybe write a path separator here: `::`
|
||||||
|
|
|
|
||||||
= note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
|
= note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
|
||||||
|
Loading…
Reference in New Issue
Block a user