@@ -23,6 +23,7 @@ use rustc_session::Session;
23
23
use rustc_span:: symbol:: { kw, sym} ;
24
24
use rustc_span:: Span ;
25
25
use std:: mem;
26
+ use std:: ops:: DerefMut ;
26
27
27
28
const MORE_EXTERN : & str =
28
29
"for more information, visit https://doc.rust-lang.org/std/keyword.extern.html" ;
@@ -1113,17 +1114,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1113
1114
1114
1115
for predicate in & generics. where_clause . predicates {
1115
1116
if let WherePredicate :: EqPredicate ( ref predicate) = * predicate {
1116
- self . err_handler ( )
1117
- . struct_span_err (
1118
- predicate. span ,
1119
- "equality constraints are not yet supported in `where` clauses" ,
1120
- )
1121
- . span_label ( predicate. span , "not supported" )
1122
- . note (
1123
- "see issue #20041 <https://github.com/rust-lang/rust/issues/20041> \
1124
- for more information",
1125
- )
1126
- . emit ( ) ;
1117
+ deny_equality_constraints ( self , predicate, generics) ;
1127
1118
}
1128
1119
}
1129
1120
@@ -1300,6 +1291,87 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1300
1291
}
1301
1292
}
1302
1293
1294
+ fn deny_equality_constraints (
1295
+ this : & mut AstValidator < ' _ > ,
1296
+ predicate : & WhereEqPredicate ,
1297
+ generics : & Generics ,
1298
+ ) {
1299
+ let mut err = this. err_handler ( ) . struct_span_err (
1300
+ predicate. span ,
1301
+ "equality constraints are not yet supported in `where` clauses" ,
1302
+ ) ;
1303
+ err. span_label ( predicate. span , "not supported" ) ;
1304
+
1305
+ // Given `<A as Foo>::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
1306
+ if let TyKind :: Path ( Some ( qself) , full_path) = & predicate. lhs_ty . kind {
1307
+ if let TyKind :: Path ( None , path) = & qself. ty . kind {
1308
+ match & path. segments [ ..] {
1309
+ [ PathSegment { ident, args : None , .. } ] => {
1310
+ for param in & generics. params {
1311
+ if param. ident == * ident {
1312
+ let param = ident;
1313
+ match & full_path. segments [ qself. position ..] {
1314
+ [ PathSegment { ident, .. } ] => {
1315
+ // Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
1316
+ let mut assoc_path = full_path. clone ( ) ;
1317
+ // Remove `Bar` from `Foo::Bar`.
1318
+ assoc_path. segments . pop ( ) ;
1319
+ let len = assoc_path. segments . len ( ) - 1 ;
1320
+ // Build `<Bar = RhsTy>`.
1321
+ let arg = AngleBracketedArg :: Constraint ( AssocTyConstraint {
1322
+ id : rustc_ast:: node_id:: DUMMY_NODE_ID ,
1323
+ ident : * ident,
1324
+ kind : AssocTyConstraintKind :: Equality {
1325
+ ty : predicate. rhs_ty . clone ( ) ,
1326
+ } ,
1327
+ span : ident. span ,
1328
+ } ) ;
1329
+ // Add `<Bar = RhsTy>` to `Foo`.
1330
+ match & mut assoc_path. segments [ len] . args {
1331
+ Some ( args) => match args. deref_mut ( ) {
1332
+ GenericArgs :: Parenthesized ( _) => continue ,
1333
+ GenericArgs :: AngleBracketed ( args) => {
1334
+ args. args . push ( arg) ;
1335
+ }
1336
+ } ,
1337
+ empty_args => {
1338
+ * empty_args = AngleBracketedArgs {
1339
+ span : ident. span ,
1340
+ args : vec ! [ arg] ,
1341
+ }
1342
+ . into ( ) ;
1343
+ }
1344
+ }
1345
+ err. span_suggestion_verbose (
1346
+ predicate. span ,
1347
+ & format ! (
1348
+ "if `{}` is an associated type you're trying to set, \
1349
+ use the associated type binding syntax",
1350
+ ident
1351
+ ) ,
1352
+ format ! (
1353
+ "{}: {}" ,
1354
+ param,
1355
+ pprust:: path_to_string( & assoc_path)
1356
+ ) ,
1357
+ Applicability :: MaybeIncorrect ,
1358
+ ) ;
1359
+ }
1360
+ _ => { }
1361
+ } ;
1362
+ }
1363
+ }
1364
+ }
1365
+ _ => { }
1366
+ }
1367
+ }
1368
+ }
1369
+ err. note (
1370
+ "see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information" ,
1371
+ ) ;
1372
+ err. emit ( ) ;
1373
+ }
1374
+
1303
1375
pub fn check_crate ( session : & Session , krate : & Crate , lints : & mut LintBuffer ) -> bool {
1304
1376
let mut validator = AstValidator {
1305
1377
session,
0 commit comments