Skip to content

Commit

Permalink
Rollup merge of rust-lang#70074 - Centril:unpanictry, r=petrochenkov
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Centril authored Mar 18, 2020
2 parents 304816b + 7d38b0f commit 2dc0837
Show file tree
Hide file tree
Showing 44 changed files with 548 additions and 260 deletions.
9 changes: 7 additions & 2 deletions src/librustc_builtin_macros/cmdline_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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");
Expand Down
24 changes: 11 additions & 13 deletions src/librustc_builtin_macros/source_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use rustc_ast::token;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast_pretty::pprust;
use rustc_expand::base::{self, *};
use rustc_expand::panictry;
use rustc_parse::{self, new_sub_parser_from_file, parser::Parser, DirectoryOwnership};
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
use rustc_span::symbol::Symbol;
Expand Down Expand Up @@ -116,7 +115,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,
Expand All @@ -131,18 +130,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;
}
}
}
Expand Down
16 changes: 8 additions & 8 deletions src/librustc_builtin_macros/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
20 changes: 10 additions & 10 deletions src/librustc_builtin_macros/test_harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Up @@ -9,7 +9,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, DirectoryOwnership, MACRO_ARGUMENTS};
use rustc_session::parse::ParseSess;
use rustc_span::edition::Edition;
Expand Down Expand Up @@ -295,16 +295,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))
}
}

Expand All @@ -315,7 +325,7 @@ pub trait AttrProcMacro {
span: Span,
annotation: TokenStream,
annotated: TokenStream,
) -> TokenStream;
) -> Result<TokenStream, ErrorReported>;
}

impl<F> AttrProcMacro for F
Expand All @@ -328,9 +338,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))
}
}

Expand Down Expand Up @@ -999,31 +1009,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.
Expand All @@ -1033,9 +1021,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);
}
Expand Down Expand Up @@ -1163,6 +1148,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(
Expand All @@ -1176,7 +1173,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 {
Expand All @@ -1185,8 +1182,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,
Expand All @@ -1195,7 +1192,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")`.
Expand Down
16 changes: 12 additions & 4 deletions src/librustc_expand/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}

Expand Down Expand Up @@ -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) => {
Expand All @@ -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) => {
Expand Down Expand Up @@ -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();
Expand Down
19 changes: 0 additions & 19 deletions src/librustc_expand/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,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;

Expand Down
Loading

0 comments on commit 2dc0837

Please sign in to comment.