@@ -1145,11 +1145,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1145
1145
} else {
1146
1146
// Otherwise, we have to walk through the supertraits to find
1147
1147
// 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
- } ) ;
1151
1148
self . one_bound_for_assoc_type (
1152
- candidates ,
1149
+ || traits :: supertraits ( tcx , trait_ref ) ,
1153
1150
& trait_ref. print_only_trait_path ( ) . to_string ( ) ,
1154
1151
binding. item_name ,
1155
1152
binding. span
@@ -1531,50 +1528,48 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1531
1528
1532
1529
debug ! ( "find_bound_for_assoc_item: predicates={:#?}" , predicates) ;
1533
1530
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
-
1541
1531
let param_hir_id = tcx. hir ( ) . as_local_hir_id ( ty_param_def_id) . unwrap ( ) ;
1542
1532
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
+ )
1547
1540
}
1548
1541
1549
- // Checks that `bounds` contains exactly one element and reports appropriate
1550
- // errors otherwise.
1551
1542
fn one_bound_for_assoc_type < I > ( & self ,
1552
- mut bounds : I ,
1543
+ all_candidates : impl Fn ( ) -> I ,
1553
1544
ty_param_name : & str ,
1554
1545
assoc_name : ast:: Ident ,
1555
1546
span : Span )
1556
1547
-> Result < ty:: PolyTraitRef < ' tcx > , ErrorReported >
1557
1548
where I : Iterator < Item = ty:: PolyTraitRef < ' tcx > >
1558
1549
{
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 ( ) {
1560
1555
Some ( bound) => bound,
1561
1556
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
+ ) ;
1568
1563
return Err ( ErrorReported ) ;
1569
1564
}
1570
1565
} ;
1571
1566
1572
1567
debug ! ( "one_bound_for_assoc_type: bound = {:?}" , bound) ;
1573
1568
1574
- if let Some ( bound2) = bounds . next ( ) {
1569
+ if let Some ( bound2) = matching_candidates . next ( ) {
1575
1570
debug ! ( "one_bound_for_assoc_type: bound2 = {:?}" , bound2) ;
1576
1571
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 ) ;
1578
1573
let mut err = struct_span_err ! (
1579
1574
self . tcx( ) . sess, span, E0221 ,
1580
1575
"ambiguous associated type `{}` in bounds of `{}`" ,
@@ -1606,6 +1601,50 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1606
1601
return Ok ( bound) ;
1607
1602
}
1608
1603
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
+
1609
1648
// Create a type from a path to an associated type.
1610
1649
// For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C`
1611
1650
// 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 {
1660
1699
}
1661
1700
} ;
1662
1701
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
+ ) ?
1667
1708
}
1668
1709
( & ty:: Param ( _) , Res :: SelfTy ( Some ( param_did) , None ) ) |
1669
1710
( & ty:: Param ( _) , Res :: Def ( DefKind :: TyParam , param_did) ) => {
0 commit comments