@@ -9,7 +9,8 @@ use crate::Expectation;
99use crate :: FnCtxt ;
1010use rustc_ast:: ast:: Mutability ;
1111use 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 ;
1314use rustc_data_structures:: unord:: UnordSet ;
1415use rustc_errors:: StashKey ;
1516use rustc_errors:: {
@@ -538,7 +539,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
538539 ) ;
539540 }
540541
541- let mut bound_spans: FxHashMap < Span , Vec < String > > = Default :: default ( ) ;
542+ let mut bound_spans: SortedMap < Span , Vec < String > > = Default :: default ( ) ;
542543 let mut restrict_type_params = false ;
543544 let mut unsatisfied_bounds = false ;
544545 if item_name. name == sym:: count && self . is_slice_ty ( rcvr_ty, span) {
@@ -637,16 +638,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
637638 match & self_ty. kind ( ) {
638639 // Point at the type that couldn't satisfy the bound.
639640 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)
641642 }
642643 // Point at the trait object that couldn't satisfy the bound.
643644 ty:: Dynamic ( preds, _, _) => {
644645 for pred in preds. iter ( ) {
645646 match pred. skip_binder ( ) {
646647 ty:: ExistentialPredicate :: Trait ( tr) => {
647648 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 ) )
650650 . push ( msg. clone ( ) ) ;
651651 }
652652 ty:: ExistentialPredicate :: Projection ( _)
@@ -657,8 +657,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
657657 // Point at the closure that couldn't satisfy the bound.
658658 ty:: Closure ( def_id, _) => {
659659 bound_spans
660- . entry ( tcx. def_span ( * def_id) )
661- . or_default ( )
660+ . get_mut_or_insert_default ( tcx. def_span ( * def_id) )
662661 . push ( format ! ( "`{quiet}`" ) ) ;
663662 }
664663 _ => { }
@@ -1167,20 +1166,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11671166
11681167 self . suggest_unwrapping_inner_self ( & mut err, source, rcvr_ty, item_name) ;
11691168
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 {
11811170 if !tcx. sess . source_map ( ) . is_span_accessible ( span) {
11821171 continue ;
11831172 }
1173+ bounds. sort ( ) ;
1174+ bounds. dedup ( ) ;
11841175 let pre = if Some ( span) == ty_span {
11851176 ty_span. take ( ) ;
11861177 format ! (
@@ -1192,6 +1183,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11921183 } ;
11931184 let msg = match & bounds[ ..] {
11941185 [ bound] => format ! ( "{pre}doesn't satisfy {bound}" ) ,
1186+ bounds if bounds. len ( ) > 4 => format ! ( "doesn't satisfy {} bounds" , bounds. len( ) ) ,
11951187 [ bounds @ .., last] => {
11961188 format ! ( "{pre}doesn't satisfy {} or {last}" , bounds. join( ", " ) )
11971189 }
0 commit comments