diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 8373304ea913..e8c711cae64e 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -56,36 +56,11 @@ crate fn annotate_err_with_kind( }; } -/// Instead of e.g. `vec![a, b, c]` in a pattern context, suggest `[a, b, c]`. -fn suggest_slice_pat(e: &mut DiagnosticBuilder<'_>, site_span: Span, parser: &Parser<'_>) { - 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", - ); -} - fn emit_frag_parse_err( mut e: DiagnosticBuilder<'_>, parser: &Parser<'_>, orig_parser: &mut Parser<'_>, site_span: Span, - macro_ident: Ident, arm_span: Span, kind: AstFragmentKind, ) { @@ -113,9 +88,6 @@ fn emit_frag_parse_err( e.span_label(site_span, "in this macro invocation"); } match kind { - AstFragmentKind::Pat if macro_ident.name == sym::vec => { - suggest_slice_pat(&mut e, site_span, parser); - } // Try a statement if an expression is wanted but failed and suggest adding `;` to call. AstFragmentKind::Expr => match parse_ast_fragment(orig_parser, AstFragmentKind::Stmts) { Err(mut err) => err.cancel(), @@ -143,7 +115,7 @@ impl<'a> ParserAnyMacro<'a> { let fragment = match parse_ast_fragment(parser, kind) { Ok(f) => f, Err(err) => { - emit_frag_parse_err(err, parser, snapshot, site_span, macro_ident, arm_span, kind); + emit_frag_parse_err(err, parser, snapshot, site_span, arm_span, kind); return kind.dummy(site_span); } }; diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index d0bfa038aa13..14a10aac061a 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -140,6 +140,7 @@ #![feature(type_alias_impl_trait)] #![feature(associated_type_bounds)] #![feature(slice_group_by)] +#![feature(decl_macro)] // Allow testing this library #[cfg(test)] @@ -193,4 +194,11 @@ mod std { #[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")] pub mod __export { pub use core::format_args; + + /// Force AST node to an expression to improve diagnostics in pattern position. + #[rustc_macro_transparency = "semitransparent"] + #[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")] + pub macro force_expr($e:expr) { + $e + } } diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs index 7d4eff6185db..3a46763c3f60 100644 --- a/library/alloc/src/macros.rs +++ b/library/alloc/src/macros.rs @@ -37,16 +37,16 @@ #[cfg(not(test))] #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] -#[allow_internal_unstable(box_syntax)] +#[allow_internal_unstable(box_syntax, liballoc_internals)] macro_rules! vec { () => ( - $crate::vec::Vec::new() + $crate::__export::force_expr!($crate::vec::Vec::new()) ); ($elem:expr; $n:expr) => ( - $crate::vec::from_elem($elem, $n) + $crate::__export::force_expr!($crate::vec::from_elem($elem, $n)) ); ($($x:expr),+ $(,)?) => ( - <[_]>::into_vec(box [$($x),+]) + $crate::__export::force_expr!(<[_]>::into_vec(box [$($x),+])) ); } diff --git a/src/test/ui/macros/vec-macro-in-pattern.rs b/src/test/ui/macros/vec-macro-in-pattern.rs new file mode 100644 index 000000000000..ce4298b8bb33 --- /dev/null +++ b/src/test/ui/macros/vec-macro-in-pattern.rs @@ -0,0 +1,10 @@ +// This is a regression test for #61933 +// Verify that the vec![] macro may not be used in patterns +// and that the resulting diagnostic is actually helpful. + +fn main() { + match Some(vec![42]) { + Some(vec![43]) => {} //~ ERROR arbitrary expressions aren't allowed in patterns + _ => {} + } +} diff --git a/src/test/ui/macros/vec-macro-in-pattern.stderr b/src/test/ui/macros/vec-macro-in-pattern.stderr new file mode 100644 index 000000000000..3dabebfdaa25 --- /dev/null +++ b/src/test/ui/macros/vec-macro-in-pattern.stderr @@ -0,0 +1,10 @@ +error: arbitrary expressions aren't allowed in patterns + --> $DIR/vec-macro-in-pattern.rs:7:14 + | +LL | Some(vec![43]) => {} + | ^^^^^^^^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/suggestions/vec-macro-in-pattern.fixed b/src/test/ui/suggestions/vec-macro-in-pattern.fixed deleted file mode 100644 index e1695d6820a8..000000000000 --- a/src/test/ui/suggestions/vec-macro-in-pattern.fixed +++ /dev/null @@ -1,8 +0,0 @@ -// 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 - _ => (), - } -} diff --git a/src/test/ui/suggestions/vec-macro-in-pattern.rs b/src/test/ui/suggestions/vec-macro-in-pattern.rs deleted file mode 100644 index 4843629fbcf9..000000000000 --- a/src/test/ui/suggestions/vec-macro-in-pattern.rs +++ /dev/null @@ -1,8 +0,0 @@ -// 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 - _ => (), - } -} diff --git a/src/test/ui/suggestions/vec-macro-in-pattern.stderr b/src/test/ui/suggestions/vec-macro-in-pattern.stderr deleted file mode 100644 index f9d0464ac88b..000000000000 --- a/src/test/ui/suggestions/vec-macro-in-pattern.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: unexpected `(` after qualified path - --> $DIR/vec-macro-in-pattern.rs:5:14 - | -LL | Some(vec![_x]) => (), - | ^^^^^^^^ - | | - | unexpected `(` after qualified path - | the 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 error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to previous error - diff --git a/src/test/ui/type/ascription/issue-47666.stderr b/src/test/ui/type/ascription/issue-47666.stderr index ba393ff1a208..755eec23c2ee 100644 --- a/src/test/ui/type/ascription/issue-47666.stderr +++ b/src/test/ui/type/ascription/issue-47666.stderr @@ -1,4 +1,4 @@ -error: expected type, found reserved keyword `box` +error: expected type, found `<[_]>::into_vec(box [0, 1])` --> $DIR/issue-47666.rs:3:25 | LL | let _ = Option:Some(vec![0, 1]);