@@ -9,7 +9,8 @@ use crate::Expectation;
9
9
use crate :: FnCtxt ;
10
10
use rustc_ast:: ast:: Mutability ;
11
11
use rustc_attr:: parse_confusables;
12
- use rustc_data_structures:: fx:: { FxHashMap , FxIndexMap , FxIndexSet } ;
12
+ use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
13
+ use rustc_data_structures:: sorted_map:: SortedMap ;
13
14
use rustc_data_structures:: unord:: UnordSet ;
14
15
use rustc_errors:: StashKey ;
15
16
use rustc_errors:: {
@@ -538,7 +539,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
538
539
) ;
539
540
}
540
541
541
- let mut bound_spans: FxHashMap < Span , Vec < String > > = Default :: default ( ) ;
542
+ let mut bound_spans: SortedMap < Span , Vec < String > > = Default :: default ( ) ;
542
543
let mut restrict_type_params = false ;
543
544
let mut unsatisfied_bounds = false ;
544
545
if item_name. name == sym:: count && self . is_slice_ty ( rcvr_ty, span) {
@@ -637,16 +638,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
637
638
match & self_ty. kind ( ) {
638
639
// Point at the type that couldn't satisfy the bound.
639
640
ty:: Adt ( def, _) => {
640
- bound_spans. entry ( tcx. def_span ( def. did ( ) ) ) . or_default ( ) . push ( msg)
641
+ bound_spans. get_mut_or_insert_default ( tcx. def_span ( def. did ( ) ) ) . push ( msg)
641
642
}
642
643
// Point at the trait object that couldn't satisfy the bound.
643
644
ty:: Dynamic ( preds, _, _) => {
644
645
for pred in preds. iter ( ) {
645
646
match pred. skip_binder ( ) {
646
647
ty:: ExistentialPredicate :: Trait ( tr) => {
647
648
bound_spans
648
- . entry ( tcx. def_span ( tr. def_id ) )
649
- . or_default ( )
649
+ . get_mut_or_insert_default ( tcx. def_span ( tr. def_id ) )
650
650
. push ( msg. clone ( ) ) ;
651
651
}
652
652
ty:: ExistentialPredicate :: Projection ( _)
@@ -657,8 +657,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
657
657
// Point at the closure that couldn't satisfy the bound.
658
658
ty:: Closure ( def_id, _) => {
659
659
bound_spans
660
- . entry ( tcx. def_span ( * def_id) )
661
- . or_default ( )
660
+ . get_mut_or_insert_default ( tcx. def_span ( * def_id) )
662
661
. push ( format ! ( "`{quiet}`" ) ) ;
663
662
}
664
663
_ => { }
@@ -1167,20 +1166,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1167
1166
1168
1167
self . suggest_unwrapping_inner_self ( & mut err, source, rcvr_ty, item_name) ;
1169
1168
1170
- #[ allow( rustc:: potential_query_instability) ] // We immediately sort the resulting Vec.
1171
- let mut bound_spans: Vec < ( Span , Vec < String > ) > = bound_spans
1172
- . into_iter ( )
1173
- . map ( |( span, mut bounds) | {
1174
- bounds. sort ( ) ;
1175
- bounds. dedup ( ) ;
1176
- ( span, bounds)
1177
- } )
1178
- . collect ( ) ;
1179
- bound_spans. sort_by_key ( |( span, _) | * span) ;
1180
- for ( span, bounds) in bound_spans {
1169
+ for ( span, mut bounds) in bound_spans {
1181
1170
if !tcx. sess . source_map ( ) . is_span_accessible ( span) {
1182
1171
continue ;
1183
1172
}
1173
+ bounds. sort ( ) ;
1174
+ bounds. dedup ( ) ;
1184
1175
let pre = if Some ( span) == ty_span {
1185
1176
ty_span. take ( ) ;
1186
1177
format ! (
@@ -1192,6 +1183,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1192
1183
} ;
1193
1184
let msg = match & bounds[ ..] {
1194
1185
[ bound] => format ! ( "{pre}doesn't satisfy {bound}" ) ,
1186
+ bounds if bounds. len ( ) > 4 => format ! ( "doesn't satisfy {} bounds" , bounds. len( ) ) ,
1195
1187
[ bounds @ .., last] => {
1196
1188
format ! ( "{pre}doesn't satisfy {} or {last}" , bounds. join( ", " ) )
1197
1189
}
0 commit comments