@@ -35,7 +35,7 @@ use ty::fold::{TypeFolder, TypeFoldable};
3535use ty:: relate:: { Relate , RelateResult , TypeRelation } ;
3636use traits:: { self , PredicateObligations , ProjectionMode } ;
3737use rustc_data_structures:: unify:: { self , UnificationTable } ;
38- use std:: cell:: { RefCell , Ref } ;
38+ use std:: cell:: { Cell , RefCell , Ref } ;
3939use std:: fmt;
4040use syntax:: ast;
4141use syntax:: codemap;
@@ -110,6 +110,25 @@ pub struct InferCtxt<'a, 'tcx: 'a> {
110110 // documentation for `ProjectionMode`.
111111 projection_mode : ProjectionMode ,
112112
113+ // When an error occurs, we want to avoid reporting "derived"
114+ // errors that are due to this original failure. Normally, we
115+ // handle this with the `err_count_on_creation` count, which
116+ // basically just tracks how many errors were reported when we
117+ // started type-checking a fn and checks to see if any new errors
118+ // have been reported since then. Not great, but it works.
119+ //
120+ // However, when errors originated in other passes -- notably
121+ // resolve -- this heuristic breaks down. Therefore, we have this
122+ // auxiliary flag that one can set whenever one creates a
123+ // type-error that is due to an error in a prior pass.
124+ //
125+ // Don't read this flag directly, call `is_tainted_by_errors()`
126+ // and `set_tainted_by_errors()`.
127+ tainted_by_errors_flag : Cell < bool > ,
128+
129+ // Track how many errors were reported when this infcx is created.
130+ // If the number of errors increases, that's also a sign (line
131+ // `tained_by_errors`) to avoid reporting certain kinds of errors.
113132 err_count_on_creation : usize ,
114133}
115134
@@ -379,6 +398,7 @@ pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a TyCtxt<'tcx>,
379398 reported_trait_errors : RefCell :: new ( FnvHashSet ( ) ) ,
380399 normalize : false ,
381400 projection_mode : projection_mode,
401+ tainted_by_errors_flag : Cell :: new ( false ) ,
382402 err_count_on_creation : tcx. sess . err_count ( )
383403 }
384404}
@@ -1128,15 +1148,36 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
11281148 . map ( |method| resolve_ty ( method. ty ) ) )
11291149 }
11301150
1131- pub fn errors_since_creation ( & self ) -> bool {
1132- self . tcx . sess . err_count ( ) - self . err_count_on_creation != 0
1151+ /// True if errors have been reported since this infcx was
1152+ /// created. This is sometimes used as a heuristic to skip
1153+ /// reporting errors that often occur as a result of earlier
1154+ /// errors, but where it's hard to be 100% sure (e.g., unresolved
1155+ /// inference variables, regionck errors).
1156+ pub fn is_tainted_by_errors ( & self ) -> bool {
1157+ debug ! ( "is_tainted_by_errors(err_count={}, err_count_on_creation={}, \
1158+ tainted_by_errors_flag={})",
1159+ self . tcx. sess. err_count( ) ,
1160+ self . err_count_on_creation,
1161+ self . tainted_by_errors_flag. get( ) ) ;
1162+
1163+ if self . tcx . sess . err_count ( ) > self . err_count_on_creation {
1164+ return true ; // errors reported since this infcx was made
1165+ }
1166+ self . tainted_by_errors_flag . get ( )
1167+ }
1168+
1169+ /// Set the "tainted by errors" flag to true. We call this when we
1170+ /// observe an error from a prior pass.
1171+ pub fn set_tainted_by_errors ( & self ) {
1172+ debug ! ( "set_tainted_by_errors()" ) ;
1173+ self . tainted_by_errors_flag . set ( true )
11331174 }
11341175
11351176 pub fn node_type ( & self , id : ast:: NodeId ) -> Ty < ' tcx > {
11361177 match self . tables . borrow ( ) . node_types . get ( & id) {
11371178 Some ( & t) => t,
11381179 // FIXME
1139- None if self . errors_since_creation ( ) =>
1180+ None if self . is_tainted_by_errors ( ) =>
11401181 self . tcx . types . err ,
11411182 None => {
11421183 bug ! ( "no type for node {}: {} in fcx" ,
@@ -1158,7 +1199,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
11581199 free_regions : & FreeRegionMap ,
11591200 subject_node_id : ast:: NodeId ) {
11601201 let errors = self . region_vars . resolve_regions ( free_regions, subject_node_id) ;
1161- if !self . errors_since_creation ( ) {
1202+ if !self . is_tainted_by_errors ( ) {
11621203 // As a heuristic, just skip reporting region errors
11631204 // altogether if other errors have been reported while
11641205 // this infcx was in use. This is totally hokey but
0 commit comments