@@ -460,7 +460,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
460
460
span,
461
461
leaf_trait_predicate,
462
462
) ;
463
- self . note_version_mismatch ( & mut err, leaf_trait_predicate) ;
463
+ self . note_version_mismatch ( & mut err, & obligation , leaf_trait_predicate) ;
464
464
self . suggest_remove_await ( & obligation, & mut err) ;
465
465
self . suggest_derive ( & obligation, & mut err, leaf_trait_predicate) ;
466
466
@@ -2358,6 +2358,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
2358
2358
fn note_version_mismatch (
2359
2359
& self ,
2360
2360
err : & mut Diag < ' _ > ,
2361
+ obligation : & PredicateObligation < ' tcx > ,
2361
2362
trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
2362
2363
) -> bool {
2363
2364
let get_trait_impls = |trait_def_id| {
@@ -2384,6 +2385,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
2384
2385
let traits_with_same_path =
2385
2386
traits_with_same_path. into_items ( ) . into_sorted_stable_ord_by_key ( |( p, _) | p) ;
2386
2387
let mut suggested = false ;
2388
+
2387
2389
for ( _, trait_with_same_path) in traits_with_same_path {
2388
2390
let trait_impls = get_trait_impls ( trait_with_same_path) ;
2389
2391
if trait_impls. is_empty ( ) {
@@ -2401,6 +2403,71 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
2401
2403
err. note ( crate_msg) ;
2402
2404
suggested = true ;
2403
2405
}
2406
+
2407
+ if suggested {
2408
+ return true ;
2409
+ }
2410
+
2411
+ let trait_def_id = trait_pred. def_id ( ) ;
2412
+ let trait_name = self . tcx . item_name ( trait_def_id) ;
2413
+ let trait_krate_name = self . tcx . crate_name ( trait_def_id. krate ) ;
2414
+
2415
+ // If there are multiple different versions of a crate in the dependency graph, there is already
2416
+ // a suggestion designed for this purpose in the rustc_hir_typeck compiler crate
2417
+ if self
2418
+ . tcx
2419
+ . all_traits_including_private ( )
2420
+ . find ( |def_id| {
2421
+ def_id. krate != trait_def_id. krate
2422
+ && self . tcx . crate_name ( def_id. krate ) == trait_krate_name
2423
+ && self . tcx . item_name ( def_id) == trait_name
2424
+ } )
2425
+ . is_some ( )
2426
+ {
2427
+ return false ;
2428
+ }
2429
+
2430
+ let trait_has_same_params = |other_trait_def_id : DefId | -> bool {
2431
+ let trait_generics = self . tcx . generics_of ( trait_def_id) ;
2432
+ let other_trait_generics = self . tcx . generics_of ( other_trait_def_id) ;
2433
+
2434
+ if trait_generics. count ( ) != other_trait_generics. count ( ) {
2435
+ return false ;
2436
+ }
2437
+ trait_generics. own_params . iter ( ) . zip ( other_trait_generics. own_params . iter ( ) ) . all (
2438
+ |( a, b) | {
2439
+ ( matches ! ( a. kind, ty:: GenericParamDefKind :: Type { .. } )
2440
+ && matches ! ( b. kind, ty:: GenericParamDefKind :: Type { .. } ) )
2441
+ || ( matches ! ( a. kind, ty:: GenericParamDefKind :: Lifetime , )
2442
+ && matches ! ( b. kind, ty:: GenericParamDefKind :: Lifetime ) )
2443
+ || ( matches ! ( a. kind, ty:: GenericParamDefKind :: Const { .. } )
2444
+ && matches ! ( b. kind, ty:: GenericParamDefKind :: Const { .. } ) )
2445
+ } ,
2446
+ )
2447
+ } ;
2448
+ let trait_name = self . tcx . item_name ( trait_def_id) ;
2449
+ if let Some ( other_trait_def_id) = self . tcx . all_traits_including_private ( ) . find ( |def_id| {
2450
+ trait_def_id != * def_id
2451
+ && trait_name == self . tcx . item_name ( def_id)
2452
+ && trait_has_same_params ( * def_id)
2453
+ && self . predicate_must_hold_modulo_regions ( & Obligation :: new (
2454
+ self . tcx ,
2455
+ obligation. cause . clone ( ) ,
2456
+ obligation. param_env ,
2457
+ trait_pred. map_bound ( |tr| ty:: TraitPredicate {
2458
+ trait_ref : ty:: TraitRef :: new ( self . tcx , * def_id, tr. trait_ref . args ) ,
2459
+ ..tr
2460
+ } ) ,
2461
+ ) )
2462
+ } ) {
2463
+ err. note ( format ! (
2464
+ "`{}` implements similarly named `{}`, but not `{}`" ,
2465
+ trait_pred. self_ty( ) ,
2466
+ self . tcx. def_path_str( other_trait_def_id) ,
2467
+ trait_pred. print_modifiers_and_trait_path( )
2468
+ ) ) ;
2469
+ suggested = true ;
2470
+ }
2404
2471
suggested
2405
2472
}
2406
2473
0 commit comments