From 95a32157af8291b452570319c2d035a4307b52e6 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 22 Jun 2019 12:46:48 +0100 Subject: [PATCH] Count all errors for `track_errors` --- src/librustc/infer/mod.rs | 1 + src/librustc_errors/lib.rs | 16 ++++++++-- src/librustc_mir/const_eval.rs | 20 ++++--------- src/librustc_save_analysis/span_utils.rs | 6 ---- src/librustc_typeck/check/mod.rs | 10 +++---- src/librustc_typeck/lib.rs | 5 +++- src/test/ui/consts/enum-discr-type-err.rs | 29 +++++++++++++++++++ src/test/ui/consts/enum-discr-type-err.stderr | 19 ++++++++++++ 8 files changed, 77 insertions(+), 29 deletions(-) create mode 100644 src/test/ui/consts/enum-discr-type-err.rs create mode 100644 src/test/ui/consts/enum-discr-type-err.stderr diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index fc46fe383c972..eb007062e6d50 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -171,6 +171,7 @@ pub struct InferCtxt<'a, 'tcx> { /// Track how many errors were reported when this infcx is created. /// If the number of errors increases, that's also a sign (line /// `tained_by_errors`) to avoid reporting certain kinds of errors. + // FIXME(matthewjasper) Merge into `tainted_by_errors_flag` err_count_on_creation: usize, /// This flag is true while there is an active snapshot. diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 082f981338a6c..70bd25a9d5772 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -307,7 +307,12 @@ pub use diagnostic_builder::DiagnosticBuilder; pub struct Handler { pub flags: HandlerFlags, + /// The number of errors that have been emitted, including duplicates. + /// + /// This is not necessarily the count that's reported to the user once + /// compilation ends. err_count: AtomicUsize, + deduplicated_err_count: AtomicUsize, emitter: Lock>, continue_after_error: AtomicBool, delayed_span_bugs: Lock>, @@ -407,6 +412,7 @@ impl Handler { Handler { flags, err_count: AtomicUsize::new(0), + deduplicated_err_count: AtomicUsize::new(0), emitter: Lock::new(e), continue_after_error: AtomicBool::new(true), delayed_span_bugs: Lock::new(Vec::new()), @@ -428,6 +434,7 @@ impl Handler { pub fn reset_err_count(&self) { // actually frees the underlying memory (which `clear` would not do) *self.emitted_diagnostics.borrow_mut() = Default::default(); + self.deduplicated_err_count.store(0, SeqCst); self.err_count.store(0, SeqCst); } @@ -660,10 +667,10 @@ impl Handler { } pub fn print_error_count(&self, registry: &Registry) { - let s = match self.err_count() { + let s = match self.deduplicated_err_count.load(SeqCst) { 0 => return, 1 => "aborting due to previous error".to_string(), - _ => format!("aborting due to {} previous errors", self.err_count()) + count => format!("aborting due to {} previous errors", count) }; if self.treat_err_as_bug() { return; @@ -769,9 +776,12 @@ impl Handler { if self.emitted_diagnostics.borrow_mut().insert(diagnostic_hash) { self.emitter.borrow_mut().emit_diagnostic(db); if db.is_error() { - self.bump_err_count(); + self.deduplicated_err_count.fetch_add(1, SeqCst); } } + if db.is_error() { + self.bump_err_count(); + } } pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 284a8f40e1f35..8c2bfc42b020a 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -15,7 +15,6 @@ use rustc::ty::{self, TyCtxt, query::TyCtxtAt}; use rustc::ty::layout::{self, LayoutOf, VariantIdx}; use rustc::ty::subst::Subst; use rustc::traits::Reveal; -use rustc::util::common::ErrorReported; use rustc_data_structures::fx::FxHashMap; use syntax::source_map::{Span, DUMMY_SP}; @@ -655,19 +654,12 @@ pub fn const_eval_raw_provider<'tcx>( if tcx.is_static(def_id) { // Ensure that if the above error was either `TooGeneric` or `Reported` // an error must be reported. - let reported_err = tcx.sess.track_errors(|| { - err.report_as_error(ecx.tcx, - "could not evaluate static initializer") - }); - match reported_err { - Ok(v) => { - tcx.sess.delay_span_bug(err.span, - &format!("static eval failure did not emit an error: {:#?}", - v)); - v - }, - Err(ErrorReported) => ErrorHandled::Reported, - } + let v = err.report_as_error(ecx.tcx, "could not evaluate static initializer"); + tcx.sess.delay_span_bug( + err.span, + &format!("static eval failure did not emit an error: {:#?}", v) + ); + v } else if def_id.is_local() { // constant defined in this crate, we can figure out a lint level! match tcx.def_kind(def_id) { diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs index 5831b0bcd8fa3..8905f475647ba 100644 --- a/src/librustc_save_analysis/span_utils.rs +++ b/src/librustc_save_analysis/span_utils.rs @@ -2,8 +2,6 @@ use rustc::session::Session; use crate::generated_code; -use std::cell::Cell; - use syntax::parse::lexer::{self, StringReader}; use syntax::parse::token::{self, TokenKind}; use syntax_pos::*; @@ -11,16 +9,12 @@ use syntax_pos::*; #[derive(Clone)] pub struct SpanUtils<'a> { pub sess: &'a Session, - // FIXME given that we clone SpanUtils all over the place, this err_count is - // probably useless and any logic relying on it is bogus. - pub err_count: Cell, } impl<'a> SpanUtils<'a> { pub fn new(sess: &'a Session) -> SpanUtils<'a> { SpanUtils { sess, - err_count: Cell::new(0), } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 40812b6a952d9..6d092011f7c9c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -527,6 +527,8 @@ pub struct FnCtxt<'a, 'tcx> { /// checking this function. On exit, if we find that *more* errors /// have been reported, we will skip regionck and other work that /// expects the types within the function to be consistent. + // FIXME(matthewjasper) This should not exist, and it's not correct + // if type checking is run in parallel. err_count_on_creation: usize, ret_coercion: Option>>, @@ -696,11 +698,9 @@ impl ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> { fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { } } -pub fn check_wf_new<'tcx>(tcx: TyCtxt<'tcx>) -> Result<(), ErrorReported> { - tcx.sess.track_errors(|| { - let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx); - tcx.hir().krate().par_visit_all_item_likes(&mut visit); - }) +pub fn check_wf_new<'tcx>(tcx: TyCtxt<'tcx>) { + let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx); + tcx.hir().krate().par_visit_all_item_likes(&mut visit); } fn check_mod_item_types<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) { diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index cc6f7a07d9621..8728f80bd985c 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -321,6 +321,7 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) -> Result<(), ErrorReported> { // this ensures that later parts of type checking can assume that items // have valid types and not error + // FIXME(matthewjasper) We shouldn't need to do this. tcx.sess.track_errors(|| { time(tcx.sess, "type collecting", || { for &module in tcx.hir().krate().modules.keys() { @@ -353,7 +354,9 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) -> Result<(), ErrorReported> { })?; } - time(tcx.sess, "wf checking", || check::check_wf_new(tcx))?; + tcx.sess.track_errors(|| { + time(tcx.sess, "wf checking", || check::check_wf_new(tcx)); + })?; time(tcx.sess, "item-types checking", || { for &module in tcx.hir().krate().modules.keys() { diff --git a/src/test/ui/consts/enum-discr-type-err.rs b/src/test/ui/consts/enum-discr-type-err.rs new file mode 100644 index 0000000000000..d66c4f47d03ee --- /dev/null +++ b/src/test/ui/consts/enum-discr-type-err.rs @@ -0,0 +1,29 @@ +// Test that we mark enum discriminant values as having errors, even when the +// diagnostic is deduplicated. + +struct F; +struct T; + +impl F { + const V: i32 = 0; +} + +impl T { + const V: i32 = 0; +} + +macro_rules! mac { + ($( $v: ident = $s: ident,)*) => { + enum E { + $( $v = $s::V, )* + //~^ ERROR mismatched types + } + } +} + +mac! { + A = F, + B = T, +} + +fn main() {} diff --git a/src/test/ui/consts/enum-discr-type-err.stderr b/src/test/ui/consts/enum-discr-type-err.stderr new file mode 100644 index 0000000000000..3c4fac7327d40 --- /dev/null +++ b/src/test/ui/consts/enum-discr-type-err.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/enum-discr-type-err.rs:18:21 + | +LL | $( $v = $s::V, )* + | ^^^^^ expected isize, found i32 +... +LL | / mac! { +LL | | A = F, +LL | | B = T, +LL | | } + | |_- in this macro invocation +help: you can convert an `i32` to `isize` and panic if the converted value wouldn't fit + | +LL | $( $v = $s::V.try_into().unwrap(), )* + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`.