Skip to content

Commit c5e6069

Browse files
authored
Rollup merge of rust-lang#62055 - matthewjasper:fix-error-counting, r=pnkfelix
Fix error counting Count duplicate errors for `track_errors` and other error counting checks. Add FIXMEs to make it clear that we should be moving away from this kind of logic. Closes rust-lang#61663
2 parents 81be122 + 95a3215 commit c5e6069

File tree

13 files changed

+96
-54
lines changed

13 files changed

+96
-54
lines changed

src/librustc/infer/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ pub struct InferCtxt<'a, 'tcx> {
171171
/// Track how many errors were reported when this infcx is created.
172172
/// If the number of errors increases, that's also a sign (line
173173
/// `tained_by_errors`) to avoid reporting certain kinds of errors.
174+
// FIXME(matthewjasper) Merge into `tainted_by_errors_flag`
174175
err_count_on_creation: usize,
175176

176177
/// This flag is true while there is an active snapshot.

src/librustc/session/mod.rs

+6-9
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,13 @@ impl Session {
320320
self.diagnostic().abort_if_errors();
321321
}
322322
pub fn compile_status(&self) -> Result<(), ErrorReported> {
323-
compile_result_from_err_count(self.err_count())
323+
if self.has_errors() {
324+
Err(ErrorReported)
325+
} else {
326+
Ok(())
327+
}
324328
}
329+
// FIXME(matthewjasper) Remove this method, it should never be needed.
325330
pub fn track_errors<F, T>(&self, f: F) -> Result<T, ErrorReported>
326331
where
327332
F: FnOnce() -> T,
@@ -1388,11 +1393,3 @@ pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
13881393
}
13891394

13901395
pub type CompileResult = Result<(), ErrorReported>;
1391-
1392-
pub fn compile_result_from_err_count(err_count: usize) -> CompileResult {
1393-
if err_count == 0 {
1394-
Ok(())
1395-
} else {
1396-
Err(ErrorReported)
1397-
}
1398-
}

src/librustc_errors/lib.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,12 @@ pub use diagnostic_builder::DiagnosticBuilder;
307307
pub struct Handler {
308308
pub flags: HandlerFlags,
309309

310+
/// The number of errors that have been emitted, including duplicates.
311+
///
312+
/// This is not necessarily the count that's reported to the user once
313+
/// compilation ends.
310314
err_count: AtomicUsize,
315+
deduplicated_err_count: AtomicUsize,
311316
emitter: Lock<Box<dyn Emitter + sync::Send>>,
312317
continue_after_error: AtomicBool,
313318
delayed_span_bugs: Lock<Vec<Diagnostic>>,
@@ -352,7 +357,7 @@ pub struct HandlerFlags {
352357

353358
impl Drop for Handler {
354359
fn drop(&mut self) {
355-
if self.err_count() == 0 {
360+
if !self.has_errors() {
356361
let mut bugs = self.delayed_span_bugs.borrow_mut();
357362
let has_bugs = !bugs.is_empty();
358363
for bug in bugs.drain(..) {
@@ -407,6 +412,7 @@ impl Handler {
407412
Handler {
408413
flags,
409414
err_count: AtomicUsize::new(0),
415+
deduplicated_err_count: AtomicUsize::new(0),
410416
emitter: Lock::new(e),
411417
continue_after_error: AtomicBool::new(true),
412418
delayed_span_bugs: Lock::new(Vec::new()),
@@ -428,6 +434,7 @@ impl Handler {
428434
pub fn reset_err_count(&self) {
429435
// actually frees the underlying memory (which `clear` would not do)
430436
*self.emitted_diagnostics.borrow_mut() = Default::default();
437+
self.deduplicated_err_count.store(0, SeqCst);
431438
self.err_count.store(0, SeqCst);
432439
}
433440

@@ -660,10 +667,10 @@ impl Handler {
660667
}
661668

662669
pub fn print_error_count(&self, registry: &Registry) {
663-
let s = match self.err_count() {
670+
let s = match self.deduplicated_err_count.load(SeqCst) {
664671
0 => return,
665672
1 => "aborting due to previous error".to_string(),
666-
_ => format!("aborting due to {} previous errors", self.err_count())
673+
count => format!("aborting due to {} previous errors", count)
667674
};
668675
if self.treat_err_as_bug() {
669676
return;
@@ -705,10 +712,9 @@ impl Handler {
705712
}
706713

707714
pub fn abort_if_errors(&self) {
708-
if self.err_count() == 0 {
709-
return;
715+
if self.has_errors() {
716+
FatalError.raise();
710717
}
711-
FatalError.raise();
712718
}
713719
pub fn emit(&self, msp: &MultiSpan, msg: &str, lvl: Level) {
714720
if lvl == Warning && !self.flags.can_emit_warnings {
@@ -770,9 +776,12 @@ impl Handler {
770776
if self.emitted_diagnostics.borrow_mut().insert(diagnostic_hash) {
771777
self.emitter.borrow_mut().emit_diagnostic(db);
772778
if db.is_error() {
773-
self.bump_err_count();
779+
self.deduplicated_err_count.fetch_add(1, SeqCst);
774780
}
775781
}
782+
if db.is_error() {
783+
self.bump_err_count();
784+
}
776785
}
777786

778787
pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {

src/librustc_interface/passes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,7 @@ fn analysis<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> Result<()> {
959959
// lot of annoying errors in the compile-fail tests (basically,
960960
// lint warnings and so on -- kindck used to do this abort, but
961961
// kindck is gone now). -nmatsakis
962-
if sess.err_count() > 0 {
962+
if sess.has_errors() {
963963
return Err(ErrorReported);
964964
}
965965

src/librustc_mir/const_eval.rs

+6-14
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ use rustc::ty::{self, TyCtxt, query::TyCtxtAt};
1515
use rustc::ty::layout::{self, LayoutOf, VariantIdx};
1616
use rustc::ty::subst::Subst;
1717
use rustc::traits::Reveal;
18-
use rustc::util::common::ErrorReported;
1918
use rustc_data_structures::fx::FxHashMap;
2019

2120
use syntax::source_map::{Span, DUMMY_SP};
@@ -655,19 +654,12 @@ pub fn const_eval_raw_provider<'tcx>(
655654
if tcx.is_static(def_id) {
656655
// Ensure that if the above error was either `TooGeneric` or `Reported`
657656
// an error must be reported.
658-
let reported_err = tcx.sess.track_errors(|| {
659-
err.report_as_error(ecx.tcx,
660-
"could not evaluate static initializer")
661-
});
662-
match reported_err {
663-
Ok(v) => {
664-
tcx.sess.delay_span_bug(err.span,
665-
&format!("static eval failure did not emit an error: {:#?}",
666-
v));
667-
v
668-
},
669-
Err(ErrorReported) => ErrorHandled::Reported,
670-
}
657+
let v = err.report_as_error(ecx.tcx, "could not evaluate static initializer");
658+
tcx.sess.delay_span_bug(
659+
err.span,
660+
&format!("static eval failure did not emit an error: {:#?}", v)
661+
);
662+
v
671663
} else if def_id.is_local() {
672664
// constant defined in this crate, we can figure out a lint level!
673665
match tcx.def_kind(def_id) {

src/librustc_save_analysis/span_utils.rs

-6
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,19 @@ use rustc::session::Session;
22

33
use crate::generated_code;
44

5-
use std::cell::Cell;
6-
75
use syntax::parse::lexer::{self, StringReader};
86
use syntax::parse::token::{self, TokenKind};
97
use syntax_pos::*;
108

119
#[derive(Clone)]
1210
pub struct SpanUtils<'a> {
1311
pub sess: &'a Session,
14-
// FIXME given that we clone SpanUtils all over the place, this err_count is
15-
// probably useless and any logic relying on it is bogus.
16-
pub err_count: Cell<isize>,
1712
}
1813

1914
impl<'a> SpanUtils<'a> {
2015
pub fn new(sess: &'a Session) -> SpanUtils<'a> {
2116
SpanUtils {
2217
sess,
23-
err_count: Cell::new(0),
2418
}
2519
}
2620

src/librustc_typeck/check/expr.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
565565
// else an error would have been flagged by the
566566
// `loops` pass for using break with an expression
567567
// where you are not supposed to.
568-
assert!(expr_opt.is_none() || self.tcx.sess.err_count() > 0);
568+
assert!(expr_opt.is_none() || self.tcx.sess.has_errors());
569569
}
570570

571571
ctxt.may_break = true;
@@ -577,10 +577,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
577577
// this can only happen if the `break` was not
578578
// inside a loop at all, which is caught by the
579579
// loop-checking pass.
580-
if self.tcx.sess.err_count() == 0 {
581-
self.tcx.sess.delay_span_bug(expr.span,
582-
"break was outside loop, but no error was emitted");
583-
}
580+
self.tcx.sess.delay_span_bug(expr.span,
581+
"break was outside loop, but no error was emitted");
584582

585583
// We still need to assign a type to the inner expression to
586584
// prevent the ICE in #43162.

src/librustc_typeck/check/mod.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,8 @@ pub struct FnCtxt<'a, 'tcx> {
527527
/// checking this function. On exit, if we find that *more* errors
528528
/// have been reported, we will skip regionck and other work that
529529
/// expects the types within the function to be consistent.
530+
// FIXME(matthewjasper) This should not exist, and it's not correct
531+
// if type checking is run in parallel.
530532
err_count_on_creation: usize,
531533

532534
ret_coercion: Option<RefCell<DynamicCoerceMany<'tcx>>>,
@@ -696,11 +698,9 @@ impl ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> {
696698
fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { }
697699
}
698700

699-
pub fn check_wf_new<'tcx>(tcx: TyCtxt<'tcx>) -> Result<(), ErrorReported> {
700-
tcx.sess.track_errors(|| {
701-
let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx);
702-
tcx.hir().krate().par_visit_all_item_likes(&mut visit);
703-
})
701+
pub fn check_wf_new<'tcx>(tcx: TyCtxt<'tcx>) {
702+
let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx);
703+
tcx.hir().krate().par_visit_all_item_likes(&mut visit);
704704
}
705705

706706
fn check_mod_item_types<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
@@ -2128,8 +2128,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21282128
&self.tcx.sess
21292129
}
21302130

2131-
pub fn err_count_since_creation(&self) -> usize {
2132-
self.tcx.sess.err_count() - self.err_count_on_creation
2131+
pub fn errors_reported_since_creation(&self) -> bool {
2132+
self.tcx.sess.err_count() > self.err_count_on_creation
21332133
}
21342134

21352135
/// Produces warning on the given node, if the current point in the
@@ -4375,7 +4375,7 @@ pub fn check_bounds_are_used<'tcx>(tcx: TyCtxt<'tcx>, generics: &ty::Generics, t
43754375
} else if let ty::Error = leaf_ty.sty {
43764376
// If there is already another error, do not emit
43774377
// an error for not using a type Parameter.
4378-
assert!(tcx.sess.err_count() > 0);
4378+
assert!(tcx.sess.has_errors());
43794379
return;
43804380
}
43814381
}

src/librustc_typeck/check/regionck.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
123123
// standalone expr (e.g., the `E` in a type like `[u32; E]`).
124124
rcx.outlives_environment.save_implied_bounds(id);
125125

126-
if self.err_count_since_creation() == 0 {
126+
if !self.errors_reported_since_creation() {
127127
// regionck assumes typeck succeeded
128128
rcx.visit_body(body);
129129
rcx.visit_region_obligations(id);
@@ -173,7 +173,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
173173
self.param_env,
174174
);
175175

176-
if self.err_count_since_creation() == 0 {
176+
if !self.errors_reported_since_creation() {
177177
// regionck assumes typeck succeeded
178178
rcx.visit_fn_body(fn_id, body, self.tcx.hir().span(fn_id));
179179
}

src/librustc_typeck/lib.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) -> Result<(), ErrorReported> {
320320

321321
// this ensures that later parts of type checking can assume that items
322322
// have valid types and not error
323+
// FIXME(matthewjasper) We shouldn't need to do this.
323324
tcx.sess.track_errors(|| {
324325
time(tcx.sess, "type collecting", || {
325326
for &module in tcx.hir().krate().modules.keys() {
@@ -352,7 +353,9 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) -> Result<(), ErrorReported> {
352353
})?;
353354
}
354355

355-
time(tcx.sess, "wf checking", || check::check_wf_new(tcx))?;
356+
tcx.sess.track_errors(|| {
357+
time(tcx.sess, "wf checking", || check::check_wf_new(tcx));
358+
})?;
356359

357360
time(tcx.sess, "item-types checking", || {
358361
for &module in tcx.hir().krate().modules.keys() {

src/librustdoc/core.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
346346
// current architecture.
347347
let resolver = abort_on_err(compiler.expansion(), sess).peek().1.clone();
348348

349-
if sess.err_count() > 0 {
349+
if sess.has_errors() {
350350
sess.fatal("Compilation failed, aborting rustdoc");
351351
}
352352

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Test that we mark enum discriminant values as having errors, even when the
2+
// diagnostic is deduplicated.
3+
4+
struct F;
5+
struct T;
6+
7+
impl F {
8+
const V: i32 = 0;
9+
}
10+
11+
impl T {
12+
const V: i32 = 0;
13+
}
14+
15+
macro_rules! mac {
16+
($( $v: ident = $s: ident,)*) => {
17+
enum E {
18+
$( $v = $s::V, )*
19+
//~^ ERROR mismatched types
20+
}
21+
}
22+
}
23+
24+
mac! {
25+
A = F,
26+
B = T,
27+
}
28+
29+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/enum-discr-type-err.rs:18:21
3+
|
4+
LL | $( $v = $s::V, )*
5+
| ^^^^^ expected isize, found i32
6+
...
7+
LL | / mac! {
8+
LL | | A = F,
9+
LL | | B = T,
10+
LL | | }
11+
| |_- in this macro invocation
12+
help: you can convert an `i32` to `isize` and panic if the converted value wouldn't fit
13+
|
14+
LL | $( $v = $s::V.try_into().unwrap(), )*
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
16+
17+
error: aborting due to previous error
18+
19+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)