@@ -1593,44 +1593,98 @@ fn deny_equality_constraints(
1593
1593
}
1594
1594
}
1595
1595
}
1596
- // Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
1597
- if let TyKind :: Path ( None , full_path) = & predicate. lhs_ty . kind {
1598
- if let [ potential_param, potential_assoc] = & full_path. segments [ ..] {
1599
- for param in & generics. params {
1600
- if param. ident == potential_param. ident {
1601
- for bound in & param. bounds {
1602
- if let ast:: GenericBound :: Trait ( trait_ref, TraitBoundModifiers :: NONE ) =
1603
- bound
1596
+
1597
+ let mut suggest =
1598
+ |poly : & PolyTraitRef , potential_assoc : & PathSegment , predicate : & WhereEqPredicate | {
1599
+ if let [ trait_segment] = & poly. trait_ref . path . segments [ ..] {
1600
+ let assoc = pprust:: path_to_string ( & ast:: Path :: from_ident ( potential_assoc. ident ) ) ;
1601
+ let ty = pprust:: ty_to_string ( & predicate. rhs_ty ) ;
1602
+ let ( args, span) = match & trait_segment. args {
1603
+ Some ( args) => match args. deref ( ) {
1604
+ ast:: GenericArgs :: AngleBracketed ( args) => {
1605
+ let Some ( arg) = args. args . last ( ) else {
1606
+ return ;
1607
+ } ;
1608
+ ( format ! ( ", {assoc} = {ty}" ) , arg. span ( ) . shrink_to_hi ( ) )
1609
+ }
1610
+ _ => return ,
1611
+ } ,
1612
+ None => ( format ! ( "<{assoc} = {ty}>" ) , trait_segment. span ( ) . shrink_to_hi ( ) ) ,
1613
+ } ;
1614
+ let removal_span = if generics. where_clause . predicates . len ( ) == 1 {
1615
+ // We're removing th eonly where bound left, remove the whole thing.
1616
+ generics. where_clause . span
1617
+ } else {
1618
+ let mut span = predicate. span ;
1619
+ let mut prev: Option < Span > = None ;
1620
+ let mut preds = generics. where_clause . predicates . iter ( ) . peekable ( ) ;
1621
+ // Find the predicate that shouldn't have been in the where bound list.
1622
+ while let Some ( pred) = preds. next ( ) {
1623
+ if let WherePredicate :: EqPredicate ( pred) = pred
1624
+ && pred. span == predicate. span
1604
1625
{
1605
- if let [ trait_segment] = & trait_ref. trait_ref . path . segments [ ..] {
1606
- let assoc = pprust:: path_to_string ( & ast:: Path :: from_ident (
1607
- potential_assoc. ident ,
1608
- ) ) ;
1609
- let ty = pprust:: ty_to_string ( & predicate. rhs_ty ) ;
1610
- let ( args, span) = match & trait_segment. args {
1611
- Some ( args) => match args. deref ( ) {
1612
- ast:: GenericArgs :: AngleBracketed ( args) => {
1613
- let Some ( arg) = args. args . last ( ) else {
1614
- continue ;
1615
- } ;
1616
- ( format ! ( ", {assoc} = {ty}" ) , arg. span ( ) . shrink_to_hi ( ) )
1617
- }
1618
- _ => continue ,
1619
- } ,
1620
- None => (
1621
- format ! ( "<{assoc} = {ty}>" ) ,
1622
- trait_segment. span ( ) . shrink_to_hi ( ) ,
1623
- ) ,
1624
- } ;
1625
- err. assoc2 = Some ( errors:: AssociatedSuggestion2 {
1626
- span,
1627
- args,
1628
- predicate : predicate. span ,
1629
- trait_segment : trait_segment. ident ,
1630
- potential_assoc : potential_assoc. ident ,
1631
- } ) ;
1626
+ if let Some ( next) = preds. peek ( ) {
1627
+ // This is the first predicate, remove the trailing comma as well.
1628
+ span = span. with_hi ( next. span ( ) . lo ( ) ) ;
1629
+ } else if let Some ( prev) = prev {
1630
+ // Remove the previous comma as well.
1631
+ span = span. with_lo ( prev. hi ( ) ) ;
1632
1632
}
1633
1633
}
1634
+ prev = Some ( pred. span ( ) ) ;
1635
+ }
1636
+ span
1637
+ } ;
1638
+ err. assoc2 = Some ( errors:: AssociatedSuggestion2 {
1639
+ span,
1640
+ args,
1641
+ predicate : removal_span,
1642
+ trait_segment : trait_segment. ident ,
1643
+ potential_assoc : potential_assoc. ident ,
1644
+ } ) ;
1645
+ }
1646
+ } ;
1647
+
1648
+ if let TyKind :: Path ( None , full_path) = & predicate. lhs_ty . kind {
1649
+ // Given `A: Foo, Foo::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
1650
+ for bounds in generics. params . iter ( ) . map ( |p| & p. bounds ) . chain (
1651
+ generics. where_clause . predicates . iter ( ) . filter_map ( |pred| match pred {
1652
+ WherePredicate :: BoundPredicate ( p) => Some ( & p. bounds ) ,
1653
+ _ => None ,
1654
+ } ) ,
1655
+ ) {
1656
+ for bound in bounds {
1657
+ if let GenericBound :: Trait ( poly, TraitBoundModifiers :: NONE ) = bound {
1658
+ if full_path. segments [ ..full_path. segments . len ( ) - 1 ]
1659
+ . iter ( )
1660
+ . map ( |segment| segment. ident . name )
1661
+ . zip ( poly. trait_ref . path . segments . iter ( ) . map ( |segment| segment. ident . name ) )
1662
+ . all ( |( a, b) | a == b)
1663
+ && let Some ( potential_assoc) = full_path. segments . iter ( ) . last ( )
1664
+ {
1665
+ suggest ( poly, potential_assoc, predicate) ;
1666
+ }
1667
+ }
1668
+ }
1669
+ }
1670
+ // Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
1671
+ if let [ potential_param, potential_assoc] = & full_path. segments [ ..] {
1672
+ for ( ident, bounds) in generics. params . iter ( ) . map ( |p| ( p. ident , & p. bounds ) ) . chain (
1673
+ generics. where_clause . predicates . iter ( ) . filter_map ( |pred| match pred {
1674
+ WherePredicate :: BoundPredicate ( p)
1675
+ if let ast:: TyKind :: Path ( None , path) = & p. bounded_ty . kind
1676
+ && let [ segment] = & path. segments [ ..] =>
1677
+ {
1678
+ Some ( ( segment. ident , & p. bounds ) )
1679
+ }
1680
+ _ => None ,
1681
+ } ) ,
1682
+ ) {
1683
+ if ident == potential_param. ident {
1684
+ for bound in bounds {
1685
+ if let ast:: GenericBound :: Trait ( poly, TraitBoundModifiers :: NONE ) = bound {
1686
+ suggest ( poly, potential_assoc, predicate) ;
1687
+ }
1634
1688
}
1635
1689
}
1636
1690
}
0 commit comments