Rollup merge of #70074 - Centril:unpanictry, r=petrochenkov

Expand: nix all fatal errors

Basically, we go after all `.span_fatal` / `FatalError.raise()` and similar things and remove them one by one until there are no fatal errors left.

r? @petrochenkov
This commit is contained in:
Mazdak Farrokhzad 2020-03-24 07:13:33 +01:00 committed by GitHub
commit 3d8b9614d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 584 additions and 274 deletions

View File

@ -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");

View File

@ -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;
}
}
}

View File

@ -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 {

View File

@ -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
}

View File

@ -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")`.

View File

@ -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();

View File

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

View File

@ -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> {

View File

@ -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, 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(

View File

@ -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,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

View File

@ -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)

View File

@ -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
}

View File

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

View File

@ -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
}

View File

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

View File

@ -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
}

View File

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

View File

@ -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
}
}

View File

@ -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

View File

@ -0,0 +1,8 @@
fn main() {}
macro_rules! ambiguity {
($($i:ident)* $j:ident) => {};
}
ambiguity!(error); //~ ERROR local ambiguity
ambiguity!(error); //~ ERROR local ambiguity

View File

@ -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

View File

@ -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() {

View File

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

View File

@ -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!()

View File

@ -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

View File

@ -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() {}

View File

@ -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

View File

@ -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`

View File

@ -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

View File

@ -6,3 +6,5 @@ macro_rules! foo {
}
foo!();
fn main() {}

View File

@ -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);
}

View File

@ -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

View File

@ -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
}

View File

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

View File

@ -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() {}

View File

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

View File

@ -14,3 +14,5 @@
extern crate invalid_punct_ident;
invalid_punct!(); //~ ERROR proc macro panicked
fn main() {}

View File

@ -14,3 +14,5 @@
extern crate invalid_punct_ident;
invalid_ident!(); //~ ERROR proc macro panicked
fn main() {}

View File

@ -14,3 +14,5 @@
extern crate invalid_punct_ident;
invalid_raw_ident!(); //~ ERROR proc macro panicked
fn main() {}

View File

@ -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
}

View File

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

View File

@ -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,
}

View File

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

View File

@ -11,3 +11,5 @@
extern crate transitive_dep_two;
transitive_dep_two::parse_error!(); //~ ERROR expected one of
fn main() {}

View File

@ -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 {}
}
}

View File

@ -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

View File

@ -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.

View File

@ -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]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
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`.