@@ -1337,6 +1337,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13371337 but its trait bounds were not satisfied"
13381338 )
13391339 } ) ;
1340+
13401341 err. primary_message ( primary_message) ;
13411342 if let Some ( label) = label {
13421343 custom_span_label = true ;
@@ -1353,6 +1354,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13531354
13541355 suggested_derive = self . suggest_derive ( & mut err, unsatisfied_predicates) ;
13551356
1357+ if let ty:: Adt ( adt_def, _) = rcvr_ty. kind ( )
1358+ && self . tcx . is_diagnostic_item ( sym:: HashSet , adt_def. did ( ) )
1359+ && unsatisfied_predicates. iter ( ) . any ( |( pred, _parent, _cause) | {
1360+ if let ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( pred) ) =
1361+ pred. kind ( ) . skip_binder ( )
1362+ {
1363+ self . tcx . is_diagnostic_item ( sym:: BuildHasher , pred. def_id ( ) )
1364+ } else {
1365+ false
1366+ }
1367+ } )
1368+ {
1369+ err. span_help ( span, "you might have intended to use a HashMap instead" ) ;
1370+ }
1371+
13561372 unsatisfied_bounds = true ;
13571373 }
13581374 } else if let ty:: Adt ( def, targs) = rcvr_ty. kind ( )
@@ -2925,7 +2941,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
29252941 . filter_map ( |e| match e. obligation . predicate . kind ( ) . skip_binder ( ) {
29262942 ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( pred) ) => {
29272943 match pred. self_ty ( ) . kind ( ) {
2928- ty:: Adt ( _, _) => Some ( pred) ,
2944+ ty:: Adt ( _, _) => Some ( (
2945+ ( e. root_obligation . predicate , e. root_obligation . cause . span ) ,
2946+ pred,
2947+ ) ) ,
29292948 _ => None ,
29302949 }
29312950 }
@@ -2935,18 +2954,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
29352954
29362955 // Note for local items and foreign items respectively.
29372956 let ( mut local_preds, mut foreign_preds) : ( Vec < _ > , Vec < _ > ) =
2938- preds. iter ( ) . partition ( |& pred| {
2957+ preds. iter ( ) . partition ( |& ( _ , pred) | {
29392958 if let ty:: Adt ( def, _) = pred. self_ty ( ) . kind ( ) {
29402959 def. did ( ) . is_local ( )
29412960 } else {
29422961 false
29432962 }
29442963 } ) ;
29452964
2946- local_preds. sort_by_key ( |pred : & & ty :: TraitPredicate < ' _ > | pred. trait_ref . to_string ( ) ) ;
2965+ local_preds. sort_by_key ( |( _ , pred ) | pred. trait_ref . to_string ( ) ) ;
29472966 let local_def_ids = local_preds
29482967 . iter ( )
2949- . filter_map ( |pred| match pred. self_ty ( ) . kind ( ) {
2968+ . filter_map ( |( _ , pred) | match pred. self_ty ( ) . kind ( ) {
29502969 ty:: Adt ( def, _) => Some ( def. did ( ) ) ,
29512970 _ => None ,
29522971 } )
@@ -2959,7 +2978,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
29592978 } )
29602979 . collect :: < Vec < _ > > ( )
29612980 . into ( ) ;
2962- for pred in & local_preds {
2981+ for ( _ , pred) in & local_preds {
29632982 if let ty:: Adt ( def, _) = pred. self_ty ( ) . kind ( ) {
29642983 local_spans. push_span_label (
29652984 self . tcx . def_span ( def. did ( ) ) ,
@@ -2968,7 +2987,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
29682987 }
29692988 }
29702989 if local_spans. primary_span ( ) . is_some ( ) {
2971- let msg = if let [ local_pred] = local_preds. as_slice ( ) {
2990+ let msg = if let [ ( _ , local_pred) ] = local_preds. as_slice ( ) {
29722991 format ! (
29732992 "an implementation of `{}` might be missing for `{}`" ,
29742993 local_pred. trait_ref. print_trait_sugared( ) ,
@@ -2986,10 +3005,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
29863005 err. span_note ( local_spans, msg) ;
29873006 }
29883007
2989- foreign_preds. sort_by_key ( |pred : & & ty :: TraitPredicate < ' _ > | pred. trait_ref . to_string ( ) ) ;
3008+ foreign_preds. sort_by_key ( |( _ , pred ) | pred. trait_ref . to_string ( ) ) ;
29903009 let foreign_def_ids = foreign_preds
29913010 . iter ( )
2992- . filter_map ( |pred| match pred. self_ty ( ) . kind ( ) {
3011+ . filter_map ( |( _ , pred) | match pred. self_ty ( ) . kind ( ) {
29933012 ty:: Adt ( def, _) => Some ( def. did ( ) ) ,
29943013 _ => None ,
29953014 } )
@@ -3002,7 +3021,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30023021 } )
30033022 . collect :: < Vec < _ > > ( )
30043023 . into ( ) ;
3005- for pred in & foreign_preds {
3024+ for ( _ , pred) in & foreign_preds {
30063025 if let ty:: Adt ( def, _) = pred. self_ty ( ) . kind ( ) {
30073026 foreign_spans. push_span_label (
30083027 self . tcx . def_span ( def. did ( ) ) ,
@@ -3011,7 +3030,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30113030 }
30123031 }
30133032 if foreign_spans. primary_span ( ) . is_some ( ) {
3014- let msg = if let [ foreign_pred] = foreign_preds. as_slice ( ) {
3033+ let msg = if let [ ( _ , foreign_pred) ] = foreign_preds. as_slice ( ) {
30153034 format ! (
30163035 "the foreign item type `{}` doesn't implement `{}`" ,
30173036 foreign_pred. self_ty( ) ,
@@ -3027,6 +3046,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30273046 )
30283047 } ;
30293048 err. span_note ( foreign_spans, msg) ;
3049+
3050+ if let Some ( span) = foreign_preds. iter ( ) . find_map ( |& ( ( root_pred, span) , pred) | {
3051+ match root_pred. kind ( ) . skip_binder ( ) {
3052+ ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( root_pred) )
3053+ if let Some ( root_adt) = root_pred. self_ty ( ) . ty_adt_def ( )
3054+ && self . tcx . is_diagnostic_item ( sym:: HashSet , root_adt. did ( ) )
3055+ && self . tcx . is_diagnostic_item ( sym:: BuildHasher , pred. def_id ( ) ) =>
3056+ {
3057+ Some ( span)
3058+ }
3059+ _ => None ,
3060+ }
3061+ } ) {
3062+ err. span_help ( span, "you might have intended to use a HashMap instead" ) ;
3063+ }
30303064 }
30313065
30323066 let preds: Vec < _ > = errors
0 commit comments