@@ -1753,6 +1753,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17531753 err. note ( note) ;
17541754 }
17551755
1756+ if let ty:: Adt ( adt_def, _) = rcvr_ty. kind ( )
1757+ && self . tcx . is_diagnostic_item ( sym:: HashSet , adt_def. did ( ) )
1758+ && unsatisfied_predicates. iter ( ) . any ( |( pred, _parent, _cause) | {
1759+ if let ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( pred) ) =
1760+ pred. kind ( ) . skip_binder ( )
1761+ {
1762+ self . tcx . is_diagnostic_item ( sym:: BuildHasher , pred. def_id ( ) )
1763+ } else {
1764+ false
1765+ }
1766+ } )
1767+ {
1768+ err. help ( "you might have intended to use a HashMap instead" ) ;
1769+ }
1770+
17561771 * suggested_derive = self . suggest_derive ( err, unsatisfied_predicates) ;
17571772 * unsatisfied_bounds = true ;
17581773 }
@@ -2989,7 +3004,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
29893004 . filter_map ( |e| match e. obligation . predicate . kind ( ) . skip_binder ( ) {
29903005 ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( pred) ) => {
29913006 match pred. self_ty ( ) . kind ( ) {
2992- ty:: Adt ( _, _) => Some ( pred) ,
3007+ ty:: Adt ( _, _) => Some ( ( e . root_obligation . predicate , pred) ) ,
29933008 _ => None ,
29943009 }
29953010 }
@@ -2999,18 +3014,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
29993014
30003015 // Note for local items and foreign items respectively.
30013016 let ( mut local_preds, mut foreign_preds) : ( Vec < _ > , Vec < _ > ) =
3002- preds. iter ( ) . partition ( |& pred| {
3017+ preds. iter ( ) . partition ( |& ( _ , pred) | {
30033018 if let ty:: Adt ( def, _) = pred. self_ty ( ) . kind ( ) {
30043019 def. did ( ) . is_local ( )
30053020 } else {
30063021 false
30073022 }
30083023 } ) ;
30093024
3010- local_preds. sort_by_key ( |pred : & & ty :: TraitPredicate < ' _ > | pred. trait_ref . to_string ( ) ) ;
3025+ local_preds. sort_by_key ( |( _ , pred ) | pred. trait_ref . to_string ( ) ) ;
30113026 let local_def_ids = local_preds
30123027 . iter ( )
3013- . filter_map ( |pred| match pred. self_ty ( ) . kind ( ) {
3028+ . filter_map ( |( _ , pred) | match pred. self_ty ( ) . kind ( ) {
30143029 ty:: Adt ( def, _) => Some ( def. did ( ) ) ,
30153030 _ => None ,
30163031 } )
@@ -3023,7 +3038,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30233038 } )
30243039 . collect :: < Vec < _ > > ( )
30253040 . into ( ) ;
3026- for pred in & local_preds {
3041+ for ( _ , pred) in & local_preds {
30273042 if let ty:: Adt ( def, _) = pred. self_ty ( ) . kind ( ) {
30283043 local_spans. push_span_label (
30293044 self . tcx . def_span ( def. did ( ) ) ,
@@ -3032,7 +3047,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30323047 }
30333048 }
30343049 if local_spans. primary_span ( ) . is_some ( ) {
3035- let msg = if let [ local_pred] = local_preds. as_slice ( ) {
3050+ let msg = if let [ ( _ , local_pred) ] = local_preds. as_slice ( ) {
30363051 format ! (
30373052 "an implementation of `{}` might be missing for `{}`" ,
30383053 local_pred. trait_ref. print_trait_sugared( ) ,
@@ -3050,9 +3065,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30503065 err. span_note ( local_spans, msg) ;
30513066 }
30523067
3053- foreign_preds. sort_by_key ( |pred : & & ty:: TraitPredicate < ' _ > | pred. trait_ref . to_string ( ) ) ;
3068+ foreign_preds
3069+ . sort_by_key ( |( _, pred) : & ( _ , ty:: TraitPredicate < ' _ > ) | pred. trait_ref . to_string ( ) ) ;
30543070
3055- for pred in foreign_preds {
3071+ for ( _ , pred) in & foreign_preds {
30563072 let ty = pred. self_ty ( ) ;
30573073 let ty:: Adt ( def, _) = ty. kind ( ) else { continue } ;
30583074 let span = self . tcx . def_span ( def. did ( ) ) ;
@@ -3065,6 +3081,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30653081 mspan,
30663082 format ! ( "`{ty}` does not implement `{}`" , pred. trait_ref. print_trait_sugared( ) ) ,
30673083 ) ;
3084+
3085+ if foreign_preds. iter ( ) . any ( |& ( root_pred, pred) | {
3086+ if let ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( root_pred) ) =
3087+ root_pred. kind ( ) . skip_binder ( )
3088+ && let Some ( root_adt) = root_pred. self_ty ( ) . ty_adt_def ( )
3089+ {
3090+ self . tcx . is_diagnostic_item ( sym:: HashSet , root_adt. did ( ) )
3091+ && self . tcx . is_diagnostic_item ( sym:: BuildHasher , pred. def_id ( ) )
3092+ } else {
3093+ false
3094+ }
3095+ } ) {
3096+ err. help ( "you might have intended to use a HashMap instead" ) ;
3097+ }
30683098 }
30693099
30703100 let preds: Vec < _ > = errors
0 commit comments