@@ -25,7 +25,7 @@ use rustc::mir::{
25
25
use rustc:: ty:: { self , RegionVid , Ty , TyCtxt , TypeFoldable } ;
26
26
use rustc:: util:: common;
27
27
use rustc_data_structures:: bit_set:: BitSet ;
28
- use rustc_data_structures:: fx:: FxHashMap ;
28
+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
29
29
use rustc_data_structures:: graph:: scc:: Sccs ;
30
30
use rustc_data_structures:: indexed_vec:: IndexVec ;
31
31
use rustc_errors:: { Diagnostic , DiagnosticBuilder } ;
@@ -67,10 +67,8 @@ pub struct RegionInferenceContext<'tcx> {
67
67
constraint_sccs : Rc < Sccs < RegionVid , ConstraintSccIndex > > ,
68
68
69
69
/// Map closure bounds to a `Span` that should be used for error reporting.
70
- closure_bounds_mapping : FxHashMap <
71
- Location ,
72
- FxHashMap < ( RegionVid , RegionVid ) , ( ConstraintCategory , Span ) > ,
73
- > ,
70
+ closure_bounds_mapping :
71
+ FxHashMap < Location , FxHashMap < ( RegionVid , RegionVid ) , ( ConstraintCategory , Span ) > > ,
74
72
75
73
/// Contains the minimum universe of any variable within the same
76
74
/// SCC. We will ensure that no SCC contains values that are not
@@ -580,6 +578,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
580
578
) {
581
579
let tcx = infcx. tcx ;
582
580
581
+ // Sometimes we register equivalent type-tests that would
582
+ // result in basically the exact same error being reported to
583
+ // the user. Avoid that.
584
+ let mut deduplicate_errors = FxHashSet :: default ( ) ;
585
+
583
586
for type_test in & self . type_tests {
584
587
debug ! ( "check_type_test: {:?}" , type_test) ;
585
588
@@ -605,11 +608,31 @@ impl<'tcx> RegionInferenceContext<'tcx> {
605
608
}
606
609
}
607
610
608
- // Oh the humanity. Obviously we will do better than this error eventually.
611
+ // Type-test failed. Report the error.
612
+
613
+ // Try to convert the lower-bound region into something named we can print for the user.
609
614
let lower_bound_region = self . to_error_region ( type_test. lower_bound ) ;
615
+
616
+ // Skip duplicate-ish errors.
617
+ let type_test_span = type_test. locations . span ( mir) ;
618
+ let erased_generic_kind = tcx. erase_regions ( & type_test. generic_kind ) ;
619
+ if !deduplicate_errors. insert ( (
620
+ erased_generic_kind,
621
+ lower_bound_region,
622
+ type_test. locations ,
623
+ ) ) {
624
+ continue ;
625
+ } else {
626
+ debug ! (
627
+ "check_type_test: reporting error for erased_generic_kind={:?}, \
628
+ lower_bound_region={:?}, \
629
+ type_test.locations={:?}",
630
+ erased_generic_kind, lower_bound_region, type_test. locations,
631
+ ) ;
632
+ }
633
+
610
634
if let Some ( lower_bound_region) = lower_bound_region {
611
635
let region_scope_tree = & tcx. region_scope_tree ( mir_def_id) ;
612
- let type_test_span = type_test. locations . span ( mir) ;
613
636
infcx
614
637
. construct_generic_bound_failure (
615
638
region_scope_tree,
@@ -629,7 +652,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
629
652
// to report it; we could probably handle it by
630
653
// iterating over the universal regions and reporting
631
654
// an error that multiple bounds are required.
632
- let type_test_span = type_test. locations . span ( mir) ;
633
655
tcx. sess
634
656
. struct_span_err (
635
657
type_test_span,
0 commit comments