Skip to content

Commit 26dae32

Browse files
committed
Put in -Z continue_parse_after_error
This works by adding a method, `fn abort_if_no_parse_recovery`, to the diagnostic handler in `syntax::errors`, and calling it after each error is emitted in the parser. (We might consider adding a debugflag to do such aborts in other places where we are currently attempting recovery, such as resolve, but I think the parser is the really important case to handle in the face of rust-lang#31994 and the parser bugs of varying degrees that were injected by parse error recovery.)
1 parent 40deb27 commit 26dae32

File tree

8 files changed

+55
-14
lines changed

8 files changed

+55
-14
lines changed

src/librustc/session/config.rs

+6
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ pub struct Options {
138138
pub no_trans: bool,
139139
pub error_format: ErrorOutputType,
140140
pub treat_err_as_bug: bool,
141+
pub continue_parse_after_error: bool,
141142
pub mir_opt_level: usize,
142143

143144
/// if true, build up the dep-graph
@@ -259,6 +260,7 @@ pub fn basic_options() -> Options {
259260
parse_only: false,
260261
no_trans: false,
261262
treat_err_as_bug: false,
263+
continue_parse_after_error: false,
262264
mir_opt_level: 1,
263265
build_dep_graph: false,
264266
dump_dep_graph: false,
@@ -633,6 +635,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
633635
"run all passes except translation; no output"),
634636
treat_err_as_bug: bool = (false, parse_bool,
635637
"treat all errors that occur as bugs"),
638+
continue_parse_after_error: bool = (false, parse_bool,
639+
"attempt to recover from parse errors (experimental)"),
636640
incr_comp: bool = (false, parse_bool,
637641
"enable incremental compilation (experimental)"),
638642
dump_dep_graph: bool = (false, parse_bool,
@@ -1045,6 +1049,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
10451049
let parse_only = debugging_opts.parse_only;
10461050
let no_trans = debugging_opts.no_trans;
10471051
let treat_err_as_bug = debugging_opts.treat_err_as_bug;
1052+
let continue_parse_after_error = debugging_opts.continue_parse_after_error;
10481053
let mir_opt_level = debugging_opts.mir_opt_level.unwrap_or(1);
10491054
let incremental_compilation = debugging_opts.incr_comp;
10501055
let dump_dep_graph = debugging_opts.dump_dep_graph;
@@ -1228,6 +1233,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
12281233
parse_only: parse_only,
12291234
no_trans: no_trans,
12301235
treat_err_as_bug: treat_err_as_bug,
1236+
continue_parse_after_error: continue_parse_after_error,
12311237
mir_opt_level: mir_opt_level,
12321238
build_dep_graph: incremental_compilation || dump_dep_graph,
12331239
dump_dep_graph: dump_dep_graph,

src/librustc/session/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ pub fn build_session(sopts: config::Options,
414414
.last()
415415
.unwrap_or(true);
416416
let treat_err_as_bug = sopts.treat_err_as_bug;
417+
let continue_parse_after_error = sopts.continue_parse_after_error;
417418

418419
let codemap = Rc::new(codemap::CodeMap::new());
419420
let emitter: Box<Emitter> = match sopts.error_format {
@@ -428,6 +429,7 @@ pub fn build_session(sopts: config::Options,
428429
let diagnostic_handler =
429430
errors::Handler::with_emitter(can_print_warnings,
430431
treat_err_as_bug,
432+
continue_parse_after_error,
431433
emitter);
432434

433435
build_session_(sopts, local_crate_source_file, diagnostic_handler, codemap, cstore)

src/librustc_trans/back/write.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -908,7 +908,7 @@ fn run_work_multithreaded(sess: &Session,
908908
futures.push(rx);
909909

910910
thread::Builder::new().name(format!("codegen-{}", i)).spawn(move || {
911-
let diag_handler = Handler::with_emitter(true, false, box diag_emitter);
911+
let diag_handler = Handler::with_emitter(true, false, false, box diag_emitter);
912912

913913
// Must construct cgcx inside the proc because it has non-Send
914914
// fields.

src/librustdoc/core.rs

+1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
123123
None,
124124
true,
125125
false,
126+
false,
126127
codemap.clone());
127128

128129
let cstore = Rc::new(CStore::new(token::get_ident_interner()));

src/librustdoc/test.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ pub fn run(input: &str,
7777
None,
7878
true,
7979
false,
80+
false,
8081
codemap.clone());
8182

8283
let cstore = Rc::new(CStore::new(token::get_ident_interner()));
@@ -235,7 +236,7 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec<String>, libs: SearchPaths,
235236
let _bomb = Bomb(data, old.unwrap_or(box io::stdout()));
236237

237238
// Compile the code
238-
let diagnostic_handler = errors::Handler::with_emitter(true, false, box emitter);
239+
let diagnostic_handler = errors::Handler::with_emitter(true, false, false, box emitter);
239240

240241
let cstore = Rc::new(CStore::new(token::get_ident_interner()));
241242
let sess = session::build_session_(sessopts,

src/libsyntax/errors/mod.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ pub struct Handler {
370370
emit: RefCell<Box<Emitter>>,
371371
pub can_emit_warnings: bool,
372372
treat_err_as_bug: bool,
373+
continue_parse_after_err: bool,
373374
delayed_span_bug: RefCell<Option<(MultiSpan, String)>>,
374375
}
375376

@@ -378,20 +379,26 @@ impl Handler {
378379
registry: Option<diagnostics::registry::Registry>,
379380
can_emit_warnings: bool,
380381
treat_err_as_bug: bool,
382+
continue_parse_after_err: bool,
381383
cm: Rc<codemap::CodeMap>)
382384
-> Handler {
383385
let emitter = Box::new(EmitterWriter::stderr(color_config, registry, cm));
384-
Handler::with_emitter(can_emit_warnings, treat_err_as_bug, emitter)
386+
Handler::with_emitter(can_emit_warnings,
387+
treat_err_as_bug,
388+
continue_parse_after_err,
389+
emitter)
385390
}
386391

387392
pub fn with_emitter(can_emit_warnings: bool,
388393
treat_err_as_bug: bool,
394+
continue_parse_after_err: bool,
389395
e: Box<Emitter>) -> Handler {
390396
Handler {
391397
err_count: Cell::new(0),
392398
emit: RefCell::new(e),
393399
can_emit_warnings: can_emit_warnings,
394400
treat_err_as_bug: treat_err_as_bug,
401+
continue_parse_after_err: continue_parse_after_err,
395402
delayed_span_bug: RefCell::new(None),
396403
}
397404
}
@@ -572,7 +579,13 @@ impl Handler {
572579
self.bug(&format!("unimplemented {}", msg));
573580
}
574581

575-
pub fn bump_err_count(&self) {
582+
pub fn abort_if_no_parse_recovery(&self) {
583+
if !self.continue_parse_after_err {
584+
self.abort_if_errors();
585+
}
586+
}
587+
588+
fn bump_err_count(&self) {
576589
self.err_count.set(self.err_count.get() + 1);
577590
}
578591

src/libsyntax/parse/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub struct ParseSess {
4949
impl ParseSess {
5050
pub fn new() -> ParseSess {
5151
let cm = Rc::new(CodeMap::new());
52-
let handler = Handler::with_tty_emitter(ColorConfig::Auto, None, true, false, cm.clone());
52+
let handler = Handler::with_tty_emitter(ColorConfig::Auto, None, true, false, true, cm.clone());
5353
ParseSess::with_span_handler(handler, cm)
5454
}
5555

src/libsyntax/parse/parser.rs

+27-9
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,8 @@ impl<'a> Parser<'a> {
689689
pub fn check_reserved_keywords(&mut self) {
690690
if self.token.is_reserved_keyword() {
691691
let token_str = self.this_token_to_string();
692-
self.fatal(&format!("`{}` is a reserved keyword", token_str)).emit()
692+
self.fatal(&format!("`{}` is a reserved keyword", token_str)).emit();
693+
self.sess.span_diagnostic.abort_if_no_parse_recovery();
693694
}
694695
}
695696

@@ -869,7 +870,7 @@ impl<'a> Parser<'a> {
869870
self.parse_seq_to_before_tokens(kets,
870871
SeqSep::none(),
871872
|p| p.parse_token_tree(),
872-
|mut e| e.cancel());
873+
|_self, mut e| e.cancel());
873874
}
874875

875876
/// Parse a sequence, including the closing delimiter. The function
@@ -897,7 +898,10 @@ impl<'a> Parser<'a> {
897898
-> Vec<T>
898899
where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
899900
{
900-
self.parse_seq_to_before_tokens(&[ket], sep, f, |mut e| e.emit())
901+
self.parse_seq_to_before_tokens(&[ket], sep, f, |s, mut e| {
902+
e.emit();
903+
s.sess.span_diagnostic.abort_if_no_parse_recovery();
904+
})
901905
}
902906

903907
// `fe` is an error handler.
@@ -908,7 +912,7 @@ impl<'a> Parser<'a> {
908912
mut fe: Fe)
909913
-> Vec<T>
910914
where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
911-
Fe: FnMut(DiagnosticBuilder)
915+
Fe: FnMut(&mut Parser<'a>, DiagnosticBuilder)
912916
{
913917
let mut first: bool = true;
914918
let mut v = vec!();
@@ -919,7 +923,7 @@ impl<'a> Parser<'a> {
919923
first = false;
920924
} else {
921925
if let Err(e) = self.expect(t) {
922-
fe(e);
926+
fe(self, e);
923927
break;
924928
}
925929
}
@@ -933,7 +937,7 @@ impl<'a> Parser<'a> {
933937
match f(self) {
934938
Ok(t) => v.push(t),
935939
Err(e) => {
936-
fe(e);
940+
fe(self, e);
937941
break;
938942
}
939943
}
@@ -1091,7 +1095,8 @@ impl<'a> Parser<'a> {
10911095
self.sess.span_diagnostic.span_warn(sp, m)
10921096
}
10931097
pub fn span_err(&self, sp: Span, m: &str) {
1094-
self.sess.span_diagnostic.span_err(sp, m)
1098+
self.sess.span_diagnostic.span_err(sp, m);
1099+
self.sess.span_diagnostic.abort_if_no_parse_recovery();
10951100
}
10961101
pub fn span_bug(&self, sp: Span, m: &str) -> ! {
10971102
self.sess.span_diagnostic.span_bug(sp, m)
@@ -2375,6 +2380,7 @@ impl<'a> Parser<'a> {
23752380
}
23762381
Err(mut e) => {
23772382
e.emit();
2383+
self.sess.span_diagnostic.abort_if_no_parse_recovery();
23782384
self.recover_stmt();
23792385
}
23802386
}
@@ -2385,6 +2391,7 @@ impl<'a> Parser<'a> {
23852391
Ok(f) => fields.push(f),
23862392
Err(mut e) => {
23872393
e.emit();
2394+
self.sess.span_diagnostic.abort_if_no_parse_recovery();
23882395
self.recover_stmt();
23892396
break;
23902397
}
@@ -2396,6 +2403,7 @@ impl<'a> Parser<'a> {
23962403
Ok(()) => {}
23972404
Err(mut e) => {
23982405
e.emit();
2406+
self.sess.span_diagnostic.abort_if_no_parse_recovery();
23992407
self.recover_stmt();
24002408
break;
24012409
}
@@ -2704,8 +2712,10 @@ impl<'a> Parser<'a> {
27042712
pub fn check_unknown_macro_variable(&mut self) {
27052713
if self.quote_depth == 0 {
27062714
match self.token {
2707-
token::SubstNt(name, _) =>
2708-
self.fatal(&format!("unknown macro variable `{}`", name)).emit(),
2715+
token::SubstNt(name, _) => {
2716+
self.fatal(&format!("unknown macro variable `{}`", name)).emit();
2717+
self.sess.span_diagnostic.abort_if_no_parse_recovery();
2718+
}
27092719
_ => {}
27102720
}
27112721
}
@@ -3076,6 +3086,7 @@ impl<'a> Parser<'a> {
30763086
"use `::<...>` instead of `<...>` if you meant to specify type arguments");
30773087
}
30783088
err.emit();
3089+
self.sess.span_diagnostic.abort_if_no_parse_recovery();
30793090
}
30803091
_ => {}
30813092
}
@@ -3284,6 +3295,7 @@ impl<'a> Parser<'a> {
32843295
Err(mut e) => {
32853296
// Recover by skipping to the end of the block.
32863297
e.emit();
3298+
self.sess.span_diagnostic.abort_if_no_parse_recovery();
32873299
self.recover_stmt();
32883300
let hi = self.span.hi;
32893301
if self.token == token::CloseDelim(token::Brace) {
@@ -3652,6 +3664,7 @@ impl<'a> Parser<'a> {
36523664
self.bump();
36533665
let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| {
36543666
e.emit();
3667+
self.sess.span_diagnostic.abort_if_no_parse_recovery();
36553668
self.recover_stmt();
36563669
(vec![], false)
36573670
});
@@ -3868,6 +3881,7 @@ impl<'a> Parser<'a> {
38683881
fn parse_stmt_(&mut self) -> Option<Stmt> {
38693882
self.parse_stmt_without_recovery().unwrap_or_else(|mut e| {
38703883
e.emit();
3884+
self.sess.span_diagnostic.abort_if_no_parse_recovery();
38713885
self.recover_stmt_(SemiColonMode::Break);
38723886
None
38733887
})
@@ -4139,6 +4153,7 @@ impl<'a> Parser<'a> {
41394153
self.commit_stmt(&[], &[token::Semi, token::CloseDelim(token::Brace)])
41404154
{
41414155
e.emit();
4156+
self.sess.span_diagnostic.abort_if_no_parse_recovery();
41424157
self.recover_stmt();
41434158
}
41444159
}
@@ -4529,6 +4544,7 @@ impl<'a> Parser<'a> {
45294544
Ok(arg) => Ok(Some(arg)),
45304545
Err(mut e) => {
45314546
e.emit();
4547+
p.sess.span_diagnostic.abort_if_no_parse_recovery();
45324548
p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
45334549
Ok(None)
45344550
}
@@ -4917,6 +4933,7 @@ impl<'a> Parser<'a> {
49174933
inside the invocation")
49184934
.emit();
49194935
}
4936+
self.sess.span_diagnostic.abort_if_no_parse_recovery();
49204937
}
49214938
Visibility::Inherited => (),
49224939
}
@@ -5778,6 +5795,7 @@ impl<'a> Parser<'a> {
57785795
self.diagnostic().struct_span_err(last_span, "const globals cannot be mutable")
57795796
.fileline_help(last_span, "did you mean to declare a static?")
57805797
.emit();
5798+
self.sess.span_diagnostic.abort_if_no_parse_recovery();
57815799
}
57825800
let (ident, item_, extra_attrs) = self.parse_item_const(None)?;
57835801
let last_span = self.last_span;

0 commit comments

Comments
 (0)