Auto merge of #57205 - petrochenkov:extrecov, r=estebank

Improve error recovery for some built-in macros

Fixes https://github.com/rust-lang/rust/issues/55897
This commit is contained in:
bors 2018-12-30 16:06:30 +00:00
commit 953a9cf10d
13 changed files with 74 additions and 47 deletions

View File

@ -995,7 +995,7 @@ pub fn expr_to_spanned_string<'a>(
cx: &'a mut ExtCtxt, cx: &'a mut ExtCtxt,
expr: P<ast::Expr>, expr: P<ast::Expr>,
err_msg: &str, err_msg: &str,
) -> Result<Spanned<(Symbol, ast::StrStyle)>, DiagnosticBuilder<'a>> { ) -> Result<Spanned<(Symbol, ast::StrStyle)>, Option<DiagnosticBuilder<'a>>> {
// Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation. // Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation.
let expr = expr.map(|mut expr| { let expr = expr.map(|mut expr| {
expr.span = expr.span.apply_mark(cx.current_expansion.mark); expr.span = expr.span.apply_mark(cx.current_expansion.mark);
@ -1007,16 +1007,17 @@ pub fn expr_to_spanned_string<'a>(
Err(match expr.node { Err(match expr.node {
ast::ExprKind::Lit(ref l) => match l.node { ast::ExprKind::Lit(ref l) => match l.node {
ast::LitKind::Str(s, style) => return Ok(respan(expr.span, (s, style))), ast::LitKind::Str(s, style) => return Ok(respan(expr.span, (s, style))),
_ => cx.struct_span_err(l.span, err_msg) _ => Some(cx.struct_span_err(l.span, err_msg))
}, },
_ => cx.struct_span_err(expr.span, err_msg) ast::ExprKind::Err => None,
_ => Some(cx.struct_span_err(expr.span, err_msg))
}) })
} }
pub fn expr_to_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &str) pub fn expr_to_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &str)
-> Option<(Symbol, ast::StrStyle)> { -> Option<(Symbol, ast::StrStyle)> {
expr_to_spanned_string(cx, expr, err_msg) expr_to_spanned_string(cx, expr, err_msg)
.map_err(|mut err| err.emit()) .map_err(|err| err.map(|mut err| err.emit()))
.ok() .ok()
.map(|s| s.node) .map(|s| s.node)
} }

View File

@ -86,7 +86,7 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::T
-> Box<dyn base::MacResult+'cx> { -> Box<dyn base::MacResult+'cx> {
let file = match get_single_str_from_tts(cx, sp, tts, "include!") { let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
Some(f) => f, Some(f) => f,
None => return DummyResult::expr(sp), None => return DummyResult::any(sp),
}; };
// The file will be added to the code map by the parser // The file will be added to the code map by the parser
let path = res_rel_file(cx, sp, file); let path = res_rel_file(cx, sp, file);

View File

@ -10,7 +10,7 @@ pub fn expand_compile_error<'cx>(cx: &'cx mut ExtCtxt,
tts: &[tokenstream::TokenTree]) tts: &[tokenstream::TokenTree])
-> Box<dyn base::MacResult + 'cx> { -> Box<dyn base::MacResult + 'cx> {
let var = match get_single_str_from_tts(cx, sp, tts, "compile_error!") { let var = match get_single_str_from_tts(cx, sp, tts, "compile_error!") {
None => return DummyResult::expr(sp), None => return DummyResult::any(sp),
Some(v) => v, Some(v) => v,
}; };

View File

@ -18,6 +18,7 @@ pub fn expand_syntax_ext(
}; };
let mut accumulator = String::new(); let mut accumulator = String::new();
let mut missing_literal = vec![]; let mut missing_literal = vec![];
let mut has_errors = false;
for e in es { for e in es {
match e.node { match e.node {
ast::ExprKind::Lit(ref lit) => match lit.node { ast::ExprKind::Lit(ref lit) => match lit.node {
@ -41,6 +42,9 @@ pub fn expand_syntax_ext(
cx.span_err(e.span, "cannot concatenate a byte string literal"); cx.span_err(e.span, "cannot concatenate a byte string literal");
} }
}, },
ast::ExprKind::Err => {
has_errors = true;
}
_ => { _ => {
missing_literal.push(e.span); missing_literal.push(e.span);
} }
@ -50,6 +54,9 @@ pub fn expand_syntax_ext(
let mut err = cx.struct_span_err(missing_literal, "expected a literal"); let mut err = cx.struct_span_err(missing_literal, "expected a literal");
err.note("only literals (like `\"foo\"`, `42` and `3.14`) can be passed to `concat!()`"); err.note("only literals (like `\"foo\"`, `42` and `3.14`) can be passed to `concat!()`");
err.emit(); err.emit();
return base::DummyResult::expr(sp);
} else if has_errors {
return base::DummyResult::expr(sp);
} }
let sp = sp.apply_mark(cx.current_expansion.mark); let sp = sp.apply_mark(cx.current_expansion.mark);
base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator))) base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator)))

View File

@ -24,7 +24,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
if tts.is_empty() { if tts.is_empty() {
cx.span_err(sp, "concat_idents! takes 1 or more arguments."); cx.span_err(sp, "concat_idents! takes 1 or more arguments.");
return DummyResult::expr(sp); return DummyResult::any(sp);
} }
let mut res_str = String::new(); let mut res_str = String::new();
@ -34,7 +34,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
TokenTree::Token(_, token::Comma) => {} TokenTree::Token(_, token::Comma) => {}
_ => { _ => {
cx.span_err(sp, "concat_idents! expecting comma."); cx.span_err(sp, "concat_idents! expecting comma.");
return DummyResult::expr(sp); return DummyResult::any(sp);
} }
} }
} else { } else {
@ -43,7 +43,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
res_str.push_str(&ident.as_str()), res_str.push_str(&ident.as_str()),
_ => { _ => {
cx.span_err(sp, "concat_idents! requires ident args."); cx.span_err(sp, "concat_idents! requires ident args.");
return DummyResult::expr(sp); return DummyResult::any(sp);
} }
} }
} }

View File

@ -79,7 +79,7 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt,
let e = match env::var(&*var.as_str()) { let e = match env::var(&*var.as_str()) {
Err(_) => { Err(_) => {
cx.span_err(sp, &msg.as_str()); cx.span_err(sp, &msg.as_str());
cx.expr_usize(sp, 0) return DummyResult::expr(sp);
} }
Ok(s) => cx.expr_str(sp, Symbol::intern(&s)), Ok(s) => cx.expr_str(sp, Symbol::intern(&s)),
}; };

View File

@ -748,18 +748,20 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
fmt fmt
} }
Ok(fmt) => fmt, Ok(fmt) => fmt,
Err(mut err) => { Err(err) => {
let sugg_fmt = match args.len() { if let Some(mut err) = err {
0 => "{}".to_string(), let sugg_fmt = match args.len() {
_ => format!("{}{{}}", "{} ".repeat(args.len())), 0 => "{}".to_string(),
}; _ => format!("{}{{}}", "{} ".repeat(args.len())),
err.span_suggestion_with_applicability( };
fmt_sp.shrink_to_lo(), err.span_suggestion_with_applicability(
"you might be missing a string literal to format with", fmt_sp.shrink_to_lo(),
format!("\"{}\", ", sugg_fmt), "you might be missing a string literal to format with",
Applicability::MaybeIncorrect, format!("\"{}\", ", sugg_fmt),
); Applicability::MaybeIncorrect,
err.emit(); );
err.emit();
}
return DummyResult::raw_expr(sp, true); return DummyResult::raw_expr(sp, true);
} }
}; };

View File

@ -0,0 +1,15 @@
use prelude::*; //~ ERROR unresolved import `prelude`
mod unresolved_env {
use env;
include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
//~^ ERROR cannot determine resolution for the macro `env`
}
mod nonexistent_env {
include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
//~^ ERROR environment variable `NON_EXISTENT` not defined
}
fn main() {}

View File

@ -0,0 +1,23 @@
error: environment variable `NON_EXISTENT` not defined
--> $DIR/issue-55897.rs:11:22
|
LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
| ^^^^^^^^^^^^^^^^^^^^
error[E0432]: unresolved import `prelude`
--> $DIR/issue-55897.rs:1:5
|
LL | use prelude::*; //~ ERROR unresolved import `prelude`
| ^^^^^^^ did you mean `std::prelude`?
error: cannot determine resolution for the macro `env`
--> $DIR/issue-55897.rs:6:22
|
LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
| ^^^
|
= note: import resolution is stuck, try simplifying macro imports
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0432`.

View File

@ -1,5 +1,3 @@
fn main() { fn main() {
print!(testo!()); print!(testo!()); //~ ERROR cannot find macro `testo!` in this scope
//~^ ERROR: format argument must be a string literal
//~| ERROR: cannot find macro `testo!` in this scope
} }

View File

@ -1,18 +1,8 @@
error: format argument must be a string literal
--> $DIR/issue-11692-1.rs:2:12
|
LL | print!(testo!());
| ^^^^^^^^
help: you might be missing a string literal to format with
|
LL | print!("{}", testo!());
| ^^^^^
error: cannot find macro `testo!` in this scope error: cannot find macro `testo!` in this scope
--> $DIR/issue-11692-1.rs:2:12 --> $DIR/issue-11692-1.rs:2:12
| |
LL | print!(testo!()); LL | print!(testo!()); //~ ERROR cannot find macro `testo!` in this scope
| ^^^^^ | ^^^^^
error: aborting due to 2 previous errors error: aborting due to previous error

View File

@ -1,4 +1,3 @@
fn main() { fn main() {
concat!(test!()); //~ ERROR cannot find macro `test!` in this scope concat!(test!()); //~ ERROR cannot find macro `test!` in this scope
//~| ERROR expected a literal
} }

View File

@ -1,16 +1,8 @@
error: expected a literal
--> $DIR/issue-11692-2.rs:2:13
|
LL | concat!(test!()); //~ ERROR cannot find macro `test!` in this scope
| ^^^^^^^
|
= note: only literals (like `"foo"`, `42` and `3.14`) can be passed to `concat!()`
error: cannot find macro `test!` in this scope error: cannot find macro `test!` in this scope
--> $DIR/issue-11692-2.rs:2:13 --> $DIR/issue-11692-2.rs:2:13
| |
LL | concat!(test!()); //~ ERROR cannot find macro `test!` in this scope LL | concat!(test!()); //~ ERROR cannot find macro `test!` in this scope
| ^^^^ | ^^^^
error: aborting due to 2 previous errors error: aborting due to previous error