Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/librustc_builtin_macros/cmdline_attrs.rs
Original file line number Diff line number Diff line change
@@ -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");
24 changes: 11 additions & 13 deletions src/librustc_builtin_macros/source_util.rs
Original file line number Diff line number Diff line change
@@ -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<ExpandResult<'a>>) -> Option<P<ast::Expr>> {
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<ExpandResult<'a>>) -> Option<SmallVec<[P<ast::Item>; 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;
}
}
}
16 changes: 8 additions & 8 deletions src/librustc_builtin_macros/test.rs
Original file line number Diff line number Diff line change
@@ -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 {
20 changes: 10 additions & 10 deletions src/librustc_builtin_macros/test_harness.rs
Original file line number Diff line number Diff line change
@@ -345,14 +345,14 @@ fn is_test_case(i: &ast::Item) -> bool {

fn get_test_runner(sd: &rustc_errors::Handler, krate: &ast::Crate) -> Option<ast::Path> {
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
}
69 changes: 33 additions & 36 deletions src/librustc_expand/base.rs
Original file line number Diff line number Diff line change
@@ -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<TokenStream, ErrorReported>;
}

impl<F> 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<TokenStream, ErrorReported> {
// 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<TokenStream, ErrorReported>;
}

impl<F> AttrProcMacro for F
@@ -329,9 +339,9 @@ where
_span: Span,
annotation: TokenStream,
annotated: TokenStream,
) -> TokenStream {
) -> Result<TokenStream, ErrorReported> {
// 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<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'a> {
self.parse_sess.span_diagnostic.struct_span_warn(sp, msg)
}
pub fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'a> {
self.parse_sess.span_diagnostic.struct_span_err(sp, msg)
}
pub fn struct_span_fatal<S: Into<MultiSpan>>(&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<S: Into<MultiSpan>>(&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<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.parse_sess.span_diagnostic.span_err(sp, msg);
}
pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
self.parse_sess.span_diagnostic.span_err_with_code(sp, msg, code);
}
pub fn span_warn<S: Into<MultiSpan>>(&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<P<ast::Expr>> {
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")`.
16 changes: 12 additions & 4 deletions src/librustc_expand/expand.rs
Original file line number Diff line number Diff line change
@@ -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();
19 changes: 0 additions & 19 deletions src/librustc_expand/lib.rs
Original file line number Diff line number Diff line change
@@ -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;

29 changes: 14 additions & 15 deletions src/librustc_expand/mbe/macro_parser.rs
Original file line number Diff line number Diff line change
@@ -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<T> {
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<Nonterminal, ()> {
// 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> {
144 changes: 91 additions & 53 deletions src/librustc_expand/mbe/macro_rules.rs
Original file line number Diff line number Diff line change
@@ -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 `<eof>`") {
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 `<eof>`", ""),
),
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<ParserAnyMacro<'a>>, 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 `<eof>`") {
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 `<eof>`", ""),
),
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<dyn MacResult + 'cx> {
DummyResult::any(span)
}

fn trace_macros_note(cx_expansions: &mut FxHashMap<Span, Vec<String>>, 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::<Vec<_>>();
// 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, msg) => {
sess.span_diagnostic.struct_span_err(sp.substitute_dummy(def.span), &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();
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(
27 changes: 15 additions & 12 deletions src/librustc_expand/mbe/transcribe.rs
Original file line number Diff line number Diff line change
@@ -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<MacroRulesNormalizedIdent, NamedMatch>,
src: Vec<mbe::TokenTree>,
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,19 +173,19 @@ 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) => {
// FIXME: this really ought to be caught at macro definition time... It
// 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
67 changes: 24 additions & 43 deletions src/librustc_expand/proc_macro.rs
Original file line number Diff line number Diff line change
@@ -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<TokenStream, ErrorReported> {
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<TokenStream, ErrorReported> {
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)
10 changes: 10 additions & 0 deletions src/test/ui/editions/edition-keywords-2018-2015-parsing.rs
Original file line number Diff line number Diff line change
@@ -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
}
21 changes: 15 additions & 6 deletions src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr
Original file line number Diff line number Diff line change
@@ -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`.
10 changes: 10 additions & 0 deletions src/test/ui/editions/edition-keywords-2018-2018-parsing.rs
Original file line number Diff line number Diff line change
@@ -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
}
21 changes: 15 additions & 6 deletions src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr
Original file line number Diff line number Diff line change
@@ -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`.
3 changes: 2 additions & 1 deletion src/test/ui/macros/issue-61033-1.rs
Original file line number Diff line number Diff line change
@@ -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
}
11 changes: 10 additions & 1 deletion src/test/ui/macros/issue-61033-1.stderr
Original file line number Diff line number Diff line change
@@ -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`.
8 changes: 7 additions & 1 deletion src/test/ui/macros/issue-61033-2.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
15 changes: 14 additions & 1 deletion src/test/ui/macros/issue-61033-2.stderr
Original file line number Diff line number Diff line change
@@ -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

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fn main() {}

macro_rules! ambiguity {
($($i:ident)* $j:ident) => {};
}

ambiguity!(error); //~ ERROR local ambiguity
ambiguity!(error); //~ ERROR local ambiguity
14 changes: 14 additions & 0 deletions src/test/ui/macros/local-ambiguity-multiple-parsing-options.stderr
Original file line number Diff line number Diff line change
@@ -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

2 changes: 2 additions & 0 deletions src/test/ui/macros/macro-context.rs
Original file line number Diff line number Diff line change
@@ -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() {
26 changes: 25 additions & 1 deletion src/test/ui/macros/macro-context.stderr
Original file line number Diff line number Diff line change
@@ -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`.
9 changes: 8 additions & 1 deletion src/test/ui/macros/macro-match-nonterminal.rs
Original file line number Diff line number Diff line change
@@ -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!()
18 changes: 14 additions & 4 deletions src/test/ui/macros/macro-match-nonterminal.stderr
Original file line number Diff line number Diff line change
@@ -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 <https://github.com/rust-lang/rust/issues/40107>

error: aborting due to 2 previous errors

12 changes: 5 additions & 7 deletions src/test/ui/macros/trace_faulty_macros.rs
Original file line number Diff line number Diff line change
@@ -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() {}
23 changes: 20 additions & 3 deletions src/test/ui/macros/trace_faulty_macros.stderr
Original file line number Diff line number Diff line change
@@ -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

5 changes: 5 additions & 0 deletions src/test/ui/parser/issue-62894.rs
Original file line number Diff line number Diff line change
@@ -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`
13 changes: 9 additions & 4 deletions src/test/ui/parser/issue-62894.stderr
Original file line number Diff line number Diff line change
@@ -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

2 changes: 2 additions & 0 deletions src/test/ui/parser/macro/issue-33569.rs
Original file line number Diff line number Diff line change
@@ -6,3 +6,5 @@ macro_rules! foo {
}

foo!();

fn main() {}
9 changes: 6 additions & 3 deletions src/test/ui/parser/macro/macro-repeat.rs
Original file line number Diff line number Diff line change
@@ -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);
}
8 changes: 7 additions & 1 deletion src/test/ui/parser/macro/macro-repeat.stderr
Original file line number Diff line number Diff line change
@@ -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

10 changes: 10 additions & 0 deletions src/test/ui/parser/nt-parsing-has-recovery.rs
Original file line number Diff line number Diff line change
@@ -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
}
29 changes: 29 additions & 0 deletions src/test/ui/parser/nt-parsing-has-recovery.stderr
Original file line number Diff line number Diff line change
@@ -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`.
8 changes: 3 additions & 5 deletions src/test/ui/proc-macro/derive-bad.rs
Original file line number Diff line number Diff line change
@@ -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() {}
26 changes: 19 additions & 7 deletions src/test/ui/proc-macro/derive-bad.stderr
Original file line number Diff line number Diff line change
@@ -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`.
2 changes: 2 additions & 0 deletions src/test/ui/proc-macro/invalid-punct-ident-1.rs
Original file line number Diff line number Diff line change
@@ -14,3 +14,5 @@
extern crate invalid_punct_ident;

invalid_punct!(); //~ ERROR proc macro panicked

fn main() {}
2 changes: 2 additions & 0 deletions src/test/ui/proc-macro/invalid-punct-ident-2.rs
Original file line number Diff line number Diff line change
@@ -14,3 +14,5 @@
extern crate invalid_punct_ident;

invalid_ident!(); //~ ERROR proc macro panicked

fn main() {}
2 changes: 2 additions & 0 deletions src/test/ui/proc-macro/invalid-punct-ident-3.rs
Original file line number Diff line number Diff line change
@@ -14,3 +14,5 @@
extern crate invalid_punct_ident;

invalid_raw_ident!(); //~ ERROR proc macro panicked

fn main() {}
9 changes: 7 additions & 2 deletions src/test/ui/proc-macro/invalid-punct-ident-4.rs
Original file line number Diff line number Diff line change
@@ -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
}
11 changes: 10 additions & 1 deletion src/test/ui/proc-macro/invalid-punct-ident-4.stderr
Original file line number Diff line number Diff line change
@@ -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`.
1 change: 1 addition & 0 deletions src/test/ui/proc-macro/issue-36935.rs
Original file line number Diff line number Diff line change
@@ -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,
}
14 changes: 13 additions & 1 deletion src/test/ui/proc-macro/issue-36935.stderr
Original file line number Diff line number Diff line change
@@ -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`.
2 changes: 2 additions & 0 deletions src/test/ui/span/transitive-dep-span.rs
Original file line number Diff line number Diff line change
@@ -11,3 +11,5 @@
extern crate transitive_dep_two;

transitive_dep_two::parse_error!(); //~ ERROR expected one of

fn main() {}
8 changes: 7 additions & 1 deletion src/test/ui/test-attrs/test-attr-non-associated-functions.rs
Original file line number Diff line number Diff line change
@@ -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 {}
}
}
12 changes: 11 additions & 1 deletion src/test/ui/test-attrs/test-attr-non-associated-functions.stderr
Original file line number Diff line number Diff line change
@@ -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

2 changes: 2 additions & 0 deletions src/test/ui/type/ascription/issue-47666.rs
Original file line number Diff line number Diff line change
@@ -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.
32 changes: 31 additions & 1 deletion src/test/ui/type/ascription/issue-47666.stderr
Original file line number Diff line number Diff line change
@@ -13,5 +13,35 @@ LL | let _ = Option:Some(vec![0, 1]);
= note: see issue #23416 <https://github.com/rust-lang/rust/issues/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]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This suggestion is really weird.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open an issue: #70382

| ^^^^^^^^^^^^^^^^^^^^^^^^^
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;

This comment was marked as duplicate.

| ^^^^^^^^^^^^^^^^^^^
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`.