@@ -32,7 +32,6 @@ use rustc_infer::infer::{InferOk, TypeTrace};
32
32
use rustc_middle:: traits:: select:: OverflowError ;
33
33
use rustc_middle:: ty:: abstract_const:: NotConstEvaluatable ;
34
34
use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
35
- use rustc_middle:: ty:: fast_reject:: TreatProjections ;
36
35
use rustc_middle:: ty:: fold:: { TypeFolder , TypeSuperFoldable } ;
37
36
use rustc_middle:: ty:: print:: { with_forced_trimmed_paths, FmtPrinter , Print } ;
38
37
use rustc_middle:: ty:: {
@@ -1836,57 +1835,61 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
1836
1835
} ) ;
1837
1836
let mut diag = struct_span_err ! ( self . tcx. sess, obligation. cause. span, E0271 , "{msg}" ) ;
1838
1837
1839
- let secondary_span = match predicate. kind ( ) . skip_binder ( ) {
1840
- ty:: PredicateKind :: Clause ( ty:: Clause :: Projection ( proj) ) => self
1841
- . tcx
1842
- . opt_associated_item ( proj. projection_ty . def_id )
1843
- . and_then ( |trait_assoc_item| {
1844
- self . tcx
1845
- . trait_of_item ( proj. projection_ty . def_id )
1846
- . map ( |id| ( trait_assoc_item, id) )
1847
- } )
1848
- . and_then ( |( trait_assoc_item, id) | {
1849
- let trait_assoc_ident = trait_assoc_item. ident ( self . tcx ) ;
1850
- self . tcx . find_map_relevant_impl (
1851
- id,
1852
- proj. projection_ty . self_ty ( ) ,
1853
- TreatProjections :: ForLookup ,
1854
- |did| {
1855
- self . tcx
1856
- . associated_items ( did)
1857
- . in_definition_order ( )
1858
- . find ( |assoc| assoc. ident ( self . tcx ) == trait_assoc_ident)
1859
- } ,
1860
- )
1861
- } )
1862
- . and_then ( |item| match self . tcx . hir ( ) . get_if_local ( item. def_id ) {
1863
- Some (
1864
- hir:: Node :: TraitItem ( hir:: TraitItem {
1865
- kind : hir:: TraitItemKind :: Type ( _, Some ( ty) ) ,
1866
- ..
1867
- } )
1868
- | hir:: Node :: ImplItem ( hir:: ImplItem {
1869
- kind : hir:: ImplItemKind :: Type ( ty) ,
1870
- ..
1871
- } ) ,
1872
- ) => Some ( (
1873
- ty. span ,
1874
- with_forced_trimmed_paths ! ( format!(
1875
- "type mismatch resolving `{}`" ,
1876
- self . resolve_vars_if_possible( predicate)
1877
- . print( FmtPrinter :: new_with_limit(
1878
- self . tcx,
1879
- Namespace :: TypeNS ,
1880
- rustc_session:: Limit ( 5 ) ,
1881
- ) )
1882
- . unwrap( )
1883
- . into_buffer( )
1884
- ) ) ,
1838
+ let secondary_span = ( || {
1839
+ let ty:: PredicateKind :: Clause ( ty:: Clause :: Projection ( proj) ) =
1840
+ predicate. kind ( ) . skip_binder ( )
1841
+ else {
1842
+ return None ;
1843
+ } ;
1844
+
1845
+ let trait_assoc_item = self . tcx . opt_associated_item ( proj. projection_ty . def_id ) ?;
1846
+ let trait_assoc_ident = trait_assoc_item. ident ( self . tcx ) ;
1847
+
1848
+ let mut associated_items = vec ! [ ] ;
1849
+ self . tcx . for_each_relevant_impl (
1850
+ self . tcx . trait_of_item ( proj. projection_ty . def_id ) ?,
1851
+ proj. projection_ty . self_ty ( ) ,
1852
+ |impl_def_id| {
1853
+ associated_items. extend (
1854
+ self . tcx
1855
+ . associated_items ( impl_def_id)
1856
+ . in_definition_order ( )
1857
+ . find ( |assoc| assoc. ident ( self . tcx ) == trait_assoc_ident) ,
1858
+ ) ;
1859
+ } ,
1860
+ ) ;
1861
+
1862
+ let [ associated_item] : & [ ty:: AssocItem ] = & associated_items[ ..] else {
1863
+ return None ;
1864
+ } ;
1865
+ match self . tcx . hir ( ) . get_if_local ( associated_item. def_id ) {
1866
+ Some (
1867
+ hir:: Node :: TraitItem ( hir:: TraitItem {
1868
+ kind : hir:: TraitItemKind :: Type ( _, Some ( ty) ) ,
1869
+ ..
1870
+ } )
1871
+ | hir:: Node :: ImplItem ( hir:: ImplItem {
1872
+ kind : hir:: ImplItemKind :: Type ( ty) ,
1873
+ ..
1874
+ } ) ,
1875
+ ) => Some ( (
1876
+ ty. span ,
1877
+ with_forced_trimmed_paths ! ( format!(
1878
+ "type mismatch resolving `{}`" ,
1879
+ self . resolve_vars_if_possible( predicate)
1880
+ . print( FmtPrinter :: new_with_limit(
1881
+ self . tcx,
1882
+ Namespace :: TypeNS ,
1883
+ rustc_session:: Limit ( 5 ) ,
1884
+ ) )
1885
+ . unwrap( )
1886
+ . into_buffer( )
1885
1887
) ) ,
1886
- _ => None ,
1887
- } ) ,
1888
- _ => None ,
1889
- } ;
1888
+ ) ) ,
1889
+ _ => None ,
1890
+ }
1891
+ } ) ( ) ;
1892
+
1890
1893
self . note_type_err (
1891
1894
& mut diag,
1892
1895
& obligation. cause ,
@@ -2228,14 +2231,18 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
2228
2231
err : & mut Diagnostic ,
2229
2232
trait_ref : & ty:: PolyTraitRef < ' tcx > ,
2230
2233
) -> bool {
2231
- let get_trait_impl = |trait_def_id| {
2232
- self . tcx . find_map_relevant_impl (
2234
+ let get_trait_impls = |trait_def_id| {
2235
+ let mut trait_impls = vec ! [ ] ;
2236
+ self . tcx . for_each_relevant_impl (
2233
2237
trait_def_id,
2234
2238
trait_ref. skip_binder ( ) . self_ty ( ) ,
2235
- TreatProjections :: ForLookup ,
2236
- Some ,
2237
- )
2239
+ |impl_def_id| {
2240
+ trait_impls. push ( impl_def_id) ;
2241
+ } ,
2242
+ ) ;
2243
+ trait_impls
2238
2244
} ;
2245
+
2239
2246
let required_trait_path = self . tcx . def_path_str ( trait_ref. def_id ( ) ) ;
2240
2247
let traits_with_same_path: std:: collections:: BTreeSet < _ > = self
2241
2248
. tcx
@@ -2245,17 +2252,23 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
2245
2252
. collect ( ) ;
2246
2253
let mut suggested = false ;
2247
2254
for trait_with_same_path in traits_with_same_path {
2248
- if let Some ( impl_def_id) = get_trait_impl ( trait_with_same_path) {
2249
- let impl_span = self . tcx . def_span ( impl_def_id) ;
2250
- err. span_help ( impl_span, "trait impl with same name found" ) ;
2251
- let trait_crate = self . tcx . crate_name ( trait_with_same_path. krate ) ;
2252
- let crate_msg = format ! (
2253
- "perhaps two different versions of crate `{}` are being used?" ,
2254
- trait_crate
2255
- ) ;
2256
- err. note ( & crate_msg) ;
2257
- suggested = true ;
2255
+ let trait_impls = get_trait_impls ( trait_with_same_path) ;
2256
+ if trait_impls. is_empty ( ) {
2257
+ continue ;
2258
2258
}
2259
+ let impl_spans: Vec < _ > =
2260
+ trait_impls. iter ( ) . map ( |impl_def_id| self . tcx . def_span ( * impl_def_id) ) . collect ( ) ;
2261
+ err. span_help (
2262
+ impl_spans,
2263
+ format ! ( "trait impl{} with same name found" , pluralize!( trait_impls. len( ) ) ) ,
2264
+ ) ;
2265
+ let trait_crate = self . tcx . crate_name ( trait_with_same_path. krate ) ;
2266
+ let crate_msg = format ! (
2267
+ "perhaps two different versions of crate `{}` are being used?" ,
2268
+ trait_crate
2269
+ ) ;
2270
+ err. note ( & crate_msg) ;
2271
+ suggested = true ;
2259
2272
}
2260
2273
suggested
2261
2274
}
0 commit comments