@@ -65,9 +65,6 @@ use super::region_inference::ConcreteFailure;
6565use super :: region_inference:: SubSupConflict ;
6666use super :: region_inference:: GenericBoundFailure ;
6767use super :: region_inference:: GenericKind ;
68- use super :: region_inference:: ProcessedErrors ;
69- use super :: region_inference:: ProcessedErrorOrigin ;
70- use super :: region_inference:: SameRegions ;
7168
7269use hir:: map as hir_map;
7370use hir;
@@ -77,11 +74,10 @@ use infer;
7774use middle:: region;
7875use traits:: { ObligationCause , ObligationCauseCode } ;
7976use ty:: { self , TyCtxt , TypeFoldable } ;
80- use ty:: { Region , ReFree , Issue32330 } ;
77+ use ty:: { Region , Issue32330 } ;
8178use ty:: error:: TypeError ;
8279
8380use std:: fmt;
84- use syntax:: ast;
8581use syntax_pos:: { Pos , Span } ;
8682use errors:: DiagnosticBuilder ;
8783
@@ -255,8 +251,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
255251
256252 // try to pre-process the errors, which will group some of them
257253 // together into a `ProcessedErrors` group:
258- let processed_errors = self . process_errors ( errors) ;
259- let errors = processed_errors. as_ref ( ) . unwrap_or ( errors) ;
254+ let errors = self . process_errors ( errors) ;
260255
261256 debug ! ( "report_region_errors: {} errors after preprocessing" , errors. len( ) ) ;
262257
@@ -278,13 +273,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
278273 sub_origin, sub_r,
279274 sup_origin, sup_r) ;
280275 }
281-
282- ProcessedErrors ( ref origins,
283- ref same_regions) => {
284- if !same_regions. is_empty ( ) {
285- self . report_processed_errors ( origins) ;
286- }
287- }
288276 }
289277 }
290278 }
@@ -300,202 +288,31 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
300288 // duplicates that will be unhelpful to the end-user. But
301289 // obviously it never weeds out ALL errors.
302290 fn process_errors ( & self , errors : & Vec < RegionResolutionError < ' tcx > > )
303- -> Option < Vec < RegionResolutionError < ' tcx > > > {
291+ -> Vec < RegionResolutionError < ' tcx > > {
304292 debug ! ( "process_errors()" ) ;
305- let mut origins = Vec :: new ( ) ;
306-
307- // we collect up ConcreteFailures and SubSupConflicts that are
308- // relating free-regions bound on the fn-header and group them
309- // together into this vector
310- let mut same_regions = Vec :: new ( ) ;
311-
312- // here we put errors that we will not be able to process nicely
313- let mut other_errors = Vec :: new ( ) ;
314-
315- // we collect up GenericBoundFailures in here.
316- let mut bound_failures = Vec :: new ( ) ;
317-
318- for error in errors {
319- // Check whether we can process this error into some other
320- // form; if not, fall through.
321- match * error {
322- ConcreteFailure ( ref origin, sub, sup) => {
323- debug ! ( "processing ConcreteFailure" ) ;
324- if let SubregionOrigin :: CompareImplMethodObligation { .. } = * origin {
325- // When comparing an impl method against a
326- // trait method, it is not helpful to suggest
327- // changes to the impl method. This is
328- // because the impl method signature is being
329- // checked using the trait's environment, so
330- // usually the changes we suggest would
331- // actually have to be applied to the *trait*
332- // method (and it's not clear that the trait
333- // method is even under the user's control).
334- } else if let Some ( same_frs) = free_regions_from_same_fn ( self . tcx , sub, sup) {
335- origins. push (
336- ProcessedErrorOrigin :: ConcreteFailure (
337- origin. clone ( ) ,
338- sub,
339- sup) ) ;
340- append_to_same_regions ( & mut same_regions, & same_frs) ;
341- continue ;
342- }
343- }
344- SubSupConflict ( ref var_origin, ref sub_origin, sub, ref sup_origin, sup) => {
345- debug ! ( "processing SubSupConflict sub: {:?} sup: {:?}" , sub, sup) ;
346- match ( sub_origin, sup_origin) {
347- ( & SubregionOrigin :: CompareImplMethodObligation { .. } , _) => {
348- // As above, when comparing an impl method
349- // against a trait method, it is not helpful
350- // to suggest changes to the impl method.
351- }
352- ( _, & SubregionOrigin :: CompareImplMethodObligation { .. } ) => {
353- // See above.
354- }
355- _ => {
356- if let Some ( same_frs) = free_regions_from_same_fn ( self . tcx , sub, sup) {
357- origins. push (
358- ProcessedErrorOrigin :: VariableFailure (
359- var_origin. clone ( ) ) ) ;
360- append_to_same_regions ( & mut same_regions, & same_frs) ;
361- continue ;
362- }
363- }
364- }
365- }
366- GenericBoundFailure ( ref origin, ref kind, region) => {
367- bound_failures. push ( ( origin. clone ( ) , kind. clone ( ) , region) ) ;
368- continue ;
369- }
370- ProcessedErrors ( ..) => {
371- bug ! ( "should not encounter a `ProcessedErrors` yet: {:?}" , error)
372- }
373- }
374-
375- // No changes to this error.
376- other_errors. push ( error. clone ( ) ) ;
377- }
378-
379- // ok, let's pull together the errors, sorted in an order that
380- // we think will help user the best
381- let mut processed_errors = vec ! [ ] ;
382-
383- // first, put the processed errors, if any
384- if !same_regions. is_empty ( ) {
385- let common_scope_id = same_regions[ 0 ] . scope_id ;
386- for sr in & same_regions {
387- // Since ProcessedErrors is used to reconstruct the function
388- // declaration, we want to make sure that they are, in fact,
389- // from the same scope
390- if sr. scope_id != common_scope_id {
391- debug ! ( "returning empty result from process_errors because
392- {} != {}" , sr. scope_id, common_scope_id) ;
393- return None ;
394- }
395- }
396- assert ! ( origins. len( ) > 0 ) ;
397- let pe = ProcessedErrors ( origins, same_regions) ;
398- debug ! ( "errors processed: {:?}" , pe) ;
399- processed_errors. push ( pe) ;
400- }
401-
402- // next, put the other misc errors
403- processed_errors. extend ( other_errors) ;
404-
405- // finally, put the `T: 'a` errors, but only if there were no
406- // other errors. otherwise, these have a very high rate of
407- // being unhelpful in practice. This is because they are
408- // basically secondary checks that test the state of the
409- // region graph after the rest of inference is done, and the
410- // other kinds of errors indicate that the region constraint
411- // graph is internally inconsistent, so these test results are
412- // likely to be meaningless.
413- if processed_errors. is_empty ( ) {
414- for ( origin, kind, region) in bound_failures {
415- processed_errors. push ( GenericBoundFailure ( origin, kind, region) ) ;
416- }
417- }
418293
419- // we should always wind up with SOME errors, unless there were no
420- // errors to start
421- assert ! ( if errors. len( ) > 0 { processed_errors. len( ) > 0 } else { true } ) ;
422-
423- return Some ( processed_errors) ;
424-
425- #[ derive( Debug ) ]
426- struct FreeRegionsFromSameFn {
427- sub_fr : ty:: FreeRegion ,
428- sup_fr : ty:: FreeRegion ,
429- scope_id : ast:: NodeId
430- }
431-
432- impl FreeRegionsFromSameFn {
433- fn new ( sub_fr : ty:: FreeRegion ,
434- sup_fr : ty:: FreeRegion ,
435- scope_id : ast:: NodeId )
436- -> FreeRegionsFromSameFn {
437- FreeRegionsFromSameFn {
438- sub_fr : sub_fr,
439- sup_fr : sup_fr,
440- scope_id : scope_id
441- }
442- }
443- }
444-
445- fn free_regions_from_same_fn < ' a , ' gcx , ' tcx > ( tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
446- sub : & ' tcx Region ,
447- sup : & ' tcx Region )
448- -> Option < FreeRegionsFromSameFn > {
449- debug ! ( "free_regions_from_same_fn(sub={:?}, sup={:?})" , sub, sup) ;
450- let ( scope_id, fr1, fr2) = match ( sub, sup) {
451- ( & ReFree ( fr1) , & ReFree ( fr2) ) => {
452- if fr1. scope != fr2. scope {
453- return None
454- }
455- assert ! ( fr1. scope == fr2. scope) ;
456- ( fr1. scope . node_id ( & tcx. region_maps ) , fr1, fr2)
457- } ,
458- _ => return None
459- } ;
460- let parent = tcx. hir . get_parent ( scope_id) ;
461- let parent_node = tcx. hir . find ( parent) ;
462- match parent_node {
463- Some ( node) => match node {
464- hir_map:: NodeItem ( item) => match item. node {
465- hir:: ItemFn ( ..) => {
466- Some ( FreeRegionsFromSameFn :: new ( fr1, fr2, scope_id) )
467- } ,
468- _ => None
469- } ,
470- hir_map:: NodeImplItem ( ..) |
471- hir_map:: NodeTraitItem ( ..) => {
472- Some ( FreeRegionsFromSameFn :: new ( fr1, fr2, scope_id) )
473- } ,
474- _ => None
475- } ,
476- None => {
477- debug ! ( "no parent node of scope_id {}" , scope_id) ;
478- None
479- }
480- }
481- }
294+ // We want to avoid reporting generic-bound failures if we can
295+ // avoid it: these have a very high rate of being unhelpful in
296+ // practice. This is because they are basically secondary
297+ // checks that test the state of the region graph after the
298+ // rest of inference is done, and the other kinds of errors
299+ // indicate that the region constraint graph is internally
300+ // inconsistent, so these test results are likely to be
301+ // meaningless.
302+ //
303+ // Therefore, we filter them out of the list unless they are
304+ // the only thing in the list.
305+
306+ let is_bound_failure = |e : & RegionResolutionError < ' tcx > | match * e {
307+ ConcreteFailure ( ..) => false ,
308+ SubSupConflict ( ..) => false ,
309+ GenericBoundFailure ( ..) => true ,
310+ } ;
482311
483- fn append_to_same_regions ( same_regions : & mut Vec < SameRegions > ,
484- same_frs : & FreeRegionsFromSameFn ) {
485- debug ! ( "append_to_same_regions(same_regions={:?}, same_frs={:?})" ,
486- same_regions, same_frs) ;
487- let scope_id = same_frs. scope_id ;
488- let ( sub_fr, sup_fr) = ( same_frs. sub_fr , same_frs. sup_fr ) ;
489- for sr in same_regions. iter_mut ( ) {
490- if sr. contains ( & sup_fr. bound_region ) && scope_id == sr. scope_id {
491- sr. push ( sub_fr. bound_region ) ;
492- return
493- }
494- }
495- same_regions. push ( SameRegions {
496- scope_id : scope_id,
497- regions : vec ! [ sub_fr. bound_region, sup_fr. bound_region]
498- } )
312+ if errors. iter ( ) . all ( |e| is_bound_failure ( e) ) {
313+ errors. clone ( )
314+ } else {
315+ errors. iter ( ) . filter ( |& e| !is_bound_failure ( e) ) . cloned ( ) . collect ( )
499316 }
500317 }
501318
@@ -1072,20 +889,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
1072889 self . note_region_origin ( & mut err, & sub_origin) ;
1073890 err. emit ( ) ;
1074891 }
1075-
1076- fn report_processed_errors ( & self ,
1077- origins : & [ ProcessedErrorOrigin < ' tcx > ] ) {
1078- for origin in origins. iter ( ) {
1079- let mut err = match * origin {
1080- ProcessedErrorOrigin :: VariableFailure ( ref var_origin) =>
1081- self . report_inference_failure ( var_origin. clone ( ) ) ,
1082- ProcessedErrorOrigin :: ConcreteFailure ( ref sr_origin, sub, sup) =>
1083- self . report_concrete_failure ( sr_origin. clone ( ) , sub, sup) ,
1084- } ;
1085-
1086- err. emit ( ) ;
1087- }
1088- }
1089892}
1090893
1091894impl < ' a , ' gcx , ' tcx > InferCtxt < ' a , ' gcx , ' tcx > {
0 commit comments