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