@@ -467,7 +467,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
467467                            span, 
468468                            leaf_trait_predicate, 
469469                        ) ; 
470-                         self . note_version_mismatch ( & mut  err,  leaf_trait_predicate) ; 
470+                         self . note_trait_version_mismatch ( & mut  err,  leaf_trait_predicate) ; 
471+                         self . note_adt_version_mismatch ( & mut  err,  leaf_trait_predicate) ; 
471472                        self . suggest_remove_await ( & obligation,  & mut  err) ; 
472473                        self . suggest_derive ( & obligation,  & mut  err,  leaf_trait_predicate) ; 
473474
@@ -2406,7 +2407,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
24062407    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait 
24072408/// with the same path as `trait_ref`, a help message about 
24082409/// a probable version mismatch is added to `err` 
2409- fn  note_version_mismatch ( 
2410+ fn  note_trait_version_mismatch ( 
24102411        & self , 
24112412        err :  & mut  Diag < ' _ > , 
24122413        trait_pred :  ty:: PolyTraitPredicate < ' tcx > , 
@@ -2446,15 +2447,87 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
24462447                impl_spans, 
24472448                format ! ( "trait impl{} with same name found" ,  pluralize!( trait_impls. len( ) ) ) , 
24482449            ) ; 
2449-             let  trait_crate = self . tcx . crate_name ( trait_with_same_path. krate ) ; 
2450-             let  crate_msg =
2451-                 format ! ( "perhaps two different versions of crate `{trait_crate}` are being used?" ) ; 
2452-             err. note ( crate_msg) ; 
2450+             self . note_two_crate_versions ( trait_with_same_path,  err) ; 
24532451            suggested = true ; 
24542452        } 
24552453        suggested
24562454    } 
24572455
2456+     fn  note_two_crate_versions ( & self ,  did :  DefId ,  err :  & mut  Diag < ' _ > )  { 
2457+         let  crate_name = self . tcx . crate_name ( did. krate ) ; 
2458+         let  crate_msg =
2459+             format ! ( "perhaps two different versions of crate `{crate_name}` are being used?" ) ; 
2460+         err. note ( crate_msg) ; 
2461+     } 
2462+ 
2463+     fn  note_adt_version_mismatch ( 
2464+         & self , 
2465+         err :  & mut  Diag < ' _ > , 
2466+         trait_pred :  ty:: PolyTraitPredicate < ' tcx > , 
2467+     )  { 
2468+         let  ty:: Adt ( impl_self_def,  _)  = trait_pred. self_ty ( ) . skip_binder ( ) . peel_refs ( ) . kind ( ) 
2469+         else  { 
2470+             return ; 
2471+         } ; 
2472+ 
2473+         let  impl_self_did = impl_self_def. did ( ) ; 
2474+ 
2475+         // We only want to warn about different versions of a dependency. 
2476+         // If no dependency is involved, bail. 
2477+         if  impl_self_did. krate  == LOCAL_CRATE  { 
2478+             return ; 
2479+         } 
2480+ 
2481+         let  impl_self_path = self . comparable_path ( impl_self_did) ; 
2482+         let  impl_self_crate_name = self . tcx . crate_name ( impl_self_did. krate ) ; 
2483+         let  similar_items:  UnordSet < _ >  = self 
2484+             . tcx 
2485+             . visible_parent_map ( ( ) ) 
2486+             . items ( ) 
2487+             . filter_map ( |( & item,  _) | { 
2488+                 // If we found ourselves, ignore. 
2489+                 if  impl_self_did == item { 
2490+                     return  None ; 
2491+                 } 
2492+                 // We only want to warn about different versions of a dependency. 
2493+                 // Ignore items from our own crate. 
2494+                 if  item. krate  == LOCAL_CRATE  { 
2495+                     return  None ; 
2496+                 } 
2497+                 // We want to warn about different versions of a dependency. 
2498+                 // So make sure the crate names are the same. 
2499+                 if  impl_self_crate_name != self . tcx . crate_name ( item. krate )  { 
2500+                     return  None ; 
2501+                 } 
2502+                 // Filter out e.g. constructors that often have the same path 
2503+                 // str as the relevant ADT. 
2504+                 if  !self . tcx . def_kind ( item) . is_adt ( )  { 
2505+                     return  None ; 
2506+                 } 
2507+                 let  path = self . comparable_path ( item) ; 
2508+                 // We don't know if our item or the one we found is the re-exported one. 
2509+                 // Check both cases. 
2510+                 let  is_similar = path. ends_with ( & impl_self_path)  || impl_self_path. ends_with ( & path) ; 
2511+                 is_similar. then_some ( ( item,  path) ) 
2512+             } ) 
2513+             . collect ( ) ; 
2514+ 
2515+         let  mut  similar_items =
2516+             similar_items. into_items ( ) . into_sorted_stable_ord_by_key ( |( _,  path) | path) ; 
2517+         similar_items. dedup ( ) ; 
2518+ 
2519+         for  ( similar_item,  _)  in  similar_items { 
2520+             err. span_help ( self . tcx . def_span ( similar_item) ,  "item with same name found" ) ; 
2521+             self . note_two_crate_versions ( similar_item,  err) ; 
2522+         } 
2523+     } 
2524+ 
2525+     /// Add a `::` prefix when comparing paths so that paths with just one item 
2526+ /// like "Foo" does not equal the end of "OtherFoo". 
2527+ fn  comparable_path ( & self ,  did :  DefId )  -> String  { 
2528+         format ! ( "::{}" ,  self . tcx. def_path_str( did) ) 
2529+     } 
2530+ 
24582531    /// Creates a `PredicateObligation` with `new_self_ty` replacing the existing type in the 
24592532/// `trait_ref`. 
24602533/// 
0 commit comments