@@ -1753,6 +1753,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17531753 err. note ( note) ;
17541754 }
17551755
1756+ if let ty:: Adt ( adt_def, _) = rcvr_ty. kind ( ) {
1757+ unsatisfied_predicates. iter ( ) . find ( |( pred, _parent, _cause) | {
1758+ if let ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( pred) ) =
1759+ pred. kind ( ) . skip_binder ( )
1760+ {
1761+ self . suggest_hashmap_on_unsatisfied_hashset_buildhasher (
1762+ err, & pred, * adt_def,
1763+ )
1764+ } else {
1765+ false
1766+ }
1767+ } ) ;
1768+ }
1769+
17561770 * suggested_derive = self . suggest_derive ( err, unsatisfied_predicates) ;
17571771 * unsatisfied_bounds = true ;
17581772 }
@@ -2989,7 +3003,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
29893003 . filter_map ( |e| match e. obligation . predicate . kind ( ) . skip_binder ( ) {
29903004 ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( pred) ) => {
29913005 match pred. self_ty ( ) . kind ( ) {
2992- ty:: Adt ( _, _) => Some ( pred) ,
3006+ ty:: Adt ( _, _) => Some ( ( e . root_obligation . predicate , pred) ) ,
29933007 _ => None ,
29943008 }
29953009 }
@@ -2999,18 +3013,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
29993013
30003014 // Note for local items and foreign items respectively.
30013015 let ( mut local_preds, mut foreign_preds) : ( Vec < _ > , Vec < _ > ) =
3002- preds. iter ( ) . partition ( |& pred| {
3016+ preds. iter ( ) . partition ( |& ( _ , pred) | {
30033017 if let ty:: Adt ( def, _) = pred. self_ty ( ) . kind ( ) {
30043018 def. did ( ) . is_local ( )
30053019 } else {
30063020 false
30073021 }
30083022 } ) ;
30093023
3010- local_preds. sort_by_key ( |pred : & & ty :: TraitPredicate < ' _ > | pred. trait_ref . to_string ( ) ) ;
3024+ local_preds. sort_by_key ( |( _ , pred ) | pred. trait_ref . to_string ( ) ) ;
30113025 let local_def_ids = local_preds
30123026 . iter ( )
3013- . filter_map ( |pred| match pred. self_ty ( ) . kind ( ) {
3027+ . filter_map ( |( _ , pred) | match pred. self_ty ( ) . kind ( ) {
30143028 ty:: Adt ( def, _) => Some ( def. did ( ) ) ,
30153029 _ => None ,
30163030 } )
@@ -3023,7 +3037,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30233037 } )
30243038 . collect :: < Vec < _ > > ( )
30253039 . into ( ) ;
3026- for pred in & local_preds {
3040+ for ( _ , pred) in & local_preds {
30273041 if let ty:: Adt ( def, _) = pred. self_ty ( ) . kind ( ) {
30283042 local_spans. push_span_label (
30293043 self . tcx . def_span ( def. did ( ) ) ,
@@ -3032,7 +3046,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30323046 }
30333047 }
30343048 if local_spans. primary_span ( ) . is_some ( ) {
3035- let msg = if let [ local_pred] = local_preds. as_slice ( ) {
3049+ let msg = if let [ ( _ , local_pred) ] = local_preds. as_slice ( ) {
30363050 format ! (
30373051 "an implementation of `{}` might be missing for `{}`" ,
30383052 local_pred. trait_ref. print_trait_sugared( ) ,
@@ -3050,9 +3064,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30503064 err. span_note ( local_spans, msg) ;
30513065 }
30523066
3053- foreign_preds. sort_by_key ( |pred : & & ty:: TraitPredicate < ' _ > | pred. trait_ref . to_string ( ) ) ;
3067+ foreign_preds
3068+ . sort_by_key ( |( _, pred) : & ( _ , ty:: TraitPredicate < ' _ > ) | pred. trait_ref . to_string ( ) ) ;
30543069
3055- for pred in foreign_preds {
3070+ for ( _ , pred) in & foreign_preds {
30563071 let ty = pred. self_ty ( ) ;
30573072 let ty:: Adt ( def, _) = ty. kind ( ) else { continue } ;
30583073 let span = self . tcx . def_span ( def. did ( ) ) ;
@@ -3065,6 +3080,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30653080 mspan,
30663081 format ! ( "`{ty}` does not implement `{}`" , pred. trait_ref. print_trait_sugared( ) ) ,
30673082 ) ;
3083+
3084+ foreign_preds. iter ( ) . find ( |& ( root_pred, pred) | {
3085+ if let ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( root_pred) ) =
3086+ root_pred. kind ( ) . skip_binder ( )
3087+ && let Some ( root_adt) = root_pred. self_ty ( ) . ty_adt_def ( )
3088+ {
3089+ self . suggest_hashmap_on_unsatisfied_hashset_buildhasher ( err, pred, root_adt)
3090+ } else {
3091+ false
3092+ }
3093+ } ) ;
30683094 }
30693095
30703096 let preds: Vec < _ > = errors
@@ -4355,6 +4381,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
43554381
43564382 self . autoderef ( span, rcvr_ty) . silence_errors ( ) . any ( |( ty, _) | is_local ( ty) )
43574383 }
4384+
4385+ fn suggest_hashmap_on_unsatisfied_hashset_buildhasher (
4386+ & self ,
4387+ err : & mut Diag < ' _ > ,
4388+ pred : & ty:: TraitPredicate < ' _ > ,
4389+ adt : ty:: AdtDef < ' _ > ,
4390+ ) -> bool {
4391+ if self . tcx . is_diagnostic_item ( sym:: HashSet , adt. did ( ) )
4392+ && self . tcx . is_diagnostic_item ( sym:: BuildHasher , pred. def_id ( ) )
4393+ {
4394+ err. help ( "you might have intended to use a HashMap instead" ) ;
4395+ true
4396+ } else {
4397+ false
4398+ }
4399+ }
43584400}
43594401
43604402#[ derive( Copy , Clone , Debug ) ]
0 commit comments