@@ -1145,11 +1145,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
11451145 } else {
11461146 // Otherwise, we have to walk through the supertraits to find
11471147 // those that do.
1148- let candidates = traits:: supertraits ( tcx, trait_ref) . filter ( |r| {
1149- self . trait_defines_associated_type_named ( r. def_id ( ) , binding. item_name )
1150- } ) ;
11511148 self . one_bound_for_assoc_type (
1152- candidates ,
1149+ || traits :: supertraits ( tcx , trait_ref ) ,
11531150 & trait_ref. print_only_trait_path ( ) . to_string ( ) ,
11541151 binding. item_name ,
11551152 binding. span
@@ -1531,50 +1528,48 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
15311528
15321529 debug ! ( "find_bound_for_assoc_item: predicates={:#?}" , predicates) ;
15331530
1534- let bounds = predicates. iter ( ) . filter_map ( |( p, _) | p. to_opt_poly_trait_ref ( ) ) ;
1535-
1536- // Check that there is exactly one way to find an associated type with the
1537- // correct name.
1538- let suitable_bounds = traits:: transitive_bounds ( tcx, bounds)
1539- . filter ( |b| self . trait_defines_associated_type_named ( b. def_id ( ) , assoc_name) ) ;
1540-
15411531 let param_hir_id = tcx. hir ( ) . as_local_hir_id ( ty_param_def_id) . unwrap ( ) ;
15421532 let param_name = tcx. hir ( ) . ty_param_name ( param_hir_id) ;
1543- self . one_bound_for_assoc_type ( suitable_bounds,
1544- & param_name. as_str ( ) ,
1545- assoc_name,
1546- span)
1533+ self . one_bound_for_assoc_type (
1534+ || traits:: transitive_bounds ( tcx, predicates
1535+ . iter ( ) . filter_map ( |( p, _) | p. to_opt_poly_trait_ref ( ) ) ) ,
1536+ & param_name. as_str ( ) ,
1537+ assoc_name,
1538+ span,
1539+ )
15471540 }
15481541
1549- // Checks that `bounds` contains exactly one element and reports appropriate
1550- // errors otherwise.
15511542 fn one_bound_for_assoc_type < I > ( & self ,
1552- mut bounds : I ,
1543+ all_candidates : impl Fn ( ) -> I ,
15531544 ty_param_name : & str ,
15541545 assoc_name : ast:: Ident ,
15551546 span : Span )
15561547 -> Result < ty:: PolyTraitRef < ' tcx > , ErrorReported >
15571548 where I : Iterator < Item = ty:: PolyTraitRef < ' tcx > >
15581549 {
1559- let bound = match bounds. next ( ) {
1550+ let mut matching_candidates = all_candidates ( ) . filter ( |r| {
1551+ self . trait_defines_associated_type_named ( r. def_id ( ) , assoc_name)
1552+ } ) ;
1553+
1554+ let bound = match matching_candidates. next ( ) {
15601555 Some ( bound) => bound,
15611556 None => {
1562- struct_span_err ! ( self . tcx ( ) . sess , span , E0220 ,
1563- "associated type `{}` not found for `{}`" ,
1564- assoc_name ,
1565- ty_param_name )
1566- . span_label ( span, format ! ( "associated type `{}` not found" , assoc_name ) )
1567- . emit ( ) ;
1557+ self . complain_about_assoc_type_not_found (
1558+ all_candidates ,
1559+ ty_param_name ,
1560+ assoc_name ,
1561+ span
1562+ ) ;
15681563 return Err ( ErrorReported ) ;
15691564 }
15701565 } ;
15711566
15721567 debug ! ( "one_bound_for_assoc_type: bound = {:?}" , bound) ;
15731568
1574- if let Some ( bound2) = bounds . next ( ) {
1569+ if let Some ( bound2) = matching_candidates . next ( ) {
15751570 debug ! ( "one_bound_for_assoc_type: bound2 = {:?}" , bound2) ;
15761571
1577- let bounds = iter:: once ( bound) . chain ( iter:: once ( bound2) ) . chain ( bounds ) ;
1572+ let bounds = iter:: once ( bound) . chain ( iter:: once ( bound2) ) . chain ( matching_candidates ) ;
15781573 let mut err = struct_span_err ! (
15791574 self . tcx( ) . sess, span, E0221 ,
15801575 "ambiguous associated type `{}` in bounds of `{}`" ,
@@ -1606,6 +1601,50 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
16061601 return Ok ( bound) ;
16071602 }
16081603
1604+ fn complain_about_assoc_type_not_found < I > ( & self ,
1605+ all_candidates : impl Fn ( ) -> I ,
1606+ ty_param_name : & str ,
1607+ assoc_name : ast:: Ident ,
1608+ span : Span )
1609+ where I : Iterator < Item = ty:: PolyTraitRef < ' tcx > > {
1610+ let mut err = struct_span_err ! ( self . tcx( ) . sess, span, E0220 ,
1611+ "associated type `{}` not found for `{}`" ,
1612+ assoc_name,
1613+ ty_param_name) ;
1614+
1615+ let all_candidate_names: Vec < _ > = all_candidates ( )
1616+ . map ( |r| self . tcx ( ) . associated_items ( r. def_id ( ) ) )
1617+ . flatten ( )
1618+ . filter_map ( |item|
1619+ if item. kind == ty:: AssocKind :: Type {
1620+ Some ( item. ident . name )
1621+ } else {
1622+ None
1623+ }
1624+ )
1625+ . collect ( ) ;
1626+
1627+ if let Some ( suggested_name) = find_best_match_for_name (
1628+ all_candidate_names. iter ( ) ,
1629+ & assoc_name. as_str ( ) ,
1630+ None ,
1631+ ) {
1632+ err. span_suggestion (
1633+ span,
1634+ "there is an associated type with a similar name" ,
1635+ suggested_name. to_string ( ) ,
1636+ Applicability :: MaybeIncorrect ,
1637+ ) ;
1638+ } else {
1639+ err. span_label (
1640+ span,
1641+ format ! ( "associated type `{}` not found" , assoc_name)
1642+ ) ;
1643+ }
1644+
1645+ err. emit ( ) ;
1646+ }
1647+
16091648 // Create a type from a path to an associated type.
16101649 // For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C`
16111650 // and item_segment is the path segment for `D`. We return a type and a def for
@@ -1660,10 +1699,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
16601699 }
16611700 } ;
16621701
1663- let candidates = traits:: supertraits ( tcx, ty:: Binder :: bind ( trait_ref) )
1664- . filter ( |r| self . trait_defines_associated_type_named ( r. def_id ( ) , assoc_ident) ) ;
1665-
1666- self . one_bound_for_assoc_type ( candidates, "Self" , assoc_ident, span) ?
1702+ self . one_bound_for_assoc_type (
1703+ || traits:: supertraits ( tcx, ty:: Binder :: bind ( trait_ref) ) ,
1704+ "Self" ,
1705+ assoc_ident,
1706+ span
1707+ ) ?
16671708 }
16681709 ( & ty:: Param ( _) , Res :: SelfTy ( Some ( param_did) , None ) ) |
16691710 ( & ty:: Param ( _) , Res :: Def ( DefKind :: TyParam , param_did) ) => {
0 commit comments