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);
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)
}
-> 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);
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,
};
};
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 {
cx.span_err(e.span, "cannot concatenate a byte string literal");
}
},
+ ast::ExprKind::Err => {
+ has_errors = true;
+ }
_ => {
missing_literal.push(e.span);
}
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)))
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();
TokenTree::Token(_, token::Comma) => {}
_ => {
cx.span_err(sp, "concat_idents! expecting comma.");
- return DummyResult::expr(sp);
+ return DummyResult::any(sp);
}
}
} else {
res_str.push_str(&ident.as_str()),
_ => {
cx.span_err(sp, "concat_idents! requires ident args.");
- return DummyResult::expr(sp);
+ return DummyResult::any(sp);
}
}
}
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)),
};
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);
}
};
--- /dev/null
+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() {}
--- /dev/null
+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`.
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
}
-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
fn main() {
concat!(test!()); //~ ERROR cannot find macro `test!` in this scope
- //~| ERROR expected a literal
}
-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