@@ -27,7 +27,7 @@ use rustc_ast::*;
2727use rustc_ast_pretty:: pprust:: { self , State } ;
2828use rustc_attr_parsing:: validate_attr;
2929use rustc_data_structures:: fx:: FxIndexMap ;
30- use rustc_errors:: { DiagCtxtHandle , LintBuffer } ;
30+ use rustc_errors:: { Diag , DiagCtxtHandle , LintBuffer , StashKey , Subdiagnostic as _ } ;
3131use rustc_feature:: Features ;
3232use rustc_session:: Session ;
3333use rustc_session:: lint:: BuiltinLintDiag ;
@@ -1559,14 +1559,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
15591559 }
15601560
15611561 validate_generic_param_order ( self . dcx ( ) , & generics. params , generics. span ) ;
1562-
1563- for predicate in & generics. where_clause . predicates {
1564- let span = predicate. span ;
1565- if let WherePredicateKind :: EqPredicate ( predicate) = & predicate. kind {
1566- deny_equality_constraints ( self , predicate, span, generics) ;
1567- }
1568- }
15691562 walk_list ! ( self , visit_generic_param, & generics. params) ;
1563+
15701564 for predicate in & generics. where_clause . predicates {
15711565 match & predicate. kind {
15721566 WherePredicateKind :: BoundPredicate ( bound_pred) => {
@@ -1590,7 +1584,24 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
15901584 }
15911585 }
15921586 }
1593- _ => { }
1587+ WherePredicateKind :: RegionPredicate ( _) => { }
1588+ WherePredicateKind :: EqPredicate ( eq_predicate) => {
1589+ // NOTE: We compute and attach the suggestion here instead of in the parser as
1590+ // it needs access to `generics.params`. While those could be passed to
1591+ // the where-clause parser, it would worsen its many callsites!
1592+ self . dcx ( ) . try_steal_modify_and_emit_err (
1593+ eq_predicate. lhs_ty . span ,
1594+ StashKey :: EqualityPredicate ,
1595+ |diag| {
1596+ suggest_replacing_eq_pred_with_assoc_ty_binding (
1597+ eq_predicate,
1598+ predicate. span ,
1599+ generics,
1600+ diag,
1601+ )
1602+ } ,
1603+ ) ;
1604+ }
15941605 }
15951606 self . visit_where_predicate ( predicate) ;
15961607 }
@@ -1880,24 +1891,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
18801891 }
18811892}
18821893
1883- /// When encountering an equality constraint in a `where` clause, emit an error. If the code seems
1884- /// like it's setting an associated type, provide an appropriate suggestion.
1885- fn deny_equality_constraints (
1886- this : & AstValidator < ' _ > ,
1894+ fn suggest_replacing_eq_pred_with_assoc_ty_binding (
18871895 predicate : & WhereEqPredicate ,
18881896 predicate_span : Span ,
18891897 generics : & Generics ,
1898+ diag : & mut Diag < ' _ > ,
18901899) {
1891- let mut err = errors:: EqualityInWhere { span : predicate_span, assoc : None , assoc2 : None } ;
1892-
18931900 // Given `<A as Foo>::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
18941901 if let TyKind :: Path ( Some ( qself) , full_path) = & predicate. lhs_ty . kind
18951902 && let TyKind :: Path ( None , path) = & qself. ty . kind
1896- && let [ PathSegment { ident, args : None , .. } ] = & path. segments [ ..]
1903+ && let [ PathSegment { ident, args : None , .. } ] = path. segments [ ..]
18971904 {
18981905 for param in & generics. params {
1899- if param. ident == * ident
1900- && let [ PathSegment { ident, args, .. } ] = & full_path. segments [ qself. position ..]
1906+ if param. ident == ident
1907+ && let [ PathSegment { ident, ref args, .. } ] = full_path. segments [ qself. position ..]
19011908 {
19021909 // Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
19031910 let mut assoc_path = full_path. clone ( ) ;
@@ -1908,7 +1915,7 @@ fn deny_equality_constraints(
19081915 // Build `<Bar = RhsTy>`.
19091916 let arg = AngleBracketedArg :: Constraint ( AssocItemConstraint {
19101917 id : rustc_ast:: node_id:: DUMMY_NODE_ID ,
1911- ident : * ident ,
1918+ ident,
19121919 gen_args,
19131920 kind : AssocItemConstraintKind :: Equality {
19141921 term : predicate. rhs_ty . clone ( ) . into ( ) ,
@@ -1931,12 +1938,13 @@ fn deny_equality_constraints(
19311938 ) ;
19321939 }
19331940 }
1934- err . assoc = Some ( errors:: AssociatedSuggestion {
1941+ errors:: UseAssocTypeBindingSyntaxSugg {
19351942 span : predicate_span,
1936- ident : * ident ,
1943+ ident,
19371944 param : param. ident ,
19381945 path : pprust:: path_to_string ( & assoc_path) ,
1939- } )
1946+ }
1947+ . add_to_diag ( diag) ;
19401948 }
19411949 }
19421950 }
@@ -1959,7 +1967,7 @@ fn deny_equality_constraints(
19591967 None => ( format ! ( "<{assoc} = {ty}>" ) , trait_segment. span ( ) . shrink_to_hi ( ) ) ,
19601968 } ;
19611969 let removal_span = if generics. where_clause . predicates . len ( ) == 1 {
1962- // We're removing th eonly where bound left, remove the whole thing.
1970+ // We're removing the only where bound left, remove the whole thing.
19631971 generics. where_clause . span
19641972 } else {
19651973 let mut span = predicate_span;
@@ -1982,13 +1990,14 @@ fn deny_equality_constraints(
19821990 }
19831991 span
19841992 } ;
1985- err . assoc2 = Some ( errors:: AssociatedSuggestion2 {
1993+ errors:: UseAssocTypeBindingSyntaxMultipartSugg {
19861994 span,
19871995 args,
19881996 predicate : removal_span,
19891997 trait_segment : trait_segment. ident ,
19901998 potential_assoc : potential_assoc. ident ,
1991- } ) ;
1999+ }
2000+ . add_to_diag ( diag) ;
19922001 }
19932002 } ;
19942003
@@ -2041,7 +2050,6 @@ fn deny_equality_constraints(
20412050 }
20422051 }
20432052 }
2044- this. dcx ( ) . emit_err ( err) ;
20452053}
20462054
20472055pub fn check_crate (
0 commit comments