Count all errors for track_errors
This commit is contained in:
parent
30b6c59f24
commit
95a32157af
8 changed files with 77 additions and 29 deletions
|
@ -171,6 +171,7 @@ pub struct InferCtxt<'a, 'tcx> {
|
||||||
/// Track how many errors were reported when this infcx is created.
|
/// Track how many errors were reported when this infcx is created.
|
||||||
/// If the number of errors increases, that's also a sign (line
|
/// If the number of errors increases, that's also a sign (line
|
||||||
/// `tained_by_errors`) to avoid reporting certain kinds of errors.
|
/// `tained_by_errors`) to avoid reporting certain kinds of errors.
|
||||||
|
// FIXME(matthewjasper) Merge into `tainted_by_errors_flag`
|
||||||
err_count_on_creation: usize,
|
err_count_on_creation: usize,
|
||||||
|
|
||||||
/// This flag is true while there is an active snapshot.
|
/// This flag is true while there is an active snapshot.
|
||||||
|
|
|
@ -307,7 +307,12 @@ pub use diagnostic_builder::DiagnosticBuilder;
|
||||||
pub struct Handler {
|
pub struct Handler {
|
||||||
pub flags: HandlerFlags,
|
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,
|
err_count: AtomicUsize,
|
||||||
|
deduplicated_err_count: AtomicUsize,
|
||||||
emitter: Lock<Box<dyn Emitter + sync::Send>>,
|
emitter: Lock<Box<dyn Emitter + sync::Send>>,
|
||||||
continue_after_error: AtomicBool,
|
continue_after_error: AtomicBool,
|
||||||
delayed_span_bugs: Lock<Vec<Diagnostic>>,
|
delayed_span_bugs: Lock<Vec<Diagnostic>>,
|
||||||
|
@ -407,6 +412,7 @@ impl Handler {
|
||||||
Handler {
|
Handler {
|
||||||
flags,
|
flags,
|
||||||
err_count: AtomicUsize::new(0),
|
err_count: AtomicUsize::new(0),
|
||||||
|
deduplicated_err_count: AtomicUsize::new(0),
|
||||||
emitter: Lock::new(e),
|
emitter: Lock::new(e),
|
||||||
continue_after_error: AtomicBool::new(true),
|
continue_after_error: AtomicBool::new(true),
|
||||||
delayed_span_bugs: Lock::new(Vec::new()),
|
delayed_span_bugs: Lock::new(Vec::new()),
|
||||||
|
@ -428,6 +434,7 @@ impl Handler {
|
||||||
pub fn reset_err_count(&self) {
|
pub fn reset_err_count(&self) {
|
||||||
// actually frees the underlying memory (which `clear` would not do)
|
// actually frees the underlying memory (which `clear` would not do)
|
||||||
*self.emitted_diagnostics.borrow_mut() = Default::default();
|
*self.emitted_diagnostics.borrow_mut() = Default::default();
|
||||||
|
self.deduplicated_err_count.store(0, SeqCst);
|
||||||
self.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) {
|
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,
|
0 => return,
|
||||||
1 => "aborting due to previous error".to_string(),
|
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() {
|
if self.treat_err_as_bug() {
|
||||||
return;
|
return;
|
||||||
|
@ -769,9 +776,12 @@ impl Handler {
|
||||||
if self.emitted_diagnostics.borrow_mut().insert(diagnostic_hash) {
|
if self.emitted_diagnostics.borrow_mut().insert(diagnostic_hash) {
|
||||||
self.emitter.borrow_mut().emit_diagnostic(db);
|
self.emitter.borrow_mut().emit_diagnostic(db);
|
||||||
if db.is_error() {
|
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) {
|
pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
|
||||||
|
|
|
@ -15,7 +15,6 @@ use rustc::ty::{self, TyCtxt, query::TyCtxtAt};
|
||||||
use rustc::ty::layout::{self, LayoutOf, VariantIdx};
|
use rustc::ty::layout::{self, LayoutOf, VariantIdx};
|
||||||
use rustc::ty::subst::Subst;
|
use rustc::ty::subst::Subst;
|
||||||
use rustc::traits::Reveal;
|
use rustc::traits::Reveal;
|
||||||
use rustc::util::common::ErrorReported;
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
|
||||||
use syntax::source_map::{Span, DUMMY_SP};
|
use syntax::source_map::{Span, DUMMY_SP};
|
||||||
|
@ -655,19 +654,12 @@ pub fn const_eval_raw_provider<'tcx>(
|
||||||
if tcx.is_static(def_id) {
|
if tcx.is_static(def_id) {
|
||||||
// Ensure that if the above error was either `TooGeneric` or `Reported`
|
// Ensure that if the above error was either `TooGeneric` or `Reported`
|
||||||
// an error must be reported.
|
// an error must be reported.
|
||||||
let reported_err = tcx.sess.track_errors(|| {
|
let v = err.report_as_error(ecx.tcx, "could not evaluate static initializer");
|
||||||
err.report_as_error(ecx.tcx,
|
tcx.sess.delay_span_bug(
|
||||||
"could not evaluate static initializer")
|
err.span,
|
||||||
});
|
&format!("static eval failure did not emit an error: {:#?}", v)
|
||||||
match reported_err {
|
);
|
||||||
Ok(v) => {
|
v
|
||||||
tcx.sess.delay_span_bug(err.span,
|
|
||||||
&format!("static eval failure did not emit an error: {:#?}",
|
|
||||||
v));
|
|
||||||
v
|
|
||||||
},
|
|
||||||
Err(ErrorReported) => ErrorHandled::Reported,
|
|
||||||
}
|
|
||||||
} else if def_id.is_local() {
|
} else if def_id.is_local() {
|
||||||
// constant defined in this crate, we can figure out a lint level!
|
// constant defined in this crate, we can figure out a lint level!
|
||||||
match tcx.def_kind(def_id) {
|
match tcx.def_kind(def_id) {
|
||||||
|
|
|
@ -2,8 +2,6 @@ use rustc::session::Session;
|
||||||
|
|
||||||
use crate::generated_code;
|
use crate::generated_code;
|
||||||
|
|
||||||
use std::cell::Cell;
|
|
||||||
|
|
||||||
use syntax::parse::lexer::{self, StringReader};
|
use syntax::parse::lexer::{self, StringReader};
|
||||||
use syntax::parse::token::{self, TokenKind};
|
use syntax::parse::token::{self, TokenKind};
|
||||||
use syntax_pos::*;
|
use syntax_pos::*;
|
||||||
|
@ -11,16 +9,12 @@ use syntax_pos::*;
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SpanUtils<'a> {
|
pub struct SpanUtils<'a> {
|
||||||
pub sess: &'a Session,
|
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<isize>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SpanUtils<'a> {
|
impl<'a> SpanUtils<'a> {
|
||||||
pub fn new(sess: &'a Session) -> SpanUtils<'a> {
|
pub fn new(sess: &'a Session) -> SpanUtils<'a> {
|
||||||
SpanUtils {
|
SpanUtils {
|
||||||
sess,
|
sess,
|
||||||
err_count: Cell::new(0),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -527,6 +527,8 @@ pub struct FnCtxt<'a, 'tcx> {
|
||||||
/// checking this function. On exit, if we find that *more* errors
|
/// checking this function. On exit, if we find that *more* errors
|
||||||
/// have been reported, we will skip regionck and other work that
|
/// have been reported, we will skip regionck and other work that
|
||||||
/// expects the types within the function to be consistent.
|
/// 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,
|
err_count_on_creation: usize,
|
||||||
|
|
||||||
ret_coercion: Option<RefCell<DynamicCoerceMany<'tcx>>>,
|
ret_coercion: Option<RefCell<DynamicCoerceMany<'tcx>>>,
|
||||||
|
@ -696,11 +698,9 @@ impl ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> {
|
||||||
fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { }
|
fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_wf_new<'tcx>(tcx: TyCtxt<'tcx>) -> Result<(), ErrorReported> {
|
pub fn check_wf_new<'tcx>(tcx: TyCtxt<'tcx>) {
|
||||||
tcx.sess.track_errors(|| {
|
let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx);
|
||||||
let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx);
|
tcx.hir().krate().par_visit_all_item_likes(&mut visit);
|
||||||
tcx.hir().krate().par_visit_all_item_likes(&mut visit);
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_mod_item_types<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
|
fn check_mod_item_types<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
|
||||||
|
|
|
@ -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
|
// this ensures that later parts of type checking can assume that items
|
||||||
// have valid types and not error
|
// have valid types and not error
|
||||||
|
// FIXME(matthewjasper) We shouldn't need to do this.
|
||||||
tcx.sess.track_errors(|| {
|
tcx.sess.track_errors(|| {
|
||||||
time(tcx.sess, "type collecting", || {
|
time(tcx.sess, "type collecting", || {
|
||||||
for &module in tcx.hir().krate().modules.keys() {
|
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", || {
|
time(tcx.sess, "item-types checking", || {
|
||||||
for &module in tcx.hir().krate().modules.keys() {
|
for &module in tcx.hir().krate().modules.keys() {
|
||||||
|
|
29
src/test/ui/consts/enum-discr-type-err.rs
Normal file
29
src/test/ui/consts/enum-discr-type-err.rs
Normal file
|
@ -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() {}
|
19
src/test/ui/consts/enum-discr-type-err.stderr
Normal file
19
src/test/ui/consts/enum-discr-type-err.stderr
Normal file
|
@ -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`.
|
Loading…
Add table
Add a link
Reference in a new issue