Skip to content

Improve error recovery for some built-in macros #57205

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 30, 2018
Merged
Show file tree
Hide file tree
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: 5 additions & 4 deletions src/libsyntax/ext/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -995,7 +995,7 @@ pub fn expr_to_spanned_string<'a>(
cx: &'a mut ExtCtxt,
expr: P<ast::Expr>,
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.
let expr = expr.map(|mut expr| {
expr.span = expr.span.apply_mark(cx.current_expansion.mark);
Expand All @@ -1007,16 +1007,17 @@ pub fn expr_to_spanned_string<'a>(
Err(match expr.node {
ast::ExprKind::Lit(ref l) => match l.node {
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)
-> Option<(Symbol, ast::StrStyle)> {
expr_to_spanned_string(cx, expr, err_msg)
.map_err(|mut err| err.emit())
.map_err(|err| err.map(|mut err| err.emit()))
.ok()
.map(|s| s.node)
}
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/ext/source_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::T
-> Box<dyn base::MacResult+'cx> {
let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
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
let path = res_rel_file(cx, sp, file);
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax_ext/compile_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub fn expand_compile_error<'cx>(cx: &'cx mut ExtCtxt,
tts: &[tokenstream::TokenTree])
-> Box<dyn base::MacResult + 'cx> {
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,
};

Expand Down
7 changes: 7 additions & 0 deletions src/libsyntax_ext/concat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub fn expand_syntax_ext(
};
let mut accumulator = String::new();
let mut missing_literal = vec![];
let mut has_errors = false;
for e in es {
match e.node {
ast::ExprKind::Lit(ref lit) => match lit.node {
Expand All @@ -41,6 +42,9 @@ pub fn expand_syntax_ext(
cx.span_err(e.span, "cannot concatenate a byte string literal");
}
},
ast::ExprKind::Err => {
has_errors = true;
}
_ => {
missing_literal.push(e.span);
}
Expand All @@ -50,6 +54,9 @@ pub fn expand_syntax_ext(
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.emit();
return base::DummyResult::expr(sp);
} else if has_errors {
return base::DummyResult::expr(sp);
}
let sp = sp.apply_mark(cx.current_expansion.mark);
base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator)))
Expand Down
6 changes: 3 additions & 3 deletions src/libsyntax_ext/concat_idents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,

if tts.is_empty() {
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();
Expand All @@ -34,7 +34,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
TokenTree::Token(_, token::Comma) => {}
_ => {
cx.span_err(sp, "concat_idents! expecting comma.");
return DummyResult::expr(sp);
return DummyResult::any(sp);
}
}
} else {
Expand All @@ -43,7 +43,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
res_str.push_str(&ident.as_str()),
_ => {
cx.span_err(sp, "concat_idents! requires ident args.");
return DummyResult::expr(sp);
return DummyResult::any(sp);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax_ext/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt,
let e = match env::var(&*var.as_str()) {
Err(_) => {
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)),
};
Expand Down
26 changes: 14 additions & 12 deletions src/libsyntax_ext/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -748,18 +748,20 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
fmt
}
Ok(fmt) => fmt,
Err(mut err) => {
let sugg_fmt = match args.len() {
0 => "{}".to_string(),
_ => format!("{}{{}}", "{} ".repeat(args.len())),
};
err.span_suggestion_with_applicability(
fmt_sp.shrink_to_lo(),
"you might be missing a string literal to format with",
format!("\"{}\", ", sugg_fmt),
Applicability::MaybeIncorrect,
);
err.emit();
Err(err) => {
if let Some(mut err) = err {
let sugg_fmt = match args.len() {
0 => "{}".to_string(),
_ => format!("{}{{}}", "{} ".repeat(args.len())),
};
err.span_suggestion_with_applicability(
fmt_sp.shrink_to_lo(),
"you might be missing a string literal to format with",
format!("\"{}\", ", sugg_fmt),
Applicability::MaybeIncorrect,
);
err.emit();
}
return DummyResult::raw_expr(sp, true);
}
};
Expand Down
15 changes: 15 additions & 0 deletions src/test/ui/extenv/issue-55897.rs
Original file line number Diff line number Diff line change
@@ -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() {}
23 changes: 23 additions & 0 deletions src/test/ui/extenv/issue-55897.stderr
Original file line number Diff line number Diff line change
@@ -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`.
4 changes: 1 addition & 3 deletions src/test/ui/issues/issue-11692-1.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
fn main() {
print!(testo!());
//~^ ERROR: format argument must be a string literal
//~| ERROR: cannot find macro `testo!` in this scope
print!(testo!()); //~ ERROR cannot find macro `testo!` in this scope
}
14 changes: 2 additions & 12 deletions src/test/ui/issues/issue-11692-1.stderr
Original file line number Diff line number Diff line change
@@ -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
--> $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

1 change: 0 additions & 1 deletion src/test/ui/issues/issue-11692-2.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
fn main() {
concat!(test!()); //~ ERROR cannot find macro `test!` in this scope
//~| ERROR expected a literal
}
10 changes: 1 addition & 9 deletions src/test/ui/issues/issue-11692-2.stderr
Original file line number Diff line number Diff line change
@@ -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
--> $DIR/issue-11692-2.rs:2:13
|
LL | concat!(test!()); //~ ERROR cannot find macro `test!` in this scope
| ^^^^

error: aborting due to 2 previous errors
error: aborting due to previous error