Skip to content

Commit b2bcb72

Browse files
committed
Work towards a non-panicing parser (libsyntax)
- Functions in parser.rs return PResult<> rather than panicing - Other functions in libsyntax call panic! explicitly for now if they rely on panicing behaviour. - 'panictry!' macro added as scaffolding while converting panicing functions. (This does the same as 'unwrap()' but is easier to grep for and turn into try!()) - Leaves panicing wrappers for the following functions so that the quote_* macros behave the same: - parse_expr, parse_item, parse_pat, parse_arm, parse_ty, parse_stmt
1 parent f73f323 commit b2bcb72

23 files changed

+1412
-1315
lines changed

src/librustc/metadata/creader.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,10 @@ impl<'a> CrateReader<'a> {
528528
source_name.clone(),
529529
body);
530530
let lo = p.span.lo;
531-
let body = p.parse_all_token_trees();
531+
let body = match p.parse_all_token_trees() {
532+
Ok(body) => body,
533+
Err(err) => panic!(err),
534+
};
532535
let span = mk_sp(lo, p.last_span.hi);
533536
p.abort_if_errors();
534537
macros.push(ast::MacroDef {

src/librustc/session/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,13 @@ impl Session {
6868
if self.opts.treat_err_as_bug {
6969
self.span_bug(sp, msg);
7070
}
71-
self.diagnostic().span_fatal(sp, msg)
71+
panic!(self.diagnostic().span_fatal(sp, msg))
7272
}
7373
pub fn span_fatal_with_code(&self, sp: Span, msg: &str, code: &str) -> ! {
7474
if self.opts.treat_err_as_bug {
7575
self.span_bug(sp, msg);
7676
}
77-
self.diagnostic().span_fatal_with_code(sp, msg, code)
77+
panic!(self.diagnostic().span_fatal_with_code(sp, msg, code))
7878
}
7979
pub fn fatal(&self, msg: &str) -> ! {
8080
if self.opts.treat_err_as_bug {

src/libsyntax/attr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -503,8 +503,8 @@ pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[P<MetaItem>]) {
503503
let name = meta.name();
504504

505505
if !set.insert(name.clone()) {
506-
diagnostic.span_fatal(meta.span,
507-
&format!("duplicate meta item `{}`", name));
506+
panic!(diagnostic.span_fatal(meta.span,
507+
&format!("duplicate meta item `{}`", name)));
508508
}
509509
}
510510
}

src/libsyntax/diagnostic.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ pub trait Emitter {
7272
/// from the diagnostics. You can use this with the `Any` trait to figure out
7373
/// how a rustc task died (if so desired).
7474
#[derive(Copy, Clone)]
75+
#[must_use]
7576
pub struct FatalError;
7677

7778
/// Signifies that the compiler died with an explicit call to `.bug`
@@ -88,13 +89,13 @@ pub struct SpanHandler {
8889
}
8990

9091
impl SpanHandler {
91-
pub fn span_fatal(&self, sp: Span, msg: &str) -> ! {
92+
pub fn span_fatal(&self, sp: Span, msg: &str) -> FatalError {
9293
self.handler.emit(Some((&self.cm, sp)), msg, Fatal);
93-
panic!(FatalError);
94+
return FatalError;
9495
}
95-
pub fn span_fatal_with_code(&self, sp: Span, msg: &str, code: &str) -> ! {
96+
pub fn span_fatal_with_code(&self, sp: Span, msg: &str, code: &str) -> FatalError {
9697
self.handler.emit_with_code(Some((&self.cm, sp)), msg, code, Fatal);
97-
panic!(FatalError);
98+
return FatalError;
9899
}
99100
pub fn span_err(&self, sp: Span, msg: &str) {
100101
self.handler.emit(Some((&self.cm, sp)), msg, Error);

src/libsyntax/ext/asm.rs

+25-14
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,17 @@ use parse::token::InternedString;
2323
use parse::token;
2424
use ptr::P;
2525

26+
macro_rules! panictry {
27+
($e:expr) => ({
28+
use std::result::Result::{Ok, Err};
29+
30+
match $e {
31+
Ok(e) => e,
32+
Err(e) => panic!(e),
33+
}
34+
})
35+
}
36+
2637
enum State {
2738
Asm,
2839
Outputs,
@@ -91,16 +102,16 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
91102
p.token != token::ModSep {
92103

93104
if outputs.len() != 0 {
94-
p.eat(&token::Comma);
105+
panictry!(p.eat(&token::Comma));
95106
}
96107

97-
let (constraint, _str_style) = p.parse_str();
108+
let (constraint, _str_style) = panictry!(p.parse_str());
98109

99110
let span = p.last_span;
100111

101-
p.expect(&token::OpenDelim(token::Paren));
112+
panictry!(p.expect(&token::OpenDelim(token::Paren)));
102113
let out = p.parse_expr();
103-
p.expect(&token::CloseDelim(token::Paren));
114+
panictry!(p.expect(&token::CloseDelim(token::Paren)));
104115

105116
// Expands a read+write operand into two operands.
106117
//
@@ -131,20 +142,20 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
131142
p.token != token::ModSep {
132143

133144
if inputs.len() != 0 {
134-
p.eat(&token::Comma);
145+
panictry!(p.eat(&token::Comma));
135146
}
136147

137-
let (constraint, _str_style) = p.parse_str();
148+
let (constraint, _str_style) = panictry!(p.parse_str());
138149

139150
if constraint.starts_with("=") {
140151
cx.span_err(p.last_span, "input operand constraint contains '='");
141152
} else if constraint.starts_with("+") {
142153
cx.span_err(p.last_span, "input operand constraint contains '+'");
143154
}
144155

145-
p.expect(&token::OpenDelim(token::Paren));
156+
panictry!(p.expect(&token::OpenDelim(token::Paren)));
146157
let input = p.parse_expr();
147-
p.expect(&token::CloseDelim(token::Paren));
158+
panictry!(p.expect(&token::CloseDelim(token::Paren)));
148159

149160
inputs.push((constraint, input));
150161
}
@@ -155,10 +166,10 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
155166
p.token != token::ModSep {
156167

157168
if clobs.len() != 0 {
158-
p.eat(&token::Comma);
169+
panictry!(p.eat(&token::Comma));
159170
}
160171

161-
let (s, _str_style) = p.parse_str();
172+
let (s, _str_style) = panictry!(p.parse_str());
162173

163174
if OPTIONS.iter().any(|&opt| s == opt) {
164175
cx.span_warn(p.last_span, "expected a clobber, found an option");
@@ -167,7 +178,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
167178
}
168179
}
169180
Options => {
170-
let (option, _str_style) = p.parse_str();
181+
let (option, _str_style) = panictry!(p.parse_str());
171182

172183
if option == "volatile" {
173184
// Indicates that the inline assembly has side effects
@@ -182,7 +193,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
182193
}
183194

184195
if p.token == token::Comma {
185-
p.eat(&token::Comma);
196+
panictry!(p.eat(&token::Comma));
186197
}
187198
}
188199
StateNone => ()
@@ -194,12 +205,12 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
194205
match (&p.token, state.next(), state.next().next()) {
195206
(&token::Colon, StateNone, _) |
196207
(&token::ModSep, _, StateNone) => {
197-
p.bump();
208+
panictry!(p.bump());
198209
break 'statement;
199210
}
200211
(&token::Colon, st, _) |
201212
(&token::ModSep, _, st) => {
202-
p.bump();
213+
panictry!(p.bump());
203214
state = st;
204215
}
205216
(&token::Eof, _, _) => break 'statement,

src/libsyntax/ext/base.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -652,9 +652,9 @@ impl<'a> ExtCtxt<'a> {
652652
pub fn bt_push(&mut self, ei: ExpnInfo) {
653653
self.recursion_count += 1;
654654
if self.recursion_count > self.ecfg.recursion_limit {
655-
self.span_fatal(ei.call_site,
655+
panic!(self.span_fatal(ei.call_site,
656656
&format!("recursion limit reached while expanding the macro `{}`",
657-
ei.callee.name));
657+
ei.callee.name)));
658658
}
659659

660660
let mut call_site = ei.call_site;
@@ -699,7 +699,7 @@ impl<'a> ExtCtxt<'a> {
699699
/// value doesn't have to match anything)
700700
pub fn span_fatal(&self, sp: Span, msg: &str) -> ! {
701701
self.print_backtrace();
702-
self.parse_sess.span_diagnostic.span_fatal(sp, msg);
702+
panic!(self.parse_sess.span_diagnostic.span_fatal(sp, msg));
703703
}
704704

705705
/// Emit `msg` attached to `sp`, without immediately stopping
@@ -817,7 +817,7 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
817817
let mut es = Vec::new();
818818
while p.token != token::Eof {
819819
es.push(cx.expander().fold_expr(p.parse_expr()));
820-
if p.eat(&token::Comma) {
820+
if panictry!(p.eat(&token::Comma)){
821821
continue;
822822
}
823823
if p.token != token::Eof {

src/libsyntax/ext/cfg.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub fn expand_cfg<'cx>(cx: &mut ExtCtxt,
2929
let mut p = cx.new_parser_from_tts(tts);
3030
let cfg = p.parse_meta_item();
3131

32-
if !p.eat(&token::Eof) {
32+
if !panictry!(p.eat(&token::Eof)){
3333
cx.span_err(sp, "expected 1 cfg-pattern");
3434
return DummyResult::expr(sp);
3535
}

src/libsyntax/ext/expand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1684,7 +1684,7 @@ mod test {
16841684

16851685
fn expand_crate_str(crate_str: String) -> ast::Crate {
16861686
let ps = parse::new_parse_sess();
1687-
let crate_ast = string_to_parser(&ps, crate_str).parse_crate_mod();
1687+
let crate_ast = panictry!(string_to_parser(&ps, crate_str).parse_crate_mod());
16881688
// the cfg argument actually does matter, here...
16891689
expand_crate(&ps,test_ecfg(),vec!(),vec!(),crate_ast)
16901690
}

src/libsyntax/ext/format.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,17 @@ use ptr::P;
2424
use std::collections::HashMap;
2525
use std::iter::repeat;
2626

27+
macro_rules! panictry {
28+
($e:expr) => ({
29+
use std::result::Result::{Ok, Err};
30+
31+
match $e {
32+
Ok(e) => e,
33+
Err(e) => { panic!(e); }
34+
}
35+
})
36+
}
37+
2738
#[derive(PartialEq)]
2839
enum ArgumentType {
2940
Known(String),
@@ -92,7 +103,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
92103
let fmtstr = p.parse_expr();
93104
let mut named = false;
94105
while p.token != token::Eof {
95-
if !p.eat(&token::Comma) {
106+
if !panictry!(p.eat(&token::Comma)) {
96107
ecx.span_err(sp, "expected token: `,`");
97108
return None;
98109
}
@@ -101,7 +112,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
101112
named = true;
102113
let ident = match p.token {
103114
token::Ident(i, _) => {
104-
p.bump();
115+
panictry!(p.bump());
105116
i
106117
}
107118
_ if named => {
@@ -120,7 +131,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
120131
let interned_name = token::get_ident(ident);
121132
let name = &interned_name[..];
122133

123-
p.expect(&token::Eq);
134+
panictry!(p.expect(&token::Eq));
124135
let e = p.parse_expr();
125136
match names.get(name) {
126137
None => {}

src/libsyntax/ext/quote.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -781,11 +781,11 @@ fn parse_arguments_to_quote(cx: &ExtCtxt, tts: &[ast::TokenTree])
781781
p.quote_depth += 1;
782782

783783
let cx_expr = p.parse_expr();
784-
if !p.eat(&token::Comma) {
785-
p.fatal("expected token `,`");
784+
if !panictry!(p.eat(&token::Comma)) {
785+
panic!(p.fatal("expected token `,`"));
786786
}
787787

788-
let tts = p.parse_all_token_trees();
788+
let tts = panictry!(p.parse_all_token_trees());
789789
p.abort_if_errors();
790790

791791
(cx_expr, tts)

src/libsyntax/ext/source_util.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,11 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree
117117
while self.p.token != token::Eof {
118118
match self.p.parse_item() {
119119
Some(item) => ret.push(item),
120-
None => self.p.span_fatal(
120+
None => panic!(self.p.span_fatal(
121121
self.p.span,
122122
&format!("expected item, found `{}`",
123123
self.p.this_token_to_string())
124-
)
124+
))
125125
}
126126
}
127127
Some(ret)

src/libsyntax/ext/tt/macro_parser.rs

+15-15
Original file line numberDiff line numberDiff line change
@@ -226,10 +226,10 @@ pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc<NamedMatch>])
226226
}
227227
Occupied(..) => {
228228
let string = token::get_ident(bind_name);
229-
p_s.span_diagnostic
229+
panic!(p_s.span_diagnostic
230230
.span_fatal(sp,
231231
&format!("duplicated bind name: {}",
232-
&string))
232+
&string)))
233233
}
234234
}
235235
}
@@ -260,10 +260,10 @@ pub fn parse_or_else(sess: &ParseSess,
260260
match parse(sess, cfg, rdr, &ms[..]) {
261261
Success(m) => m,
262262
Failure(sp, str) => {
263-
sess.span_diagnostic.span_fatal(sp, &str[..])
263+
panic!(sess.span_diagnostic.span_fatal(sp, &str[..]))
264264
}
265265
Error(sp, str) => {
266-
sess.span_diagnostic.span_fatal(sp, &str[..])
266+
panic!(sess.span_diagnostic.span_fatal(sp, &str[..]))
267267
}
268268
}
269269
}
@@ -512,46 +512,46 @@ pub fn parse_nt(p: &mut Parser, sp: Span, name: &str) -> Nonterminal {
512512
match name {
513513
"tt" => {
514514
p.quote_depth += 1; //but in theory, non-quoted tts might be useful
515-
let res = token::NtTT(P(p.parse_token_tree()));
515+
let res = token::NtTT(P(panictry!(p.parse_token_tree())));
516516
p.quote_depth -= 1;
517517
return res;
518518
}
519519
_ => {}
520520
}
521521
// check at the beginning and the parser checks after each bump
522-
p.check_unknown_macro_variable();
522+
panictry!(p.check_unknown_macro_variable());
523523
match name {
524524
"item" => match p.parse_item() {
525525
Some(i) => token::NtItem(i),
526-
None => p.fatal("expected an item keyword")
526+
None => panic!(p.fatal("expected an item keyword"))
527527
},
528-
"block" => token::NtBlock(p.parse_block()),
528+
"block" => token::NtBlock(panictry!(p.parse_block())),
529529
"stmt" => match p.parse_stmt() {
530530
Some(s) => token::NtStmt(s),
531-
None => p.fatal("expected a statement")
531+
None => panic!(p.fatal("expected a statement"))
532532
},
533533
"pat" => token::NtPat(p.parse_pat()),
534534
"expr" => token::NtExpr(p.parse_expr()),
535535
"ty" => token::NtTy(p.parse_ty()),
536536
// this could be handled like a token, since it is one
537537
"ident" => match p.token {
538-
token::Ident(sn,b) => { p.bump(); token::NtIdent(box sn,b) }
538+
token::Ident(sn,b) => { panictry!(p.bump()); token::NtIdent(box sn,b) }
539539
_ => {
540540
let token_str = pprust::token_to_string(&p.token);
541-
p.fatal(&format!("expected ident, found {}",
542-
&token_str[..]))
541+
panic!(p.fatal(&format!("expected ident, found {}",
542+
&token_str[..])))
543543
}
544544
},
545545
"path" => {
546-
token::NtPath(box p.parse_path(LifetimeAndTypesWithoutColons))
546+
token::NtPath(box panictry!(p.parse_path(LifetimeAndTypesWithoutColons)))
547547
}
548548
"meta" => token::NtMeta(p.parse_meta_item()),
549549
_ => {
550-
p.span_fatal_help(sp,
550+
panic!(p.span_fatal_help(sp,
551551
&format!("invalid fragment specifier `{}`", name),
552552
"valid fragment specifiers are `ident`, `block`, \
553553
`stmt`, `expr`, `pat`, `ty`, `path`, `meta`, `tt` \
554-
and `item`")
554+
and `item`"))
555555
}
556556
}
557557
}

0 commit comments

Comments
 (0)