From b1b6b33c6dbae1c72eebc50ba86a267704c2fade Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 20 Jan 2016 17:15:03 +1300 Subject: [PATCH 1/6] Some basic error correction in the parser after a dot --- src/libsyntax/parse/parser.rs | 104 ++++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 42 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index bfa42e761294b..34b94b883a4dc 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; } From 0ac8915875596db90167701c447d9c76396358bb Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 20 Jan 2016 22:07:33 +1300 Subject: [PATCH 2/6] 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(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 27745a85935ab..756d708732a4e 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 ec55daca9ecdf..6e57d5dd1ba8d 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 2f3af1c0d09b5..975ec0e709b7d 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 fd5f711c9d639..1db04033f940e 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 9122148a8cc05..9c75007a8db76 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 cda5267f7271b..f422a47572b8d 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 444c43163e3c3..fb4eb61ceb4d4 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 6983c74696ac8..a7a4ddc3b2a63 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 5f27bdfc98a41..72537f6c7b26a 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 090b070433f46..32372ccc13b47 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 34b94b883a4dc..acce6ed87d00b 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)); From 585cf6fb5f0c2736c781b6efb4651ba6d317a753 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 20 Jan 2016 22:29:47 +1300 Subject: [PATCH 3/6] Prevent missing idents from causing problems down the line --- src/librustc_resolve/lib.rs | 4 ++++ src/librustc_typeck/check/mod.rs | 18 +++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index fb4eb61ceb4d4..e30fafda63cb4 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3037,6 +3037,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { check_ribs: bool, record_used: bool) -> Option { + if identifier.name == special_idents::invalid.name { + return Some(LocalDef::from_def(DefErr)); + } + // First, check to see whether the name is a primitive type. if namespace == TypeNS { if let Some(&prim_ty) = self.primitive_type_table diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f49b25df66e87..922ebb3683e80 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -121,7 +121,7 @@ use syntax::attr; use syntax::attr::AttrMetaMethods; use syntax::codemap::{self, Span, Spanned}; use syntax::errors::DiagnosticBuilder; -use syntax::parse::token::{self, InternedString}; +use syntax::parse::token::{self, InternedString, special_idents}; use syntax::ptr::P; use syntax::util::lev_distance::find_best_match_for_name; @@ -2839,8 +2839,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, method_ty } Err(error) => { - method::report_error(fcx, method_name.span, expr_t, - method_name.node, Some(rcvr), error); + if method_name.node != special_idents::invalid.name { + method::report_error(fcx, method_name.span, expr_t, + method_name.node, Some(rcvr), error); + } fcx.write_error(expr.id); fcx.tcx().types.err } @@ -2938,6 +2940,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, None => {} } + if field.node == special_idents::invalid.name { + fcx.write_error(expr.id); + return; + } + if method::exists(fcx, field.span, field.node, expr_t, expr.id) { fcx.type_error_struct(field.span, |actual| { @@ -3788,8 +3795,9 @@ pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>, Some((Some(ty), slice::ref_slice(item_segment), def)) } Err(error) => { - method::report_error(fcx, span, ty, - item_name, None, error); + if item_name != special_idents::invalid.name { + method::report_error(fcx, span, ty, item_name, None, error); + } fcx.write_error(node_id); None } From f3b525fb97c48976c740da50a38ec8c9e5f29b7e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 21 Jan 2016 12:16:59 +1300 Subject: [PATCH 4/6] test fallout --- src/librustc_driver/driver.rs | 33 ++++++++++++------- src/librustc_typeck/check/mod.rs | 13 +++----- src/test/compile-fail/cfg-non-opt-expr.rs | 2 ++ src/test/compile-fail/double-type-import.rs | 2 +- src/test/compile-fail/import-from-missing.rs | 1 + src/test/compile-fail/import.rs | 2 +- src/test/compile-fail/import2.rs | 3 +- .../macro-reexport-malformed-1.rs | 3 +- .../macro-reexport-malformed-2.rs | 3 +- .../macro-reexport-malformed-3.rs | 3 +- src/test/compile-fail/macro-reexport-undef.rs | 2 ++ src/test/compile-fail/macro-use-bad-args-1.rs | 5 ++- src/test/compile-fail/macro-use-bad-args-2.rs | 5 ++- src/test/compile-fail/privacy3.rs | 1 + src/test/compile-fail/self_type_keyword.rs | 1 + src/test/compile-fail/use-mod.rs | 1 + 16 files changed, 46 insertions(+), 34 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 1db04033f940e..36074a7ae0225 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -70,6 +70,7 @@ pub fn compile_input(sess: Session, (control.$point.callback)(state); if control.$point.stop == Compilation::Stop { + $tsess.abort_if_errors(); return; } })} @@ -469,7 +470,11 @@ pub fn phase_2_configure_and_expand(sess: &Session, let mut feature_gated_cfgs = vec![]; krate = time(time_passes, "configuration 1", || { - syntax::config::strip_unconfigured_items(sess.diagnostic(), krate, &mut feature_gated_cfgs) + sess.abort_if_new_errors(|| { + syntax::config::strip_unconfigured_items(sess.diagnostic(), + krate, + &mut feature_gated_cfgs) + }) }); *sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs); @@ -605,17 +610,23 @@ pub fn phase_2_configure_and_expand(sess: &Session, // JBC: make CFG processing part of expansion to avoid this problem: // strip again, in case expansion added anything with a #[cfg]. - krate = time(time_passes, "configuration 2", || { - syntax::config::strip_unconfigured_items(sess.diagnostic(), krate, &mut feature_gated_cfgs) - }); + krate = sess.abort_if_new_errors(|| { + let krate = time(time_passes, "configuration 2", || { + syntax::config::strip_unconfigured_items(sess.diagnostic(), + krate, + &mut feature_gated_cfgs) + }); - time(time_passes, "gated configuration checking", || { - let features = sess.features.borrow(); - feature_gated_cfgs.sort(); - feature_gated_cfgs.dedup(); - for cfg in &feature_gated_cfgs { - cfg.check_and_emit(sess.diagnostic(), &features, sess.codemap()); - } + time(time_passes, "gated configuration checking", || { + let features = sess.features.borrow(); + feature_gated_cfgs.sort(); + feature_gated_cfgs.dedup(); + for cfg in &feature_gated_cfgs { + cfg.check_and_emit(sess.diagnostic(), &features, sess.codemap()); + } + }); + + krate }); krate = time(time_passes, "maybe building test harness", || { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 922ebb3683e80..a8697f45d9156 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4229,7 +4229,9 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, } // Check for unrepresentable discriminant values match hint { - attr::ReprAny | attr::ReprExtern => (), + attr::ReprAny | attr::ReprExtern => { + disr_vals.push(current_disr_val); + } attr::ReprInt(sp, ity) => { if !disr_in_range(ccx, ity, current_disr_val) { let mut err = struct_span_err!(ccx.tcx.sess, v.span, E0082, @@ -4239,14 +4241,9 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, err.emit(); } } - attr::ReprSimd => { - ccx.tcx.sess.bug("range_to_inttype: found ReprSimd on an enum"); - } - attr::ReprPacked => { - ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum"); - } + // Error reported elsewhere. + attr::ReprSimd | attr::ReprPacked => {} } - disr_vals.push(current_disr_val); } } diff --git a/src/test/compile-fail/cfg-non-opt-expr.rs b/src/test/compile-fail/cfg-non-opt-expr.rs index d9d379ddc7dd5..b3ef3d72ca3bf 100644 --- a/src/test/compile-fail/cfg-non-opt-expr.rs +++ b/src/test/compile-fail/cfg-non-opt-expr.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(stmt_expr_attributes)] + fn main() { let _ = #[cfg(unset)] (); //~^ ERROR removing an expression is not supported in this position diff --git a/src/test/compile-fail/double-type-import.rs b/src/test/compile-fail/double-type-import.rs index 923f95e69d122..d6d7dbb4aecd8 100644 --- a/src/test/compile-fail/double-type-import.rs +++ b/src/test/compile-fail/double-type-import.rs @@ -20,5 +20,5 @@ mod foo { } fn main() { - let _ = foo::X; + let _ = foo::X; //~ ERROR unresolved name `foo::X` } diff --git a/src/test/compile-fail/import-from-missing.rs b/src/test/compile-fail/import-from-missing.rs index f393442de1011..489bcfbdefdd6 100644 --- a/src/test/compile-fail/import-from-missing.rs +++ b/src/test/compile-fail/import-from-missing.rs @@ -16,3 +16,4 @@ mod spam { } fn main() { ham(); eggs(); } +//~^ ERROR unresolved name `eggs` diff --git a/src/test/compile-fail/import.rs b/src/test/compile-fail/import.rs index 844d527a54607..86c4ce8b0380b 100644 --- a/src/test/compile-fail/import.rs +++ b/src/test/compile-fail/import.rs @@ -16,4 +16,4 @@ use zed::baz; mod zed { pub fn bar() { println!("bar"); } } -fn main(args: Vec) { bar(); } +fn main() { bar(); } diff --git a/src/test/compile-fail/import2.rs b/src/test/compile-fail/import2.rs index 6533bd5ddc610..1d2aecd4e3b7f 100644 --- a/src/test/compile-fail/import2.rs +++ b/src/test/compile-fail/import2.rs @@ -16,4 +16,5 @@ mod baz {} mod zed { pub fn bar() { println!("bar3"); } } -fn main(args: Vec) { bar(); } +fn main() { bar(); } +//~^ ERROR unresolved name `bar` diff --git a/src/test/compile-fail/macro-reexport-malformed-1.rs b/src/test/compile-fail/macro-reexport-malformed-1.rs index 6c85cf5c7f5db..ea2dfca0714fc 100644 --- a/src/test/compile-fail/macro-reexport-malformed-1.rs +++ b/src/test/compile-fail/macro-reexport-malformed-1.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![no_std] #![feature(macro_reexport)] #[macro_reexport] //~ ERROR bad macro reexport extern crate std; - -fn main() { } diff --git a/src/test/compile-fail/macro-reexport-malformed-2.rs b/src/test/compile-fail/macro-reexport-malformed-2.rs index 1dd0168181f83..844955fb7e664 100644 --- a/src/test/compile-fail/macro-reexport-malformed-2.rs +++ b/src/test/compile-fail/macro-reexport-malformed-2.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![no_std] #![feature(macro_reexport)] #[macro_reexport="foo"] //~ ERROR bad macro reexport extern crate std; - -fn main() { } diff --git a/src/test/compile-fail/macro-reexport-malformed-3.rs b/src/test/compile-fail/macro-reexport-malformed-3.rs index 7ae045f6e4f51..381c22854e654 100644 --- a/src/test/compile-fail/macro-reexport-malformed-3.rs +++ b/src/test/compile-fail/macro-reexport-malformed-3.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![no_std] #![feature(macro_reexport)] #[macro_reexport(foo="bar")] //~ ERROR bad macro reexport extern crate std; - -fn main() { } diff --git a/src/test/compile-fail/macro-reexport-undef.rs b/src/test/compile-fail/macro-reexport-undef.rs index 8fa6b32905ceb..5bb0b8759f486 100644 --- a/src/test/compile-fail/macro-reexport-undef.rs +++ b/src/test/compile-fail/macro-reexport-undef.rs @@ -10,6 +10,8 @@ // aux-build:two_macros.rs +#![feature(macro_reexport)] + #[macro_use(macro_two)] #[macro_reexport(no_way)] //~ ERROR reexported macro not found extern crate two_macros; diff --git a/src/test/compile-fail/macro-use-bad-args-1.rs b/src/test/compile-fail/macro-use-bad-args-1.rs index a73c4adb71f9f..39c09c6977963 100644 --- a/src/test/compile-fail/macro-use-bad-args-1.rs +++ b/src/test/compile-fail/macro-use-bad-args-1.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![no_std] + #[macro_use(foo(bar))] //~ ERROR bad macro import extern crate std; - -fn main() { -} diff --git a/src/test/compile-fail/macro-use-bad-args-2.rs b/src/test/compile-fail/macro-use-bad-args-2.rs index 31efe857605b4..11a0108b99b89 100644 --- a/src/test/compile-fail/macro-use-bad-args-2.rs +++ b/src/test/compile-fail/macro-use-bad-args-2.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![no_std] + #[macro_use(foo="bar")] //~ ERROR bad macro import extern crate std; - -fn main() { -} diff --git a/src/test/compile-fail/privacy3.rs b/src/test/compile-fail/privacy3.rs index da6266bc7ee6b..6a203993ccf2d 100644 --- a/src/test/compile-fail/privacy3.rs +++ b/src/test/compile-fail/privacy3.rs @@ -28,6 +28,7 @@ fn test1() { use bar::gpriv; //~^ ERROR unresolved import `bar::gpriv`. There is no `gpriv` in `bar` gpriv(); + //~^ ERROR unresolved name `gpriv` } #[start] fn main(_: isize, _: *const *const u8) -> isize { 3 } diff --git a/src/test/compile-fail/self_type_keyword.rs b/src/test/compile-fail/self_type_keyword.rs index 6f5aeead57ecb..e28197e81faf9 100644 --- a/src/test/compile-fail/self_type_keyword.rs +++ b/src/test/compile-fail/self_type_keyword.rs @@ -29,6 +29,7 @@ pub fn main() { //~^ ERROR expected identifier, found keyword `Self` Self!() => (), //~^ ERROR expected identifier, found keyword `Self` + //~^^ ERROR macro undefined: 'Self!' Foo { x: Self } => (), //~^ ERROR expected identifier, found keyword `Self` Foo { Self } => (), diff --git a/src/test/compile-fail/use-mod.rs b/src/test/compile-fail/use-mod.rs index 15640e386dfa0..9cc3c92e2e376 100644 --- a/src/test/compile-fail/use-mod.rs +++ b/src/test/compile-fail/use-mod.rs @@ -14,6 +14,7 @@ use foo::bar::{ Bar, self //~^ NOTE another `self` import appears here +//~^^ ERROR a module named `bar` has already been imported in this module }; use {self}; From ff009d1d3606e98b210fb423802cd3711fc82ee6 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 21 Jan 2016 12:32:56 +1300 Subject: [PATCH 5/6] test --- src/test/compile-fail/parse-error-correct.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/test/compile-fail/parse-error-correct.rs diff --git a/src/test/compile-fail/parse-error-correct.rs b/src/test/compile-fail/parse-error-correct.rs new file mode 100644 index 0000000000000..7715ed41841cf --- /dev/null +++ b/src/test/compile-fail/parse-error-correct.rs @@ -0,0 +1,19 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that the parser is error correcting missing idents. Despite a parsing +// error (or two), we still run type checking (and don't get extra errors there). + +fn main() { + let y = 42; + let x = y.; //~ ERROR unexpected token + let x = y.(); //~ ERROR unexpected token + let x = y.foo; //~ ERROR no field +} From 43b3681588ef40c78c794548d67a8f50101bc8ad Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 22 Jan 2016 08:55:54 +1300 Subject: [PATCH 6/6] Fix a rebasing issue and addressed reviewer comment --- src/librustc/middle/cstore.rs | 32 ++++++++++++++++++++------------ src/librustc_resolve/lib.rs | 2 +- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 756d708732a4e..973fd65beb3d8 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -267,20 +267,28 @@ impl InlinedItem { // FIXME: find a better place for this? 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_fatal(sp, s), - (None, Some(sess)) => sess.fatal(s), + let mut err_count = 0; + { + let mut say = |s: &str| { + match (sp, sess) { + (_, None) => panic!("{}", s), + (Some(sp), Some(sess)) => sess.span_err(sp, s), + (None, Some(sess)) => sess.err(s), + } + err_count += 1; + }; + if s.is_empty() { + say("crate name must not be empty"); + } + for c in s.chars() { + if c.is_alphanumeric() { continue } + if c == '_' { continue } + say(&format!("invalid character `{}` in crate name: `{}`", c, s)); } - }; - if s.is_empty() { - say("crate name must not be empty"); } - for c in s.chars() { - if c.is_alphanumeric() { continue } - if c == '_' { continue } - say(&format!("invalid character `{}` in crate name: `{}`", c, s)); + + if err_count > 0 { + sess.unwrap().abort_if_errors(); } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e30fafda63cb4..c698f72955320 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3038,7 +3038,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { record_used: bool) -> Option { if identifier.name == special_idents::invalid.name { - return Some(LocalDef::from_def(DefErr)); + return Some(LocalDef::from_def(Def::Err)); } // First, check to see whether the name is a primitive type.