diff --git a/src/librustc_builtin_macros/cmdline_attrs.rs b/src/librustc_builtin_macros/cmdline_attrs.rs index 7ddbf08306b..093815dbbcd 100644 --- a/src/librustc_builtin_macros/cmdline_attrs.rs +++ b/src/librustc_builtin_macros/cmdline_attrs.rs @@ -3,7 +3,6 @@ use rustc_ast::ast::{self, AttrItem, AttrStyle}; use rustc_ast::attr::mk_attr; use rustc_ast::token; -use rustc_expand::panictry; use rustc_session::parse::ParseSess; use rustc_span::FileName; @@ -16,7 +15,13 @@ pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) - ); let start_span = parser.token.span; - let AttrItem { path, args } = panictry!(parser.parse_attr_item()); + let AttrItem { path, args } = match parser.parse_attr_item() { + Ok(ai) => ai, + Err(mut err) => { + err.emit(); + continue; + } + }; let end_span = parser.token.span; if parser.token != token::Eof { parse_sess.span_diagnostic.span_err(start_span.to(end_span), "invalid crate attribute"); diff --git a/src/librustc_builtin_macros/source_util.rs b/src/librustc_builtin_macros/source_util.rs index 51a15f9df1b..67145c6bf43 100644 --- a/src/librustc_builtin_macros/source_util.rs +++ b/src/librustc_builtin_macros/source_util.rs @@ -5,7 +5,6 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; use rustc_expand::base::{self, *}; use rustc_expand::module::DirectoryOwnership; -use rustc_expand::panictry; use rustc_parse::{self, new_parser_from_file, parser::Parser}; use rustc_session::lint::builtin::INCOMPLETE_INCLUDE; use rustc_span::symbol::Symbol; @@ -126,7 +125,7 @@ pub fn expand_include<'cx>( } impl<'a> base::MacResult for ExpandResult<'a> { fn make_expr(mut self: Box>) -> Option> { - let r = panictry!(self.p.parse_expr()); + let r = base::parse_expr(&mut self.p)?; if self.p.token != token::Eof { self.p.sess.buffer_lint( &INCOMPLETE_INCLUDE, @@ -141,18 +140,17 @@ pub fn expand_include<'cx>( fn make_items(mut self: Box>) -> Option; 1]>> { let mut ret = SmallVec::new(); while self.p.token != token::Eof { - match panictry!(self.p.parse_item()) { - Some(item) => ret.push(item), - None => { + match self.p.parse_item() { + Err(mut err) => { + err.emit(); + break; + } + Ok(Some(item)) => ret.push(item), + Ok(None) => { let token = pprust::token_to_string(&self.p.token); - self.p - .sess - .span_diagnostic - .span_fatal( - self.p.token.span, - &format!("expected item, found `{}`", token), - ) - .raise(); + let msg = format!("expected item, found `{}`", token); + self.p.struct_span_err(self.p.token.span, &msg).emit(); + break; } } } diff --git a/src/librustc_builtin_macros/test.rs b/src/librustc_builtin_macros/test.rs index 39009ca27f1..bdc4ae2fe27 100644 --- a/src/librustc_builtin_macros/test.rs +++ b/src/librustc_builtin_macros/test.rs @@ -74,16 +74,16 @@ pub fn expand_test_or_bench( return vec![]; } - let item = if let Annotatable::Item(i) = item { - i - } else { - cx.parse_sess - .span_diagnostic - .span_fatal( - item.span(), + let item = match item { + Annotatable::Item(i) => i, + other => { + cx.struct_span_err( + other.span(), "`#[test]` attribute is only allowed on non associated functions", ) - .raise(); + .emit(); + return vec![other]; + } }; if let ast::ItemKind::MacCall(_) = item.kind { diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs index b87767f4a41..160a5204eaf 100644 --- a/src/librustc_builtin_macros/test_harness.rs +++ b/src/librustc_builtin_macros/test_harness.rs @@ -345,14 +345,14 @@ fn is_test_case(i: &ast::Item) -> bool { fn get_test_runner(sd: &rustc_errors::Handler, krate: &ast::Crate) -> Option { let test_attr = attr::find_by_name(&krate.attrs, sym::test_runner)?; - test_attr.meta_item_list().map(|meta_list| { - if meta_list.len() != 1 { - sd.span_fatal(test_attr.span, "`#![test_runner(..)]` accepts exactly 1 argument") - .raise() - } - match meta_list[0].meta_item() { - Some(meta_item) if meta_item.is_word() => meta_item.path.clone(), - _ => sd.span_fatal(test_attr.span, "`test_runner` argument must be a path").raise(), - } - }) + let meta_list = test_attr.meta_item_list()?; + let span = test_attr.span; + match &*meta_list { + [single] => match single.meta_item() { + Some(meta_item) if meta_item.is_word() => return Some(meta_item.path.clone()), + _ => sd.struct_span_err(span, "`test_runner` argument must be a path").emit(), + }, + _ => sd.struct_span_err(span, "`#![test_runner(..)]` accepts exactly 1 argument").emit(), + } + None } diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs index 0fc477bbd0b..59c1a5468f1 100644 --- a/src/librustc_expand/base.rs +++ b/src/librustc_expand/base.rs @@ -10,7 +10,7 @@ use rustc_ast::visit::{AssocCtxt, Visitor}; use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{self, Lrc}; -use rustc_errors::{DiagnosticBuilder, DiagnosticId}; +use rustc_errors::{DiagnosticBuilder, ErrorReported}; use rustc_parse::{self, parser, MACRO_ARGUMENTS}; use rustc_session::parse::ParseSess; use rustc_span::edition::Edition; @@ -296,16 +296,26 @@ where } pub trait ProcMacro { - fn expand<'cx>(&self, ecx: &'cx mut ExtCtxt<'_>, span: Span, ts: TokenStream) -> TokenStream; + fn expand<'cx>( + &self, + ecx: &'cx mut ExtCtxt<'_>, + span: Span, + ts: TokenStream, + ) -> Result; } impl ProcMacro for F where F: Fn(TokenStream) -> TokenStream, { - fn expand<'cx>(&self, _ecx: &'cx mut ExtCtxt<'_>, _span: Span, ts: TokenStream) -> TokenStream { + fn expand<'cx>( + &self, + _ecx: &'cx mut ExtCtxt<'_>, + _span: Span, + ts: TokenStream, + ) -> Result { // FIXME setup implicit context in TLS before calling self. - (*self)(ts) + Ok((*self)(ts)) } } @@ -316,7 +326,7 @@ pub trait AttrProcMacro { span: Span, annotation: TokenStream, annotated: TokenStream, - ) -> TokenStream; + ) -> Result; } impl AttrProcMacro for F @@ -329,9 +339,9 @@ where _span: Span, annotation: TokenStream, annotated: TokenStream, - ) -> TokenStream { + ) -> Result { // FIXME setup implicit context in TLS before calling self. - (*self)(annotation, annotated) + Ok((*self)(annotation, annotated)) } } @@ -1004,31 +1014,9 @@ impl<'a> ExtCtxt<'a> { self.current_expansion.id.expansion_cause() } - pub fn struct_span_warn>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'a> { - self.parse_sess.span_diagnostic.struct_span_warn(sp, msg) - } pub fn struct_span_err>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'a> { self.parse_sess.span_diagnostic.struct_span_err(sp, msg) } - pub fn struct_span_fatal>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'a> { - self.parse_sess.span_diagnostic.struct_span_fatal(sp, msg) - } - - /// Emit `msg` attached to `sp`, and stop compilation immediately. - /// - /// `span_err` should be strongly preferred where-ever possible: - /// this should *only* be used when: - /// - /// - continuing has a high risk of flow-on errors (e.g., errors in - /// declaring a macro would cause all uses of that macro to - /// complain about "undefined macro"), or - /// - there is literally nothing else that can be done (however, - /// in most cases one can construct a dummy expression/item to - /// substitute; we never hit resolve/type-checking so the dummy - /// value doesn't have to match anything) - pub fn span_fatal>(&self, sp: S, msg: &str) -> ! { - self.parse_sess.span_diagnostic.span_fatal(sp, msg).raise(); - } /// Emit `msg` attached to `sp`, without immediately stopping /// compilation. @@ -1038,9 +1026,6 @@ impl<'a> ExtCtxt<'a> { pub fn span_err>(&self, sp: S, msg: &str) { self.parse_sess.span_diagnostic.span_err(sp, msg); } - pub fn span_err_with_code>(&self, sp: S, msg: &str, code: DiagnosticId) { - self.parse_sess.span_diagnostic.span_err_with_code(sp, msg, code); - } pub fn span_warn>(&self, sp: S, msg: &str) { self.parse_sess.span_diagnostic.span_warn(sp, msg); } @@ -1168,6 +1153,18 @@ pub fn check_zero_tts(cx: &ExtCtxt<'_>, sp: Span, tts: TokenStream, name: &str) } } +/// Parse an expression. On error, emit it, advancing to `Eof`, and return `None`. +pub fn parse_expr(p: &mut parser::Parser<'_>) -> Option> { + match p.parse_expr() { + Ok(e) => return Some(e), + Err(mut err) => err.emit(), + } + while p.token != token::Eof { + p.bump(); + } + None +} + /// Interpreting `tts` as a comma-separated sequence of expressions, /// expect exactly one string literal, or emit an error and return `None`. pub fn get_single_str_from_tts( @@ -1181,7 +1178,7 @@ pub fn get_single_str_from_tts( cx.span_err(sp, &format!("{} takes 1 argument", name)); return None; } - let ret = panictry!(p.parse_expr()); + let ret = parse_expr(&mut p)?; let _ = p.eat(&token::Comma); if p.token != token::Eof { @@ -1190,8 +1187,8 @@ pub fn get_single_str_from_tts( expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s.to_string()) } -/// Extracts comma-separated expressions from `tts`. If there is a -/// parsing error, emit a non-fatal error and return `None`. +/// Extracts comma-separated expressions from `tts`. +/// On error, emit it, and return `None`. pub fn get_exprs_from_tts( cx: &mut ExtCtxt<'_>, sp: Span, @@ -1200,7 +1197,7 @@ pub fn get_exprs_from_tts( let mut p = cx.new_parser_from_tts(tts); let mut es = Vec::new(); while p.token != token::Eof { - let expr = panictry!(p.parse_expr()); + let expr = parse_expr(&mut p)?; // Perform eager expansion on the expression. // We want to be able to handle e.g., `concat!("foo", "bar")`. diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 4f568e5456c..51208906c2f 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -204,7 +204,7 @@ ast_fragments! { } impl AstFragmentKind { - fn dummy(self, span: Span) -> AstFragment { + crate fn dummy(self, span: Span) -> AstFragment { self.make_from(DummyResult::any(span)).expect("couldn't create a dummy AST fragment") } @@ -682,7 +682,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> { InvocationKind::Bang { mac, .. } => match ext { SyntaxExtensionKind::Bang(expander) => { self.gate_proc_macro_expansion_kind(span, fragment_kind); - let tok_result = expander.expand(self.cx, span, mac.args.inner_tokens()); + let tok_result = match expander.expand(self.cx, span, mac.args.inner_tokens()) { + Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)), + Ok(ts) => ts, + }; self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span) } SyntaxExtensionKind::LegacyBang(expander) => { @@ -709,8 +712,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { if let MacArgs::Eq(..) = attr_item.args { self.cx.span_err(span, "key-value macro attributes are not supported"); } - let tok_result = - expander.expand(self.cx, span, attr_item.args.inner_tokens(), tokens); + let inner_tokens = attr_item.args.inner_tokens(); + let tok_result = match expander.expand(self.cx, span, inner_tokens, tokens) { + Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)), + Ok(ts) => ts, + }; self.parse_ast_fragment(tok_result, fragment_kind, &attr_item.path, span) } SyntaxExtensionKind::LegacyAttr(expander) => { @@ -1139,6 +1145,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { // macros are expanded before any lint passes so this warning has to be hardcoded if attr.has_name(sym::derive) { self.cx + .parse_sess() + .span_diagnostic .struct_span_warn(attr.span, "`#[derive]` does nothing on macro invocations") .note("this may become a hard error in a future release") .emit(); diff --git a/src/librustc_expand/lib.rs b/src/librustc_expand/lib.rs index 0320a275e5d..876a26de3fb 100644 --- a/src/librustc_expand/lib.rs +++ b/src/librustc_expand/lib.rs @@ -9,25 +9,6 @@ extern crate proc_macro as pm; -// A variant of 'try!' that panics on an Err. This is used as a crutch on the -// way towards a non-panic!-prone parser. It should be used for fatal parsing -// errors; eventually we plan to convert all code using panictry to just use -// normal try. -#[macro_export] -macro_rules! panictry { - ($e:expr) => {{ - use rustc_errors::FatalError; - use std::result::Result::{Err, Ok}; - match $e { - Ok(e) => e, - Err(mut e) => { - e.emit(); - FatalError.raise() - } - } - }}; -} - mod placeholders; mod proc_macro_server; diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs index 0d777d88cad..e868b7e36aa 100644 --- a/src/librustc_expand/mbe/macro_parser.rs +++ b/src/librustc_expand/mbe/macro_parser.rs @@ -84,7 +84,7 @@ use rustc_parse::parser::{FollowedByType, Parser, PathStyle}; use rustc_session::parse::ParseSess; use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent, Symbol}; -use rustc_errors::{FatalError, PResult}; +use rustc_errors::PResult; use rustc_span::Span; use smallvec::{smallvec, SmallVec}; @@ -271,6 +271,7 @@ crate enum ParseResult { Failure(Token, &'static str), /// Fatal error (malformed macro?). Abort compilation. Error(rustc_span::Span, String), + ErrorReported, } /// A `ParseResult` where the `Success` variant contains a mapping of @@ -652,6 +653,7 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na Success(_) => {} Failure(token, msg) => return Failure(token, msg), Error(sp, msg) => return Error(sp, msg), + ErrorReported => return ErrorReported, } // inner parse loop handled all cur_items, so it's empty @@ -735,10 +737,11 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na let mut item = bb_items.pop().unwrap(); if let TokenTree::MetaVarDecl(span, _, ident) = item.top_elts.get_tt(item.idx) { let match_cur = item.match_cur; - item.push_match( - match_cur, - MatchedNonterminal(Lrc::new(parse_nt(parser.to_mut(), span, ident.name))), - ); + let nt = match parse_nt(parser.to_mut(), span, ident.name) { + Err(()) => return ErrorReported, + Ok(nt) => nt, + }; + item.push_match(match_cur, MatchedNonterminal(Lrc::new(nt))); item.idx += 1; item.match_cur += 1; } else { @@ -849,20 +852,16 @@ fn may_begin_with(token: &Token, name: Name) -> bool { /// # Returns /// /// The parsed non-terminal. -fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Nonterminal { +fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Result { // FIXME(Centril): Consider moving this to `parser.rs` to make // the visibilities of the methods used below `pub(super)` at most. - if name == sym::tt { - return token::NtTT(p.parse_token_tree()); - } - match parse_nt_inner(p, sp, name) { - Ok(nt) => nt, - Err(mut err) => { - err.emit(); - FatalError.raise(); - } + return Ok(token::NtTT(p.parse_token_tree())); } + parse_nt_inner(p, sp, name).map_err(|mut err| { + err.span_label(sp, format!("while parsing argument for this `{}` macro fragment", name)) + .emit() + }) } fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a, Nonterminal> { diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index b6b69400bad..859362b5e29 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -4,7 +4,7 @@ use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstF use crate::mbe; use crate::mbe::macro_check; use crate::mbe::macro_parser::parse_tt; -use crate::mbe::macro_parser::{Error, Failure, Success}; +use crate::mbe::macro_parser::{Error, ErrorReported, Failure, Success}; use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq}; use crate::mbe::transcribe::transcribe; @@ -15,7 +15,7 @@ use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, TransparencyError}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Applicability, DiagnosticBuilder, FatalError}; +use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_feature::Features; use rustc_parse::parser::Parser; use rustc_session::parse::ParseSess; @@ -83,41 +83,56 @@ fn suggest_slice_pat(e: &mut DiagnosticBuilder<'_>, site_span: Span, parser: &Pa ); } +fn emit_frag_parse_err( + mut e: DiagnosticBuilder<'_>, + parser: &Parser<'_>, + site_span: Span, + macro_ident: ast::Ident, + arm_span: Span, + kind: AstFragmentKind, +) { + if parser.token == token::Eof && e.message().ends_with(", found ``") { + if !e.span.is_dummy() { + // early end of macro arm (#52866) + e.replace_span_with(parser.sess.source_map().next_point(parser.token.span)); + } + let msg = &e.message[0]; + e.message[0] = ( + format!( + "macro expansion ends with an incomplete expression: {}", + msg.0.replace(", found ``", ""), + ), + msg.1, + ); + } + if e.span.is_dummy() { + // Get around lack of span in error (#30128) + e.replace_span_with(site_span); + if !parser.sess.source_map().is_imported(arm_span) { + e.span_label(arm_span, "in this macro arm"); + } + } else if parser.sess.source_map().is_imported(parser.token.span) { + 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); + } + _ => annotate_err_with_kind(&mut e, kind, site_span), + }; + e.emit(); +} + impl<'a> ParserAnyMacro<'a> { crate fn make(mut self: Box>, kind: AstFragmentKind) -> AstFragment { let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self; - let fragment = panictry!(parse_ast_fragment(parser, kind).map_err(|mut e| { - if parser.token == token::Eof && e.message().ends_with(", found ``") { - if !e.span.is_dummy() { - // early end of macro arm (#52866) - e.replace_span_with(parser.sess.source_map().next_point(parser.token.span)); - } - let msg = &e.message[0]; - e.message[0] = ( - format!( - "macro expansion ends with an incomplete expression: {}", - msg.0.replace(", found ``", ""), - ), - msg.1, - ); + let fragment = match parse_ast_fragment(parser, kind) { + Ok(f) => f, + Err(err) => { + emit_frag_parse_err(err, parser, site_span, macro_ident, arm_span, kind); + return kind.dummy(site_span); } - if e.span.is_dummy() { - // Get around lack of span in error (#30128) - e.replace_span_with(site_span); - if !parser.sess.source_map().is_imported(arm_span) { - e.span_label(arm_span, "in this macro arm"); - } - } else if parser.sess.source_map().is_imported(parser.token.span) { - 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); - } - _ => annotate_err_with_kind(&mut e, kind, site_span), - }; - e - })); + }; // We allow semicolons at the end of expressions -- e.g., the semicolon in // `macro_rules! m { () => { panic!(); } }` isn't parsed by `.parse_expr()`, @@ -165,6 +180,14 @@ impl TTMacroExpander for MacroRulesMacroExpander { } } +fn macro_rules_dummy_expander<'cx>( + _: &'cx mut ExtCtxt<'_>, + span: Span, + _: TokenStream, +) -> Box { + DummyResult::any(span) +} + fn trace_macros_note(cx_expansions: &mut FxHashMap>, sp: Span, message: String) { let sp = sp.macro_backtrace().last().map(|trace| trace.call_site).unwrap_or(sp); cx_expansions.entry(sp).or_default().push(message); @@ -240,7 +263,13 @@ fn generic_extension<'cx>( let rhs_spans = rhs.iter().map(|t| t.span()).collect::>(); // rhs has holes ( `$id` and `$(...)` that need filled) - let mut tts = transcribe(cx, &named_matches, rhs, transparency); + let mut tts = match transcribe(cx, &named_matches, rhs, transparency) { + Ok(tts) => tts, + Err(mut err) => { + err.emit(); + return DummyResult::any(arm_span); + } + }; // Replace all the tokens for the corresponding positions in the macro, to maintain // proper positions in error reporting, while maintaining the macro_backtrace. @@ -278,7 +307,12 @@ fn generic_extension<'cx>( Some((ref best_token, _)) if best_token.span.lo() >= token.span.lo() => {} _ => best_failure = Some((token, msg)), }, - Error(err_sp, ref msg) => cx.span_fatal(err_sp.substitute_dummy(sp), &msg[..]), + Error(err_sp, ref msg) => { + let span = err_sp.substitute_dummy(sp); + cx.struct_span_err(span, &msg).emit(); + return DummyResult::any(span); + } + ErrorReported => return DummyResult::any(sp), } // The matcher was not `Success(..)`ful. @@ -337,6 +371,18 @@ pub fn compile_declarative_macro( def: &ast::Item, edition: Edition, ) -> SyntaxExtension { + let mk_syn_ext = |expander| { + SyntaxExtension::new( + sess, + SyntaxExtensionKind::LegacyBang(expander), + def.span, + Vec::new(), + edition, + def.ident.name, + &def.attrs, + ) + }; + let diag = &sess.span_diagnostic; let lhs_nm = ast::Ident::new(sym::lhs, def.span); let rhs_nm = ast::Ident::new(sym::rhs, def.span); @@ -391,13 +437,15 @@ pub fn compile_declarative_macro( Failure(token, msg) => { let s = parse_failure_msg(&token); let sp = token.span.substitute_dummy(def.span); - let mut err = sess.span_diagnostic.struct_span_fatal(sp, &s); - err.span_label(sp, msg); - err.emit(); - FatalError.raise(); + sess.span_diagnostic.struct_span_err(sp, &s).span_label(sp, msg).emit(); + return mk_syn_ext(Box::new(macro_rules_dummy_expander)); } - Error(sp, s) => { - sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s).raise(); + Error(sp, msg) => { + sess.span_diagnostic.struct_span_err(sp.substitute_dummy(def.span), &msg).emit(); + return mk_syn_ext(Box::new(macro_rules_dummy_expander)); + } + ErrorReported => { + return mk_syn_ext(Box::new(macro_rules_dummy_expander)); } }; @@ -460,24 +508,14 @@ pub fn compile_declarative_macro( None => {} } - let expander: Box<_> = Box::new(MacroRulesMacroExpander { + mk_syn_ext(Box::new(MacroRulesMacroExpander { name: def.ident, span: def.span, transparency, lhses, rhses, valid, - }); - - SyntaxExtension::new( - sess, - SyntaxExtensionKind::LegacyBang(expander), - def.span, - Vec::new(), - edition, - def.ident.name, - &def.attrs, - ) + })) } fn check_lhs_nt_follows( diff --git a/src/librustc_expand/mbe/transcribe.rs b/src/librustc_expand/mbe/transcribe.rs index 1b1093c9529..e2d3d5c4d64 100644 --- a/src/librustc_expand/mbe/transcribe.rs +++ b/src/librustc_expand/mbe/transcribe.rs @@ -8,7 +8,7 @@ use rustc_ast::token::{self, NtTT, Token}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; -use rustc_errors::pluralize; +use rustc_errors::{pluralize, PResult}; use rustc_span::hygiene::{ExpnId, Transparency}; use rustc_span::symbol::MacroRulesNormalizedIdent; use rustc_span::Span; @@ -80,15 +80,15 @@ impl Iterator for Frame { /// `transcribe` would return a `TokenStream` containing `println!("{}", stringify!(bar));`. /// /// Along the way, we do some additional error checking. -pub(super) fn transcribe( - cx: &ExtCtxt<'_>, +pub(super) fn transcribe<'a>( + cx: &ExtCtxt<'a>, interp: &FxHashMap, src: Vec, transparency: Transparency, -) -> TokenStream { +) -> PResult<'a, TokenStream> { // Nothing for us to transcribe... if src.is_empty() { - return TokenStream::default(); + return Ok(TokenStream::default()); } // We descend into the RHS (`src`), expanding things as we go. This stack contains the things @@ -152,7 +152,7 @@ pub(super) fn transcribe( Frame::Delimited { forest, span, .. } => { if result_stack.is_empty() { // No results left to compute! We are back at the top-level. - return TokenStream::new(result); + return Ok(TokenStream::new(result)); } // Step back into the parent Delimited. @@ -173,11 +173,11 @@ pub(super) fn transcribe( seq @ mbe::TokenTree::Sequence(..) => { match lockstep_iter_size(&seq, interp, &repeats) { LockstepIterSize::Unconstrained => { - cx.span_fatal( + return Err(cx.struct_span_err( seq.span(), /* blame macro writer */ "attempted to repeat an expression containing no syntax variables \ matched as repeating at this depth", - ); + )); } LockstepIterSize::Contradiction(ref msg) => { @@ -185,7 +185,7 @@ pub(super) fn transcribe( // happens when two meta-variables are used in the same repetition in a // sequence, but they come from different sequence matchers and repeat // different amounts. - cx.span_fatal(seq.span(), &msg[..]); + return Err(cx.struct_span_err(seq.span(), &msg[..])); } LockstepIterSize::Constraint(len, _) => { @@ -203,7 +203,10 @@ pub(super) fn transcribe( // FIXME: this really ought to be caught at macro definition // time... It happens when the Kleene operator in the matcher and // the body for the same meta-variable do not match. - cx.span_fatal(sp.entire(), "this must repeat at least once"); + return Err(cx.struct_span_err( + sp.entire(), + "this must repeat at least once", + )); } } else { // 0 is the initial counter (we have done 0 repretitions so far). `len` @@ -242,10 +245,10 @@ pub(super) fn transcribe( } } else { // We were unable to descend far enough. This is an error. - cx.span_fatal( + return Err(cx.struct_span_err( sp, /* blame the macro writer */ &format!("variable '{}' is still repeating at this depth", ident), - ); + )); } } else { // If we aren't able to match the meta-var, we push it back into the result but diff --git a/src/librustc_expand/proc_macro.rs b/src/librustc_expand/proc_macro.rs index cb9afa4cd4f..df7bf9438c3 100644 --- a/src/librustc_expand/proc_macro.rs +++ b/src/librustc_expand/proc_macro.rs @@ -5,7 +5,7 @@ use rustc_ast::ast::{self, ItemKind, MetaItemKind, NestedMetaItem}; use rustc_ast::token; use rustc_ast::tokenstream::{self, TokenStream}; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Applicability, FatalError}; +use rustc_errors::{Applicability, ErrorReported}; use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; @@ -21,21 +21,16 @@ impl base::ProcMacro for BangProcMacro { ecx: &'cx mut ExtCtxt<'_>, span: Span, input: TokenStream, - ) -> TokenStream { + ) -> Result { let server = proc_macro_server::Rustc::new(ecx); - match self.client.run(&EXEC_STRATEGY, server, input) { - Ok(stream) => stream, - Err(e) => { - let msg = "proc macro panicked"; - let mut err = ecx.struct_span_fatal(span, msg); - if let Some(s) = e.as_str() { - err.help(&format!("message: {}", s)); - } - - err.emit(); - FatalError.raise(); + self.client.run(&EXEC_STRATEGY, server, input).map_err(|e| { + let mut err = ecx.struct_span_err(span, "proc macro panicked"); + if let Some(s) = e.as_str() { + err.help(&format!("message: {}", s)); } - } + err.emit(); + ErrorReported + }) } } @@ -50,21 +45,16 @@ impl base::AttrProcMacro for AttrProcMacro { span: Span, annotation: TokenStream, annotated: TokenStream, - ) -> TokenStream { + ) -> Result { let server = proc_macro_server::Rustc::new(ecx); - match self.client.run(&EXEC_STRATEGY, server, annotation, annotated) { - Ok(stream) => stream, - Err(e) => { - let msg = "custom attribute panicked"; - let mut err = ecx.struct_span_fatal(span, msg); - if let Some(s) = e.as_str() { - err.help(&format!("message: {}", s)); - } - - err.emit(); - FatalError.raise(); + self.client.run(&EXEC_STRATEGY, server, annotation, annotated).map_err(|e| { + let mut err = ecx.struct_span_err(span, "custom attribute panicked"); + if let Some(s) = e.as_str() { + err.help(&format!("message: {}", s)); } - } + err.emit(); + ErrorReported + }) } } @@ -96,8 +86,7 @@ impl MultiItemModifier for ProcMacroDerive { | Annotatable::Expr(_) => { ecx.span_err( span, - "proc-macro derives may only be \ - applied to a struct, enum, or union", + "proc-macro derives may only be applied to a struct, enum, or union", ); return ExpandResult::Ready(Vec::new()); } @@ -107,8 +96,7 @@ impl MultiItemModifier for ProcMacroDerive { _ => { ecx.span_err( span, - "proc-macro derives may only be \ - applied to a struct, enum, or union", + "proc-macro derives may only be applied to a struct, enum, or union", ); return ExpandResult::Ready(Vec::new()); } @@ -121,20 +109,16 @@ impl MultiItemModifier for ProcMacroDerive { let stream = match self.client.run(&EXEC_STRATEGY, server, input) { Ok(stream) => stream, Err(e) => { - let msg = "proc-macro derive panicked"; - let mut err = ecx.struct_span_fatal(span, msg); + let mut err = ecx.struct_span_err(span, "proc-macro derive panicked"); if let Some(s) = e.as_str() { err.help(&format!("message: {}", s)); } - err.emit(); - FatalError.raise(); + return ExpandResult::Ready(vec![]); } }; let error_count_before = ecx.parse_sess.span_diagnostic.err_count(); - let msg = "proc-macro derive produced unparseable tokens"; - let mut parser = rustc_parse::stream_to_parser(ecx.parse_sess, stream, Some("proc-macro derive")); let mut items = vec![]; @@ -144,18 +128,15 @@ impl MultiItemModifier for ProcMacroDerive { Ok(None) => break, Ok(Some(item)) => items.push(Annotatable::Item(item)), Err(mut err) => { - // FIXME: handle this better - err.cancel(); - ecx.struct_span_fatal(span, msg).emit(); - FatalError.raise(); + err.emit(); + break; } } } // fail if there have been errors emitted if ecx.parse_sess.span_diagnostic.err_count() > error_count_before { - ecx.struct_span_fatal(span, msg).emit(); - FatalError.raise(); + ecx.struct_span_err(span, "proc-macro derive produced unparseable tokens").emit(); } ExpandResult::Ready(items) diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs b/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs index dbc0465b08e..d5ed9fb9a28 100644 --- a/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs +++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs @@ -1,9 +1,17 @@ // edition:2018 // aux-build:edition-kw-macro-2015.rs +#![feature(async_closure)] + +fn main() {} + #[macro_use] extern crate edition_kw_macro_2015; +mod module { + pub fn r#async() {} +} + pub fn check_async() { let mut async = 1; //~ ERROR expected identifier, found keyword `async` let mut r#async = 1; // OK @@ -17,4 +25,6 @@ pub fn check_async() { if passes_ident!(r#async) == 1 {} // OK module::async(); //~ ERROR expected identifier, found keyword `async` module::r#async(); // OK + + let _recovery_witness: () = 0; //~ ERROR mismatched types } diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr index e12d1a48463..28663563c6c 100644 --- a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr @@ -1,5 +1,5 @@ error: expected identifier, found keyword `async` - --> $DIR/edition-keywords-2018-2015-parsing.rs:8:13 + --> $DIR/edition-keywords-2018-2015-parsing.rs:16:13 | LL | let mut async = 1; | ^^^^^ expected identifier, found keyword @@ -10,7 +10,7 @@ LL | let mut r#async = 1; | ^^^^^^^ error: expected identifier, found keyword `async` - --> $DIR/edition-keywords-2018-2015-parsing.rs:18:13 + --> $DIR/edition-keywords-2018-2015-parsing.rs:26:13 | LL | module::async(); | ^^^^^ expected identifier, found keyword @@ -21,13 +21,13 @@ LL | module::r#async(); | ^^^^^^^ error: no rules expected the token `r#async` - --> $DIR/edition-keywords-2018-2015-parsing.rs:12:31 + --> $DIR/edition-keywords-2018-2015-parsing.rs:20:31 | LL | r#async = consumes_async!(r#async); | ^^^^^^^ no rules expected this token in macro call error: no rules expected the token `async` - --> $DIR/edition-keywords-2018-2015-parsing.rs:13:35 + --> $DIR/edition-keywords-2018-2015-parsing.rs:21:35 | LL | r#async = consumes_async_raw!(async); | ^^^^^ no rules expected this token in macro call @@ -38,10 +38,19 @@ error: macro expansion ends with an incomplete expression: expected one of `move LL | ($i: ident) => ($i) | ^ expected one of `move`, `|`, or `||` | - ::: $DIR/edition-keywords-2018-2015-parsing.rs:16:8 + ::: $DIR/edition-keywords-2018-2015-parsing.rs:24:8 | LL | if passes_ident!(async) == 1 {} | -------------------- in this macro invocation -error: aborting due to 5 previous errors +error[E0308]: mismatched types + --> $DIR/edition-keywords-2018-2015-parsing.rs:29:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs b/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs index 5aca0839f0f..044ab249f2c 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs +++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs @@ -1,9 +1,17 @@ // edition:2018 // aux-build:edition-kw-macro-2018.rs +#![feature(async_closure)] + +fn main() {} + #[macro_use] extern crate edition_kw_macro_2018; +mod module { + pub fn r#async() {} +} + pub fn check_async() { let mut async = 1; //~ ERROR expected identifier, found keyword `async` let mut r#async = 1; // OK @@ -17,4 +25,6 @@ pub fn check_async() { if passes_ident!(r#async) == 1 {} // OK module::async(); //~ ERROR expected identifier, found keyword `async` module::r#async(); // OK + + let _recovery_witness: () = 0; //~ ERROR mismatched types } diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr index 110165fc077..cda7e65e437 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr @@ -1,5 +1,5 @@ error: expected identifier, found keyword `async` - --> $DIR/edition-keywords-2018-2018-parsing.rs:8:13 + --> $DIR/edition-keywords-2018-2018-parsing.rs:16:13 | LL | let mut async = 1; | ^^^^^ expected identifier, found keyword @@ -10,7 +10,7 @@ LL | let mut r#async = 1; | ^^^^^^^ error: expected identifier, found keyword `async` - --> $DIR/edition-keywords-2018-2018-parsing.rs:18:13 + --> $DIR/edition-keywords-2018-2018-parsing.rs:26:13 | LL | module::async(); | ^^^^^ expected identifier, found keyword @@ -21,13 +21,13 @@ LL | module::r#async(); | ^^^^^^^ error: no rules expected the token `r#async` - --> $DIR/edition-keywords-2018-2018-parsing.rs:12:31 + --> $DIR/edition-keywords-2018-2018-parsing.rs:20:31 | LL | r#async = consumes_async!(r#async); | ^^^^^^^ no rules expected this token in macro call error: no rules expected the token `async` - --> $DIR/edition-keywords-2018-2018-parsing.rs:13:35 + --> $DIR/edition-keywords-2018-2018-parsing.rs:21:35 | LL | r#async = consumes_async_raw!(async); | ^^^^^ no rules expected this token in macro call @@ -38,10 +38,19 @@ error: macro expansion ends with an incomplete expression: expected one of `move LL | ($i: ident) => ($i) | ^ expected one of `move`, `|`, or `||` | - ::: $DIR/edition-keywords-2018-2018-parsing.rs:16:8 + ::: $DIR/edition-keywords-2018-2018-parsing.rs:24:8 | LL | if passes_ident!(async) == 1 {} | -------------------- in this macro invocation -error: aborting due to 5 previous errors +error[E0308]: mismatched types + --> $DIR/edition-keywords-2018-2018-parsing.rs:29:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/macros/issue-61033-1.rs b/src/test/ui/macros/issue-61033-1.rs index 8f85dec017f..18df3f6ee94 100644 --- a/src/test/ui/macros/issue-61033-1.rs +++ b/src/test/ui/macros/issue-61033-1.rs @@ -1,9 +1,10 @@ // Regression test for issue #61033. macro_rules! test1 { - ($x:ident, $($tt:tt)*) => { $($tt)+ } //~ERROR this must repeat at least once + ($x:ident, $($tt:tt)*) => { $($tt)+ } //~ ERROR this must repeat at least once } fn main() { test1!(x,); + let _recovery_witness: () = 0; //~ ERROR mismatched types } diff --git a/src/test/ui/macros/issue-61033-1.stderr b/src/test/ui/macros/issue-61033-1.stderr index f3c68f4928d..18205c3436b 100644 --- a/src/test/ui/macros/issue-61033-1.stderr +++ b/src/test/ui/macros/issue-61033-1.stderr @@ -4,5 +4,14 @@ error: this must repeat at least once LL | ($x:ident, $($tt:tt)*) => { $($tt)+ } | ^^^^^ -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/issue-61033-1.rs:9:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/macros/issue-61033-2.rs b/src/test/ui/macros/issue-61033-2.rs index 0799be10b96..1760ba1584d 100644 --- a/src/test/ui/macros/issue-61033-2.rs +++ b/src/test/ui/macros/issue-61033-2.rs @@ -5,7 +5,9 @@ macro_rules! test2 { $(* $id1:ident)* $(+ $id2:ident)* ) => { - $( //~ERROR meta-variable `id1` repeats 2 times + $( + //~^ ERROR meta-variable `id1` repeats 2 times + //~| ERROR meta-variable `id1` repeats 2 times $id1 + $id2 // $id1 and $id2 may repeat different numbers of times )* } @@ -16,4 +18,8 @@ fn main() { * a * b + a + b + c } + test2! { + * a * b + + a + b + c + d + } } diff --git a/src/test/ui/macros/issue-61033-2.stderr b/src/test/ui/macros/issue-61033-2.stderr index bf502919cf7..cdfe7934a0c 100644 --- a/src/test/ui/macros/issue-61033-2.stderr +++ b/src/test/ui/macros/issue-61033-2.stderr @@ -3,9 +3,22 @@ error: meta-variable `id1` repeats 2 times, but `id2` repeats 3 times | LL | $( | __________^ +LL | | +LL | | LL | | $id1 + $id2 // $id1 and $id2 may repeat different numbers of times LL | | )* | |_________^ -error: aborting due to previous error +error: meta-variable `id1` repeats 2 times, but `id2` repeats 4 times + --> $DIR/issue-61033-2.rs:8:10 + | +LL | $( + | __________^ +LL | | +LL | | +LL | | $id1 + $id2 // $id1 and $id2 may repeat different numbers of times +LL | | )* + | |_________^ + +error: aborting due to 2 previous errors diff --git a/src/test/ui/macros/local-ambiguity-multiple-parsing-options.rs b/src/test/ui/macros/local-ambiguity-multiple-parsing-options.rs new file mode 100644 index 00000000000..3967481098c --- /dev/null +++ b/src/test/ui/macros/local-ambiguity-multiple-parsing-options.rs @@ -0,0 +1,8 @@ +fn main() {} + +macro_rules! ambiguity { + ($($i:ident)* $j:ident) => {}; +} + +ambiguity!(error); //~ ERROR local ambiguity +ambiguity!(error); //~ ERROR local ambiguity diff --git a/src/test/ui/macros/local-ambiguity-multiple-parsing-options.stderr b/src/test/ui/macros/local-ambiguity-multiple-parsing-options.stderr new file mode 100644 index 00000000000..0ae56c42221 --- /dev/null +++ b/src/test/ui/macros/local-ambiguity-multiple-parsing-options.stderr @@ -0,0 +1,14 @@ +error: local ambiguity: multiple parsing options: built-in NTs ident ('i') or ident ('j'). + --> $DIR/local-ambiguity-multiple-parsing-options.rs:7:12 + | +LL | ambiguity!(error); + | ^^^^^ + +error: local ambiguity: multiple parsing options: built-in NTs ident ('i') or ident ('j'). + --> $DIR/local-ambiguity-multiple-parsing-options.rs:8:12 + | +LL | ambiguity!(error); + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/macros/macro-context.rs b/src/test/ui/macros/macro-context.rs index 9130c3d921c..13e179578ad 100644 --- a/src/test/ui/macros/macro-context.rs +++ b/src/test/ui/macros/macro-context.rs @@ -4,6 +4,8 @@ macro_rules! m { //~| ERROR macro expansion ignores token `typeof` //~| ERROR macro expansion ignores token `;` //~| ERROR macro expansion ignores token `;` + //~| ERROR cannot find type `i` in this scope + //~| ERROR cannot find value `i` in this scope } fn main() { diff --git a/src/test/ui/macros/macro-context.stderr b/src/test/ui/macros/macro-context.stderr index 2e712110689..17c73898124 100644 --- a/src/test/ui/macros/macro-context.stderr +++ b/src/test/ui/macros/macro-context.stderr @@ -42,5 +42,29 @@ LL | m!(); | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 4 previous errors +error[E0412]: cannot find type `i` in this scope + --> $DIR/macro-context.rs:3:13 + | +LL | () => ( i ; typeof ); + | ^ help: a builtin type with a similar name exists: `i8` +... +LL | let a: m!(); + | ---- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) +error[E0425]: cannot find value `i` in this scope + --> $DIR/macro-context.rs:3:13 + | +LL | () => ( i ; typeof ); + | ^ help: a local variable with a similar name exists: `a` +... +LL | let i = m!(); + | ---- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0412, E0425. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/macros/macro-match-nonterminal.rs b/src/test/ui/macros/macro-match-nonterminal.rs index 6d4b32c9bc9..b23e5c71c03 100644 --- a/src/test/ui/macros/macro-match-nonterminal.rs +++ b/src/test/ui/macros/macro-match-nonterminal.rs @@ -1,4 +1,11 @@ -macro_rules! test { ($a, $b) => (()); } //~ ERROR missing fragment +macro_rules! test { + ($a, $b) => { + //~^ ERROR missing fragment + //~| ERROR missing fragment + //~| WARN this was previously accepted + () + }; +} fn main() { test!() diff --git a/src/test/ui/macros/macro-match-nonterminal.stderr b/src/test/ui/macros/macro-match-nonterminal.stderr index 1de8c5bd4b4..674ce3434aa 100644 --- a/src/test/ui/macros/macro-match-nonterminal.stderr +++ b/src/test/ui/macros/macro-match-nonterminal.stderr @@ -1,8 +1,18 @@ error: missing fragment specifier - --> $DIR/macro-match-nonterminal.rs:1:24 + --> $DIR/macro-match-nonterminal.rs:2:8 | -LL | macro_rules! test { ($a, $b) => (()); } - | ^ +LL | ($a, $b) => { + | ^ -error: aborting due to previous error +error: missing fragment specifier + --> $DIR/macro-match-nonterminal.rs:2:10 + | +LL | ($a, $b) => { + | ^^ + | + = note: `#[deny(missing_fragment_specifier)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #40107 + +error: aborting due to 2 previous errors diff --git a/src/test/ui/macros/trace_faulty_macros.rs b/src/test/ui/macros/trace_faulty_macros.rs index a55f05414b2..5a8e2f50ce3 100644 --- a/src/test/ui/macros/trace_faulty_macros.rs +++ b/src/test/ui/macros/trace_faulty_macros.rs @@ -1,6 +1,6 @@ // compile-flags: -Z trace-macros -#![recursion_limit="4"] +#![recursion_limit = "4"] macro_rules! my_faulty_macro { () => { @@ -24,9 +24,7 @@ macro_rules! my_recursive_macro { } macro_rules! my_macro { - () => { - - }; + () => {}; } fn main() { @@ -39,7 +37,7 @@ fn main() { } #[my_macro] -fn use_bang_macro_as_attr(){} +fn use_bang_macro_as_attr() {} -#[derive(Debug)] -fn use_derive_macro_as_attr(){} +#[derive(Debug)] //~ ERROR `derive` may only be applied to structs +fn use_derive_macro_as_attr() {} diff --git a/src/test/ui/macros/trace_faulty_macros.stderr b/src/test/ui/macros/trace_faulty_macros.stderr index 109b493b437..aec9d1ab191 100644 --- a/src/test/ui/macros/trace_faulty_macros.stderr +++ b/src/test/ui/macros/trace_faulty_macros.stderr @@ -13,7 +13,7 @@ LL | my_faulty_macro!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) note: trace_macro - --> $DIR/trace_faulty_macros.rs:33:5 + --> $DIR/trace_faulty_macros.rs:31:5 | LL | my_faulty_macro!(); | ^^^^^^^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | my_recursive_macro!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) note: trace_macro - --> $DIR/trace_faulty_macros.rs:34:5 + --> $DIR/trace_faulty_macros.rs:32:5 | LL | my_recursive_macro!(); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -60,5 +60,22 @@ LL | let a = pat_macro!(); | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 3 previous errors +error: `derive` may only be applied to structs, enums and unions + --> $DIR/trace_faulty_macros.rs:42:1 + | +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ + +note: trace_macro + --> $DIR/trace_faulty_macros.rs:36:13 + | +LL | let a = pat_macro!(); + | ^^^^^^^^^^^^ + | + = note: expanding `pat_macro! { }` + = note: to `pat_macro ! (A { a : a, b : 0, c : _, .. }) ;` + = note: expanding `pat_macro! { A { a : a, b : 0, c : _, .. } }` + = note: to `A { a: a, b: 0, c: _, .. }` + +error: aborting due to 4 previous errors diff --git a/src/test/ui/parser/issue-62894.rs b/src/test/ui/parser/issue-62894.rs index b9c0bf834dd..e38b7b65089 100644 --- a/src/test/ui/parser/issue-62894.rs +++ b/src/test/ui/parser/issue-62894.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + // Regression test for #62894, shouldn't crash. // error-pattern: this file contains an unclosed delimiter // error-pattern: expected one of `(`, `[`, or `{`, found keyword `fn` diff --git a/src/test/ui/parser/issue-62894.stderr b/src/test/ui/parser/issue-62894.stderr index 6db380f7a7f..4a1d7e275be 100644 --- a/src/test/ui/parser/issue-62894.stderr +++ b/src/test/ui/parser/issue-62894.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-62894.rs:7:14 + --> $DIR/issue-62894.rs:12:14 | LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! | - - - unclosed delimiter @@ -11,7 +11,7 @@ LL | fn main() {} | ^ error: this file contains an unclosed delimiter - --> $DIR/issue-62894.rs:7:14 + --> $DIR/issue-62894.rs:12:14 | LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! | - - - unclosed delimiter @@ -23,7 +23,7 @@ LL | fn main() {} | ^ error: this file contains an unclosed delimiter - --> $DIR/issue-62894.rs:7:14 + --> $DIR/issue-62894.rs:12:14 | LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! | - - - unclosed delimiter @@ -35,13 +35,18 @@ LL | fn main() {} | ^ error: expected one of `(`, `[`, or `{`, found keyword `fn` - --> $DIR/issue-62894.rs:7:1 + --> $DIR/issue-62894.rs:12:1 | LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! | - expected one of `(`, `[`, or `{` LL | LL | fn main() {} | ^^ unexpected token + | + ::: $SRC_DIR/libcore/macros/mod.rs:LL:COL + | +LL | ($left:expr, $right:expr) => ({ + | ---------- while parsing argument for this `expr` macro fragment error: aborting due to 4 previous errors diff --git a/src/test/ui/parser/macro/issue-33569.rs b/src/test/ui/parser/macro/issue-33569.rs index 9ed53519ceb..80e2d7c6545 100644 --- a/src/test/ui/parser/macro/issue-33569.rs +++ b/src/test/ui/parser/macro/issue-33569.rs @@ -6,3 +6,5 @@ macro_rules! foo { } foo!(); + +fn main() {} diff --git a/src/test/ui/parser/macro/macro-repeat.rs b/src/test/ui/parser/macro/macro-repeat.rs index 580a1daacbf..3ffbea217e7 100644 --- a/src/test/ui/parser/macro/macro-repeat.rs +++ b/src/test/ui/parser/macro/macro-repeat.rs @@ -1,9 +1,12 @@ macro_rules! mac { - ( $($v:tt)* ) => ( - $v //~ ERROR still repeating at this depth - ) + ( $($v:tt)* ) => { + $v + //~^ ERROR still repeating at this depth + //~| ERROR still repeating at this depth + }; } fn main() { mac!(0); + mac!(1); } diff --git a/src/test/ui/parser/macro/macro-repeat.stderr b/src/test/ui/parser/macro/macro-repeat.stderr index c86684de744..63554b197b9 100644 --- a/src/test/ui/parser/macro/macro-repeat.stderr +++ b/src/test/ui/parser/macro/macro-repeat.stderr @@ -4,5 +4,11 @@ error: variable 'v' is still repeating at this depth LL | $v | ^^ -error: aborting due to previous error +error: variable 'v' is still repeating at this depth + --> $DIR/macro-repeat.rs:3:9 + | +LL | $v + | ^^ + +error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/nt-parsing-has-recovery.rs b/src/test/ui/parser/nt-parsing-has-recovery.rs new file mode 100644 index 00000000000..ccbeb398af5 --- /dev/null +++ b/src/test/ui/parser/nt-parsing-has-recovery.rs @@ -0,0 +1,10 @@ +macro_rules! foo { + ($e:expr) => {} +} + +foo!(1 + @); //~ ERROR expected expression, found `@` +foo!(1 + @); //~ ERROR expected expression, found `@` + +fn main() { + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/src/test/ui/parser/nt-parsing-has-recovery.stderr b/src/test/ui/parser/nt-parsing-has-recovery.stderr new file mode 100644 index 00000000000..263c4ad5361 --- /dev/null +++ b/src/test/ui/parser/nt-parsing-has-recovery.stderr @@ -0,0 +1,29 @@ +error: expected expression, found `@` + --> $DIR/nt-parsing-has-recovery.rs:5:10 + | +LL | ($e:expr) => {} + | ------- while parsing argument for this `expr` macro fragment +... +LL | foo!(1 + @); + | ^ expected expression + +error: expected expression, found `@` + --> $DIR/nt-parsing-has-recovery.rs:6:10 + | +LL | ($e:expr) => {} + | ------- while parsing argument for this `expr` macro fragment +... +LL | foo!(1 + @); + | ^ expected expression + +error[E0308]: mismatched types + --> $DIR/nt-parsing-has-recovery.rs:9:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/proc-macro/derive-bad.rs b/src/test/ui/proc-macro/derive-bad.rs index 62c0741b669..cb5188b5fb4 100644 --- a/src/test/ui/proc-macro/derive-bad.rs +++ b/src/test/ui/proc-macro/derive-bad.rs @@ -3,11 +3,9 @@ #[macro_use] extern crate derive_bad; -#[derive( - A -)] -//~^^ ERROR proc-macro derive produced unparseable tokens +#[derive(A)] +//~^ ERROR proc-macro derive produced unparseable tokens //~| ERROR expected `:`, found `}` -struct A; +struct A; //~ ERROR the name `A` is defined multiple times fn main() {} diff --git a/src/test/ui/proc-macro/derive-bad.stderr b/src/test/ui/proc-macro/derive-bad.stderr index 8667396c989..bc5ed981523 100644 --- a/src/test/ui/proc-macro/derive-bad.stderr +++ b/src/test/ui/proc-macro/derive-bad.stderr @@ -1,16 +1,28 @@ error: expected `:`, found `}` - --> $DIR/derive-bad.rs:7:5 + --> $DIR/derive-bad.rs:6:10 | -LL | A - | ^ expected `:` +LL | #[derive(A)] + | ^ expected `:` | = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: proc-macro derive produced unparseable tokens - --> $DIR/derive-bad.rs:7:5 + --> $DIR/derive-bad.rs:6:10 | -LL | A - | ^ +LL | #[derive(A)] + | ^ -error: aborting due to 2 previous errors +error[E0428]: the name `A` is defined multiple times + --> $DIR/derive-bad.rs:9:1 + | +LL | #[derive(A)] + | - previous definition of the type `A` here +... +LL | struct A; + | ^^^^^^^^^ `A` redefined here + | + = note: `A` must be defined only once in the type namespace of this module +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.rs b/src/test/ui/proc-macro/invalid-punct-ident-1.rs index 9de57da5af4..3f78dea917b 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-1.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-1.rs @@ -14,3 +14,5 @@ extern crate invalid_punct_ident; invalid_punct!(); //~ ERROR proc macro panicked + +fn main() {} diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.rs b/src/test/ui/proc-macro/invalid-punct-ident-2.rs index 79f72324b1d..4e89e80ae7c 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-2.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-2.rs @@ -14,3 +14,5 @@ extern crate invalid_punct_ident; invalid_ident!(); //~ ERROR proc macro panicked + +fn main() {} diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.rs b/src/test/ui/proc-macro/invalid-punct-ident-3.rs index d01e9b699ca..8d8ce8f932e 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-3.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-3.rs @@ -14,3 +14,5 @@ extern crate invalid_punct_ident; invalid_raw_ident!(); //~ ERROR proc macro panicked + +fn main() {} diff --git a/src/test/ui/proc-macro/invalid-punct-ident-4.rs b/src/test/ui/proc-macro/invalid-punct-ident-4.rs index e50f24deae3..59b347dac67 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-4.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-4.rs @@ -3,5 +3,10 @@ #[macro_use] extern crate invalid_punct_ident; -lexer_failure!(); //~ ERROR proc macro panicked - //~| ERROR unexpected closing delimiter: `)` +lexer_failure!(); +//~^ ERROR proc macro panicked +//~| ERROR unexpected closing delimiter: `)` + +fn main() { + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/src/test/ui/proc-macro/invalid-punct-ident-4.stderr b/src/test/ui/proc-macro/invalid-punct-ident-4.stderr index fe3e55b31be..3b357aecea8 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-4.stderr +++ b/src/test/ui/proc-macro/invalid-punct-ident-4.stderr @@ -12,5 +12,14 @@ error: proc macro panicked LL | lexer_failure!(); | ^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/invalid-punct-ident-4.rs:11:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/proc-macro/issue-36935.rs b/src/test/ui/proc-macro/issue-36935.rs index f809592d5f4..5c43a564c00 100644 --- a/src/test/ui/proc-macro/issue-36935.rs +++ b/src/test/ui/proc-macro/issue-36935.rs @@ -5,6 +5,7 @@ extern crate test_macros; #[derive(Identity, Panic)] //~ ERROR proc-macro derive panicked struct Baz { + //~^ ERROR the name `Baz` is defined multiple times a: i32, b: i32, } diff --git a/src/test/ui/proc-macro/issue-36935.stderr b/src/test/ui/proc-macro/issue-36935.stderr index da4366eb668..2b2e28fdb2f 100644 --- a/src/test/ui/proc-macro/issue-36935.stderr +++ b/src/test/ui/proc-macro/issue-36935.stderr @@ -6,5 +6,17 @@ LL | #[derive(Identity, Panic)] | = help: message: panic-derive -error: aborting due to previous error +error[E0428]: the name `Baz` is defined multiple times + --> $DIR/issue-36935.rs:7:1 + | +LL | struct Baz { + | ^^^^^^^^^^ + | | + | `Baz` redefined here + | previous definition of the type `Baz` here + | + = note: `Baz` must be defined only once in the type namespace of this module +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/ui/span/transitive-dep-span.rs b/src/test/ui/span/transitive-dep-span.rs index b445d389c56..2d46f74ad9b 100644 --- a/src/test/ui/span/transitive-dep-span.rs +++ b/src/test/ui/span/transitive-dep-span.rs @@ -11,3 +11,5 @@ extern crate transitive_dep_two; transitive_dep_two::parse_error!(); //~ ERROR expected one of + +fn main() {} diff --git a/src/test/ui/test-attrs/test-attr-non-associated-functions.rs b/src/test/ui/test-attrs/test-attr-non-associated-functions.rs index e475f5b4a75..31e567c3960 100644 --- a/src/test/ui/test-attrs/test-attr-non-associated-functions.rs +++ b/src/test/ui/test-attrs/test-attr-non-associated-functions.rs @@ -6,7 +6,13 @@ struct A {} impl A { #[test] - fn new() -> A { //~ ERROR `#[test]` attribute is only allowed on non associated functions + fn new() -> A { + //~^ ERROR `#[test]` attribute is only allowed on non associated functions + A {} + } + #[test] + fn recovery_witness() -> A { + //~^ ERROR `#[test]` attribute is only allowed on non associated functions A {} } } diff --git a/src/test/ui/test-attrs/test-attr-non-associated-functions.stderr b/src/test/ui/test-attrs/test-attr-non-associated-functions.stderr index cb3ae51823e..a81b8f3980c 100644 --- a/src/test/ui/test-attrs/test-attr-non-associated-functions.stderr +++ b/src/test/ui/test-attrs/test-attr-non-associated-functions.stderr @@ -2,9 +2,19 @@ error: `#[test]` attribute is only allowed on non associated functions --> $DIR/test-attr-non-associated-functions.rs:9:5 | LL | / fn new() -> A { +LL | | LL | | A {} LL | | } | |_____^ -error: aborting due to previous error +error: `#[test]` attribute is only allowed on non associated functions + --> $DIR/test-attr-non-associated-functions.rs:14:5 + | +LL | / fn recovery_witness() -> A { +LL | | +LL | | A {} +LL | | } + | |_____^ + +error: aborting due to 2 previous errors diff --git a/src/test/ui/type/ascription/issue-47666.rs b/src/test/ui/type/ascription/issue-47666.rs index ceb1dd89dae..8035de4a48a 100644 --- a/src/test/ui/type/ascription/issue-47666.rs +++ b/src/test/ui/type/ascription/issue-47666.rs @@ -1,5 +1,7 @@ fn main() { let _ = Option:Some(vec![0, 1]); //~ ERROR expected type, found + //~^ ERROR expected value, found enum `Option` + //~| ERROR expected type, found variant `Some` } // This case isn't currently being handled gracefully due to the macro invocation. diff --git a/src/test/ui/type/ascription/issue-47666.stderr b/src/test/ui/type/ascription/issue-47666.stderr index f4c9240ab53..3cd3be70aa7 100644 --- a/src/test/ui/type/ascription/issue-47666.stderr +++ b/src/test/ui/type/ascription/issue-47666.stderr @@ -13,5 +13,35 @@ LL | let _ = Option:Some(vec![0, 1]); = note: see issue #23416 for more information = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error[E0423]: expected value, found enum `Option` + --> $DIR/issue-47666.rs:2:13 + | +LL | let _ = Option:Some(vec![0, 1]); + | ^^^^^^ + | +help: try using one of the enum's variants + | +LL | let _ = std::option::Option::None:Some(vec![0, 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _ = std::option::Option::Some:Some(vec![0, 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +error[E0573]: expected type, found variant `Some` + --> $DIR/issue-47666.rs:2:20 + | +LL | let _ = Option:Some(vec![0, 1]); + | ^^^^^^^^^^^^^^^^ not a type + | +help: try using the variant's enum + | +LL | let _ = Option:std::option::Option; + | ^^^^^^^^^^^^^^^^^^^ +help: maybe you meant to write a path separator here + | +LL | let _ = Option::Some(vec![0, 1]); + | ^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0423, E0573. +For more information about an error, try `rustc --explain E0423`.