@@ -1217,7 +1217,6 @@ pub fn prohibit_assoc_item_constraint(
1217
1217
// otherwise suggest the removal of the binding.
1218
1218
if let Some ( ( def_id, segment, _) ) = segment
1219
1219
&& segment. args ( ) . parenthesized == hir:: GenericArgsParentheses :: No
1220
- && let hir:: AssocItemConstraintKind :: Equality { term } = constraint. kind
1221
1220
{
1222
1221
// Suggests removal of the offending binding
1223
1222
let suggest_removal = |e : & mut Diag < ' _ > | {
@@ -1263,7 +1262,7 @@ pub fn prohibit_assoc_item_constraint(
1263
1262
if let Ok ( suggestion) = tcx. sess . source_map ( ) . span_to_snippet ( removal_span) {
1264
1263
e. span_suggestion_verbose (
1265
1264
removal_span,
1266
- "consider removing this associated item binding" ,
1265
+ format ! ( "consider removing this associated item {}" , constraint . kind . descr ( ) ) ,
1267
1266
suggestion,
1268
1267
Applicability :: MaybeIncorrect ,
1269
1268
) ;
@@ -1286,19 +1285,73 @@ pub fn prohibit_assoc_item_constraint(
1286
1285
// Check if the type has a generic param with the same name
1287
1286
// as the assoc type name in the associated item binding.
1288
1287
let generics = tcx. generics_of ( def_id) ;
1289
- let matching_param =
1290
- generics. own_params . iter ( ) . find ( |p| p. name . as_str ( ) == constraint. ident . as_str ( ) ) ;
1288
+ let matching_param = generics. own_params . iter ( ) . find ( |p| p. name == constraint. ident . name ) ;
1291
1289
1292
1290
// Now emit the appropriate suggestion
1293
1291
if let Some ( matching_param) = matching_param {
1294
- match ( & matching_param. kind , term) {
1295
- ( GenericParamDefKind :: Type { .. } , hir:: Term :: Ty ( ty) ) => {
1296
- suggest_direct_use ( & mut err, ty. span ) ;
1297
- }
1298
- ( GenericParamDefKind :: Const { .. } , hir:: Term :: Const ( c) ) => {
1292
+ match ( constraint. kind , & matching_param. kind ) {
1293
+ (
1294
+ hir:: AssocItemConstraintKind :: Equality { term : hir:: Term :: Ty ( ty) } ,
1295
+ GenericParamDefKind :: Type { .. } ,
1296
+ ) => suggest_direct_use ( & mut err, ty. span ) ,
1297
+ (
1298
+ hir:: AssocItemConstraintKind :: Equality { term : hir:: Term :: Const ( c) } ,
1299
+ GenericParamDefKind :: Const { .. } ,
1300
+ ) => {
1299
1301
let span = tcx. hir ( ) . span ( c. hir_id ) ;
1300
1302
suggest_direct_use ( & mut err, span) ;
1301
1303
}
1304
+ ( hir:: AssocItemConstraintKind :: Bound { bounds } , _) => {
1305
+ // Suggest `impl<T: Bound> Trait<T> for Foo` when finding
1306
+ // `impl Trait<T: Bound> for Foo`
1307
+
1308
+ // Get the parent impl block based on the binding we have
1309
+ // and the trait DefId
1310
+ let impl_block = tcx
1311
+ . hir ( )
1312
+ . parent_iter ( constraint. hir_id )
1313
+ . find_map ( |( _, node) | node. impl_block_of_trait ( def_id) ) ;
1314
+
1315
+ let type_with_constraints =
1316
+ tcx. sess . source_map ( ) . span_to_snippet ( constraint. span ) ;
1317
+
1318
+ if let Some ( impl_block) = impl_block
1319
+ && let Ok ( type_with_constraints) = type_with_constraints
1320
+ {
1321
+ // Filter out the lifetime parameters because
1322
+ // they should be declared before the type parameter
1323
+ let lifetimes: String = bounds
1324
+ . iter ( )
1325
+ . filter_map ( |bound| {
1326
+ if let hir:: GenericBound :: Outlives ( lifetime) = bound {
1327
+ Some ( format ! ( "{lifetime}, " ) )
1328
+ } else {
1329
+ None
1330
+ }
1331
+ } )
1332
+ . collect ( ) ;
1333
+ // Figure out a span and suggestion string based on
1334
+ // whether there are any existing parameters
1335
+ let param_decl = if let Some ( param_span) =
1336
+ impl_block. generics . span_for_param_suggestion ( )
1337
+ {
1338
+ ( param_span, format ! ( ", {lifetimes}{type_with_constraints}" ) )
1339
+ } else {
1340
+ (
1341
+ impl_block. generics . span . shrink_to_lo ( ) ,
1342
+ format ! ( "<{lifetimes}{type_with_constraints}>" ) ,
1343
+ )
1344
+ } ;
1345
+ let suggestions =
1346
+ vec ! [ param_decl, ( constraint. span, format!( "{}" , matching_param. name) ) ] ;
1347
+
1348
+ err. multipart_suggestion_verbose (
1349
+ format ! ( "declare the type parameter right after the `impl` keyword" ) ,
1350
+ suggestions,
1351
+ Applicability :: MaybeIncorrect ,
1352
+ ) ;
1353
+ }
1354
+ }
1302
1355
_ => suggest_removal ( & mut err) ,
1303
1356
}
1304
1357
} else {
0 commit comments