From b1b6b33c6dbae1c72eebc50ba86a267704c2fade Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 20 Jan 2016 17:15:03 +1300 Subject: Some basic error correction in the parser after a dot --- src/libsyntax/parse/parser.rs | 104 +++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 42 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index bfa42e76129..34b94b883a4 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2355,6 +2355,55 @@ impl<'a> Parser<'a> { ) } + // Assuming we have just parsed `.foo` (i.e., a dot and an ident), continue + // parsing into an expression. + fn parse_dot_suffix(&mut self, ident: Ident, ident_span: Span, self_value: P) -> PResult<'a, P> { + let (_, tys, bindings) = if self.eat(&token::ModSep) { + try!(self.expect_lt()); + try!(self.parse_generic_values_after_lt()) + } else { + (Vec::new(), Vec::new(), Vec::new()) + }; + + if !bindings.is_empty() { + let last_span = self.last_span; + self.span_err(last_span, "type bindings are only permitted on trait paths"); + } + + let lo = self_value.span.lo; + + Ok(match self.token { + // expr.f() method call. + token::OpenDelim(token::Paren) => { + let mut es = try!(self.parse_unspanned_seq( + &token::OpenDelim(token::Paren), + &token::CloseDelim(token::Paren), + seq_sep_trailing_allowed(token::Comma), + |p| Ok(try!(p.parse_expr())) + )); + let hi = self.last_span.hi; + + es.insert(0, self_value); + let id = spanned(ident_span.lo, ident_span.hi, ident); + let nd = self.mk_method_call(id, tys, es); + self.mk_expr(lo, hi, nd, None) + } + // Field access. + _ => { + if !tys.is_empty() { + let last_span = self.last_span; + self.span_err(last_span, + "field expressions may not \ + have type parameters"); + } + + let id = spanned(ident_span.lo, ident_span.hi, ident); + let field = self.mk_field(self_value, id); + self.mk_expr(lo, ident_span.hi, field, None) + } + }) + } + fn parse_dot_or_call_expr_with_(&mut self, e0: P) -> PResult<'a, P> { let mut e = e0; let lo = e.span.lo; @@ -2364,50 +2413,11 @@ impl<'a> Parser<'a> { if self.eat(&token::Dot) { match self.token { token::Ident(i, _) => { - let dot = self.last_span.hi; + let dot_pos = self.last_span.hi; hi = self.span.hi; self.bump(); - let (_, tys, bindings) = if self.eat(&token::ModSep) { - try!(self.expect_lt()); - try!(self.parse_generic_values_after_lt()) - } else { - (Vec::new(), Vec::new(), Vec::new()) - }; - - if !bindings.is_empty() { - let last_span = self.last_span; - self.span_err(last_span, "type bindings are only permitted on trait paths"); - } - // expr.f() method call - match self.token { - token::OpenDelim(token::Paren) => { - let mut es = try!(self.parse_unspanned_seq( - &token::OpenDelim(token::Paren), - &token::CloseDelim(token::Paren), - seq_sep_trailing_allowed(token::Comma), - |p| Ok(try!(p.parse_expr())) - )); - hi = self.last_span.hi; - - es.insert(0, e); - let id = spanned(dot, hi, i); - let nd = self.mk_method_call(id, tys, es); - e = self.mk_expr(lo, hi, nd, None); - } - _ => { - if !tys.is_empty() { - let last_span = self.last_span; - self.span_err(last_span, - "field expressions may not \ - have type parameters"); - } - - let id = spanned(dot, hi, i); - let field = self.mk_field(e, id); - e = self.mk_expr(lo, hi, field, None); - } - } + e = try!(self.parse_dot_suffix(i, mk_sp(dot_pos, hi), e)); } token::Literal(token::Integer(n), suf) => { let sp = self.span; @@ -2452,7 +2462,17 @@ impl<'a> Parser<'a> { self.abort_if_errors(); } - _ => return self.unexpected() + _ => { + // TODO special case lifetime + // FIXME Could factor this out into non_fatal_unexpected or something. + let actual = self.this_token_to_string(); + self.span_err(self.span, &format!("unexpected token: `{}`", actual)); + + let dot_pos = self.last_span.hi; + e = try!(self.parse_dot_suffix(special_idents::invalid, + mk_sp(dot_pos, dot_pos), + e)); + } } continue; } -- cgit 1.4.1-3-g733a5 From 0ac8915875596db90167701c447d9c76396358bb Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 20 Jan 2016 22:07:33 +1300 Subject: The war on abort_if_errors --- src/librustc/middle/cstore.rs | 8 ++--- src/librustc/middle/lang_items.rs | 1 - src/librustc/session/mod.rs | 7 +++-- src/librustc_driver/driver.rs | 64 ++++++++++++++++++++------------------- src/librustc_metadata/creader.rs | 19 +++++------- src/librustc_passes/const_fn.rs | 5 +-- src/librustc_resolve/lib.rs | 2 -- src/libsyntax/errors/mod.rs | 7 +++-- src/libsyntax/ext/expand.rs | 7 ++++- src/libsyntax/parse/mod.rs | 20 +++++------- src/libsyntax/parse/parser.rs | 7 +++-- 11 files changed, 73 insertions(+), 74 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 27745a85935..756d708732a 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -270,8 +270,8 @@ pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option) { let say = |s: &str| { match (sp, sess) { (_, None) => panic!("{}", s), - (Some(sp), Some(sess)) => sess.span_err(sp, s), - (None, Some(sess)) => sess.err(s), + (Some(sp), Some(sess)) => sess.span_fatal(sp, s), + (None, Some(sess)) => sess.fatal(s), } }; if s.is_empty() { @@ -282,10 +282,6 @@ pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option) { if c == '_' { continue } say(&format!("invalid character `{}` in crate name: `{}`", c, s)); } - match sess { - Some(sess) => sess.abort_if_errors(), - None => {} - } } /// A dummy crate store that does not support any non-local crates, diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index ec55daca9ec..6e57d5dd1ba 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -239,7 +239,6 @@ pub fn collect_language_items(session: &Session, collector.collect(krate); let LanguageItemCollector { mut items, .. } = collector; weak_lang_items::check_crate(krate, session, &mut items); - session.abort_if_errors(); items } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 2f3af1c0d09..975ec0e709b 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -176,14 +176,15 @@ impl Session { pub fn abort_if_errors(&self) { self.diagnostic().abort_if_errors(); } - pub fn abort_if_new_errors(&self, mut f: F) - where F: FnMut() + pub fn abort_if_new_errors(&self, f: F) -> T + where F: FnOnce() -> T { let count = self.err_count(); - f(); + let result = f(); if self.err_count() > count { self.abort_if_errors(); } + result } pub fn span_warn(&self, sp: Span, msg: &str) { self.diagnostic().span_warn(sp, msg) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index fd5f711c9d6..1db04033f94 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -69,7 +69,6 @@ pub fn compile_input(sess: Session, let state = $make_state; (control.$point.callback)(state); - $tsess.abort_if_errors(); if control.$point.stop == Compilation::Stop { return; } @@ -481,13 +480,15 @@ pub fn phase_2_configure_and_expand(sess: &Session, }); time(time_passes, "gated macro checking", || { - let features = syntax::feature_gate::check_crate_macros(sess.codemap(), - &sess.parse_sess.span_diagnostic, - &krate); - - // these need to be set "early" so that expansion sees `quote` if enabled. - *sess.features.borrow_mut() = features; - sess.abort_if_errors(); + sess.abort_if_new_errors(|| { + let features = + syntax::feature_gate::check_crate_macros(sess.codemap(), + &sess.parse_sess.span_diagnostic, + &krate); + + // these need to be set "early" so that expansion sees `quote` if enabled. + *sess.features.borrow_mut() = features; + }); }); @@ -525,7 +526,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, let Registry { syntax_exts, early_lint_passes, late_lint_passes, lint_groups, llvm_passes, attributes, .. } = registry; - { + sess.abort_if_new_errors(|| { let mut ls = sess.lint_store.borrow_mut(); for pass in early_lint_passes { ls.register_early_pass(Some(sess), true, pass); @@ -540,17 +541,14 @@ pub fn phase_2_configure_and_expand(sess: &Session, *sess.plugin_llvm_passes.borrow_mut() = llvm_passes; *sess.plugin_attributes.borrow_mut() = attributes.clone(); - } + }); // Lint plugins are registered; now we can process command line flags. if sess.opts.describe_lints { super::describe_lints(&*sess.lint_store.borrow(), true); return None; } - sess.lint_store.borrow_mut().process_command_line(sess); - - // Abort if there are errors from lint processing or a plugin registrar. - sess.abort_if_errors(); + sess.abort_if_new_errors(|| sess.lint_store.borrow_mut().process_command_line(sess)); krate = time(time_passes, "expansion", || { // Windows dlls do not have rpaths, so they don't know how to find their @@ -594,13 +592,14 @@ pub fn phase_2_configure_and_expand(sess: &Session, // much as possible (e.g. help the programmer avoid platform // specific differences) time(time_passes, "complete gated feature checking 1", || { - let features = syntax::feature_gate::check_crate(sess.codemap(), - &sess.parse_sess.span_diagnostic, - &krate, - &attributes, - sess.opts.unstable_features); - *sess.features.borrow_mut() = features; - sess.abort_if_errors(); + sess.abort_if_new_errors(|| { + let features = syntax::feature_gate::check_crate(sess.codemap(), + &sess.parse_sess.span_diagnostic, + &krate, + &attributes, + sess.opts.unstable_features); + *sess.features.borrow_mut() = features; + }); }); // JBC: make CFG processing part of expansion to avoid this problem: @@ -639,13 +638,14 @@ pub fn phase_2_configure_and_expand(sess: &Session, // later, to make sure we've got everything (e.g. configuration // can insert new attributes via `cfg_attr`) time(time_passes, "complete gated feature checking 2", || { - let features = syntax::feature_gate::check_crate(sess.codemap(), - &sess.parse_sess.span_diagnostic, - &krate, - &attributes, - sess.opts.unstable_features); - *sess.features.borrow_mut() = features; - sess.abort_if_errors(); + sess.abort_if_new_errors(|| { + let features = syntax::feature_gate::check_crate(sess.codemap(), + &sess.parse_sess.span_diagnostic, + &krate, + &attributes, + sess.opts.unstable_features); + *sess.features.borrow_mut() = features; + }); }); time(time_passes, @@ -711,9 +711,11 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, "external crate/lib resolution", || LocalCrateReader::new(sess, cstore, &hir_map).read_crates(krate)); - let lang_items = time(time_passes, - "language item collection", - || middle::lang_items::collect_language_items(&sess, &hir_map)); + let lang_items = time(time_passes, "language item collection", || { + sess.abort_if_new_errors(|| { + middle::lang_items::collect_language_items(&sess, &hir_map) + }) + }); let resolve::CrateMap { def_map, diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 9122148a8cc..9c75007a8db 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -258,15 +258,14 @@ impl<'a> CrateReader<'a> { metadata: &MetadataBlob) { let crate_rustc_version = decoder::crate_rustc_version(metadata.as_slice()); if crate_rustc_version != Some(rustc_version()) { - span_err!(self.sess, span, E0514, - "the crate `{}` has been compiled with {}, which is \ - incompatible with this version of rustc", - name, - crate_rustc_version - .as_ref().map(|s|&**s) - .unwrap_or("an old version of rustc") + span_fatal!(self.sess, span, E0514, + "the crate `{}` has been compiled with {}, which is \ + incompatible with this version of rustc", + name, + crate_rustc_version + .as_ref().map(|s|&**s) + .unwrap_or("an old version of rustc") ); - self.sess.abort_if_errors(); } } @@ -511,7 +510,6 @@ impl<'a> CrateReader<'a> { } }; let span = mk_sp(lo, p.last_span.hi); - p.abort_if_errors(); // Mark the attrs as used for attr in &attrs { @@ -554,8 +552,7 @@ impl<'a> CrateReader<'a> { name, config::host_triple(), self.sess.opts.target_triple); - span_err!(self.sess, span, E0456, "{}", &message[..]); - self.sess.abort_if_errors(); + span_fatal!(self.sess, span, E0456, "{}", &message[..]); } let registrar = diff --git a/src/librustc_passes/const_fn.rs b/src/librustc_passes/const_fn.rs index cda5267f727..f422a47572b 100644 --- a/src/librustc_passes/const_fn.rs +++ b/src/librustc_passes/const_fn.rs @@ -18,8 +18,9 @@ use syntax::visit::{self, Visitor, FnKind}; use syntax::codemap::Span; pub fn check_crate(sess: &Session, krate: &ast::Crate) { - visit::walk_crate(&mut CheckConstFn{ sess: sess }, krate); - sess.abort_if_errors(); + sess.abort_if_new_errors(|| { + visit::walk_crate(&mut CheckConstFn{ sess: sess }, krate); + }); } struct CheckConstFn<'a> { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 444c43163e3..fb4eb61ceb4 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -4019,10 +4019,8 @@ pub fn create_resolver<'a, 'tcx>(session: &'a Session, resolver.callback = callback; build_reduced_graph::build_reduced_graph(&mut resolver, krate); - session.abort_if_errors(); resolve_imports::resolve_imports(&mut resolver); - session.abort_if_errors(); resolver } diff --git a/src/libsyntax/errors/mod.rs b/src/libsyntax/errors/mod.rs index 6983c74696a..a7a4ddc3b2a 100644 --- a/src/libsyntax/errors/mod.rs +++ b/src/libsyntax/errors/mod.rs @@ -555,6 +555,9 @@ impl Handler { pub enum Level { Bug, Fatal, + // An error which while not immediately fatal, should stop the compiler + // progressing beyond the current phase. + PhaseFatal, Error, Warning, Note, @@ -573,7 +576,7 @@ impl fmt::Display for Level { impl Level { fn color(self) -> term::color::Color { match self { - Bug | Fatal | Error => term::color::BRIGHT_RED, + Bug | Fatal | PhaseFatal | Error => term::color::BRIGHT_RED, Warning => term::color::BRIGHT_YELLOW, Note => term::color::BRIGHT_GREEN, Help => term::color::BRIGHT_CYAN, @@ -584,7 +587,7 @@ impl Level { fn to_str(self) -> &'static str { match self { Bug => "error: internal compiler error", - Fatal | Error => "error", + Fatal | PhaseFatal | Error => "error", Warning => "warning", Note => "note", Help => "help", diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 5f27bdfc98a..72537f6c7b2 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1304,9 +1304,14 @@ pub fn expand_crate(mut cx: ExtCtxt, expander.cx.syntax_env.insert(name, extension); } + let err_count = cx.parse_sess.span_diagnostic.err_count(); let mut ret = expander.fold_crate(c); ret.exported_macros = expander.cx.exported_macros.clone(); - cx.parse_sess.span_diagnostic.abort_if_errors(); + + if cx.parse_sess.span_diagnostic.err_count() > err_count { + cx.parse_sess.span_diagnostic.abort_if_errors(); + } + ret }; return (ret, cx.syntax_env.names); diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 090b070433f..32372ccc13b 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -98,7 +98,7 @@ pub fn parse_crate_from_source_str(name: String, cfg, name, source); - maybe_aborted(panictry!(p.parse_crate_mod()),p) + panictry!(p.parse_crate_mod()) } pub fn parse_crate_attrs_from_source_str(name: String, @@ -110,7 +110,7 @@ pub fn parse_crate_attrs_from_source_str(name: String, cfg, name, source); - maybe_aborted(panictry!(p.parse_inner_attributes()), p) + panictry!(p.parse_inner_attributes()) } pub fn parse_expr_from_source_str(name: String, @@ -119,7 +119,7 @@ pub fn parse_expr_from_source_str(name: String, sess: &ParseSess) -> P { let mut p = new_parser_from_source_str(sess, cfg, name, source); - maybe_aborted(panictry!(p.parse_expr()), p) + panictry!(p.parse_expr()) } pub fn parse_item_from_source_str(name: String, @@ -128,7 +128,7 @@ pub fn parse_item_from_source_str(name: String, sess: &ParseSess) -> Option> { let mut p = new_parser_from_source_str(sess, cfg, name, source); - maybe_aborted(panictry!(p.parse_item()), p) + panictry!(p.parse_item()) } pub fn parse_meta_from_source_str(name: String, @@ -137,7 +137,7 @@ pub fn parse_meta_from_source_str(name: String, sess: &ParseSess) -> P { let mut p = new_parser_from_source_str(sess, cfg, name, source); - maybe_aborted(panictry!(p.parse_meta_item()), p) + panictry!(p.parse_meta_item()) } pub fn parse_stmt_from_source_str(name: String, @@ -151,7 +151,7 @@ pub fn parse_stmt_from_source_str(name: String, name, source ); - maybe_aborted(panictry!(p.parse_stmt()), p) + panictry!(p.parse_stmt()) } // Warning: This parses with quote_depth > 0, which is not the default. @@ -168,7 +168,7 @@ pub fn parse_tts_from_source_str(name: String, ); p.quote_depth += 1; // right now this is re-creating the token trees from ... token trees. - maybe_aborted(panictry!(p.parse_all_token_trees()),p) + panictry!(p.parse_all_token_trees()) } // Create a new parser from a source string @@ -265,16 +265,10 @@ pub fn tts_to_parser<'a>(sess: &'a ParseSess, p } -/// Abort if necessary -pub fn maybe_aborted(result: T, p: Parser) -> T { - p.abort_if_errors(); - result -} fn abort_if_errors<'a, T>(result: PResult<'a, T>, p: &Parser) -> T { match result { Ok(c) => { - p.abort_if_errors(); c } Err(mut e) => { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 34b94b883a4..acce6ed87d0 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2357,7 +2357,11 @@ impl<'a> Parser<'a> { // Assuming we have just parsed `.foo` (i.e., a dot and an ident), continue // parsing into an expression. - fn parse_dot_suffix(&mut self, ident: Ident, ident_span: Span, self_value: P) -> PResult<'a, P> { + fn parse_dot_suffix(&mut self, + ident: Ident, + ident_span: Span, + self_value: P) + -> PResult<'a, P> { let (_, tys, bindings) = if self.eat(&token::ModSep) { try!(self.expect_lt()); try!(self.parse_generic_values_after_lt()) @@ -2463,7 +2467,6 @@ impl<'a> Parser<'a> { } _ => { - // TODO special case lifetime // FIXME Could factor this out into non_fatal_unexpected or something. let actual = self.this_token_to_string(); self.span_err(self.span, &format!("unexpected token: `{}`", actual)); -- cgit 1.4.1-3-g733a5