Skip to content

syntax::ext: replace span_fatal with span_err in many places. #11644

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
Jan 20, 2014
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: 6 additions & 3 deletions src/libsyntax/ext/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,12 @@ pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
while continue_ {
match state {
Asm => {
let (s, style) =
expr_to_str(cx, p.parse_expr(),
"inline assembly must be a string literal.");
let (s, style) = match expr_to_str(cx, p.parse_expr(),
"inline assembly must be a string literal.") {
Some((s, st)) => (s, st),
// let compilation continue
None => return MacResult::dummy_expr(),
};
asm = s;
asm_str_style = Some(style);
}
Expand Down
76 changes: 60 additions & 16 deletions src/libsyntax/ext/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,17 @@ pub enum MacResult {
MRAny(@AnyMacro),
MRDef(MacroDef),
}
impl MacResult {
/// Create an empty expression MacResult; useful for satisfying
/// type signatures after emitting a non-fatal error (which stop
/// compilation well before the validity (or otherwise)) of the
/// expression are checked.
pub fn dummy_expr() -> MacResult {
MRExpr(@ast::Expr {
id: ast::DUMMY_NODE_ID, node: ast::ExprLogLevel, span: codemap::DUMMY_SP
})
}
}

pub enum SyntaxExtension {
// #[deriving] and such
Expand Down Expand Up @@ -364,10 +375,27 @@ impl<'a> ExtCtxt<'a> {
_ => self.bug("tried to pop without a push")
}
}
/// Emit `msg` attached to `sp`, and stop compilation immediately.
///
/// `span_err` should be strongly prefered 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(&self, sp: Span, msg: &str) -> ! {
self.print_backtrace();
self.parse_sess.span_diagnostic.span_fatal(sp, msg);
}

/// Emit `msg` attached to `sp`, without immediately stopping
/// compilation.
///
/// Compilation will be stopped in the near future (at the end of
/// the macro expansion phase).
pub fn span_err(&self, sp: Span, msg: &str) {
self.print_backtrace();
self.parse_sess.span_diagnostic.span_err(sp, msg);
Expand Down Expand Up @@ -402,53 +430,69 @@ impl<'a> ExtCtxt<'a> {
}
}

pub fn expr_to_str(cx: &ExtCtxt, expr: @ast::Expr, err_msg: &str) -> (@str, ast::StrStyle) {
/// Extract a string literal from `expr`, emitting `err_msg` if `expr`
/// is not a string literal. This does not stop compilation on error,
/// merely emits a non-fatal error and returns None.
pub fn expr_to_str(cx: &ExtCtxt, expr: @ast::Expr,
err_msg: &str) -> Option<(@str, ast::StrStyle)> {
match expr.node {
ast::ExprLit(l) => match l.node {
ast::LitStr(s, style) => (s, style),
_ => cx.span_fatal(l.span, err_msg)
ast::LitStr(s, style) => return Some((s, style)),
_ => cx.span_err(l.span, err_msg)
},
_ => cx.span_fatal(expr.span, err_msg)
_ => cx.span_err(expr.span, err_msg)
}
None
}

/// Non-fatally assert that `tts` is empty. Note that this function
/// returns even when `tts` is non-empty, macros that *need* to stop
/// compilation should call
/// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be
/// done as rarely as possible).
pub fn check_zero_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree],
name: &str) {
if tts.len() != 0 {
cx.span_fatal(sp, format!("{} takes no arguments", name));
cx.span_err(sp, format!("{} takes no arguments", name));
}
}

/// Extract the string literal from the first token of `tts`. If this
/// is not a string literal, emit an error and return None.
pub fn get_single_str_from_tts(cx: &ExtCtxt,
sp: Span,
tts: &[ast::TokenTree],
name: &str)
-> @str {
-> Option<@str> {
if tts.len() != 1 {
cx.span_fatal(sp, format!("{} takes 1 argument.", name));
}

match tts[0] {
ast::TTTok(_, token::LIT_STR(ident))
| ast::TTTok(_, token::LIT_STR_RAW(ident, _)) => cx.str_of(ident),
_ => cx.span_fatal(sp, format!("{} requires a string.", name)),
cx.span_err(sp, format!("{} takes 1 argument.", name));
} else {
match tts[0] {
ast::TTTok(_, token::LIT_STR(ident))
| ast::TTTok(_, token::LIT_STR_RAW(ident, _)) => return Some(cx.str_of(ident)),
_ => cx.span_err(sp, format!("{} requires a string.", name)),
}
}
None
}

/// Extract comma-separated expressions from `tts`. If there is a
/// parsing error, emit a non-fatal error and return None.
pub fn get_exprs_from_tts(cx: &ExtCtxt,
sp: Span,
tts: &[ast::TokenTree]) -> ~[@ast::Expr] {
tts: &[ast::TokenTree]) -> Option<~[@ast::Expr]> {
let mut p = parse::new_parser_from_tts(cx.parse_sess(),
cx.cfg(),
tts.to_owned());
let mut es = ~[];
while p.token != token::EOF {
if es.len() != 0 && !p.eat(&token::COMMA) {
cx.span_fatal(sp, "expected token: `,`");
cx.span_err(sp, "expected token: `,`");
return None;
}
es.push(p.parse_expr());
}
es
Some(es)
}

// in order to have some notion of scoping for macros,
Expand Down
5 changes: 4 additions & 1 deletion src/libsyntax/ext/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ use std::char;

pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult {
// Gather all argument expressions
let exprs = get_exprs_from_tts(cx, sp, tts);
let exprs = match get_exprs_from_tts(cx, sp, tts) {
None => return MacResult::dummy_expr(),
Some(e) => e,
};
let mut bytes = ~[];

for expr in exprs.iter() {
Expand Down
5 changes: 4 additions & 1 deletion src/libsyntax/ext/concat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ use ext::build::AstBuilder;
pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
sp: codemap::Span,
tts: &[ast::TokenTree]) -> base::MacResult {
let es = base::get_exprs_from_tts(cx, sp, tts);
let es = match base::get_exprs_from_tts(cx, sp, tts) {
Some(e) => e,
None => return base::MacResult::dummy_expr()
};
let mut accumulator = ~"";
for e in es.move_iter() {
let e = cx.expand_expr(e);
Expand Down
10 changes: 8 additions & 2 deletions src/libsyntax/ext/concat_idents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,18 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
if i & 1 == 1 {
match *e {
ast::TTTok(_, token::COMMA) => (),
_ => cx.span_fatal(sp, "concat_idents! expecting comma.")
_ => {
cx.span_err(sp, "concat_idents! expecting comma.");
return MacResult::dummy_expr();
}
}
} else {
match *e {
ast::TTTok(_, token::IDENT(ident,_)) => res_str.push_str(cx.str_of(ident)),
_ => cx.span_fatal(sp, "concat_idents! requires ident args.")
_ => {
cx.span_err(sp, "concat_idents! requires ident args.");
return MacResult::dummy_expr();
}
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/libsyntax/ext/deriving/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ fn default_substructure(cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Exp
}
}
StaticEnum(..) => {
cx.span_fatal(span, "`Default` cannot be derived for enums, \
only structs")
cx.span_err(span, "`Default` cannot be derived for enums, only structs");
// let compilation continue
cx.expr_uint(span, 0)
}
_ => cx.bug("Non-static method in `deriving(Default)`")
};
Expand Down
4 changes: 3 additions & 1 deletion src/libsyntax/ext/deriving/rand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ fn rand_substructure(cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
}
StaticEnum(_, ref variants) => {
if variants.is_empty() {
cx.span_fatal(span, "`Rand` cannot be derived for enums with no variants");
cx.span_err(span, "`Rand` cannot be derived for enums with no variants");
// let compilation continue
return cx.expr_uint(span, 0);
}

let variant_count = cx.expr_uint(span, variants.len());
Expand Down
5 changes: 3 additions & 2 deletions src/libsyntax/ext/deriving/zero.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,9 @@ fn zero_substructure(cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
}
}
StaticEnum(..) => {
cx.span_fatal(span, "`Zero` cannot be derived for enums, \
only structs")
cx.span_err(span, "`Zero` cannot be derived for enums, only structs");
// let compilation continue
cx.expr_uint(span, 0)
}
_ => cx.bug("Non-static method in `deriving(Zero)`")
};
Expand Down
39 changes: 28 additions & 11 deletions src/libsyntax/ext/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ use std::os;

pub fn expand_option_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-> base::MacResult {
let var = get_single_str_from_tts(cx, sp, tts, "option_env!");
let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") {
None => return MacResult::dummy_expr(),
Some(v) => v
};

let e = match os::getenv(var) {
None => quote_expr!(cx, ::std::option::None::<&'static str>),
Expand All @@ -35,24 +38,38 @@ pub fn expand_option_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])

pub fn expand_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-> base::MacResult {
let exprs = get_exprs_from_tts(cx, sp, tts);

if exprs.len() == 0 {
cx.span_fatal(sp, "env! takes 1 or 2 arguments");
}
let exprs = match get_exprs_from_tts(cx, sp, tts) {
Some([]) => {
cx.span_err(sp, "env! takes 1 or 2 arguments");
return MacResult::dummy_expr();
}
None => return MacResult::dummy_expr(),
Some(exprs) => exprs
};

let (var, _var_str_style) = expr_to_str(cx, exprs[0], "expected string literal");
let var = match expr_to_str(cx, exprs[0], "expected string literal") {
None => return MacResult::dummy_expr(),
Some((v, _style)) => v
};
let msg = match exprs.len() {
1 => format!("environment variable `{}` not defined", var).to_managed(),
2 => {
let (s, _style) = expr_to_str(cx, exprs[1], "expected string literal");
s
match expr_to_str(cx, exprs[1], "expected string literal") {
None => return MacResult::dummy_expr(),
Some((s, _style)) => s
}
}
_ => {
cx.span_err(sp, "env! takes 1 or 2 arguments");
return MacResult::dummy_expr();
}
_ => cx.span_fatal(sp, "env! takes 1 or 2 arguments")
};

let e = match os::getenv(var) {
None => cx.span_fatal(sp, msg),
None => {
cx.span_err(sp, msg);
cx.expr_uint(sp, 0)
}
Some(s) => cx.expr_str(sp, s.to_managed())
};
MRExpr(e)
Expand Down
Loading