@@ -329,41 +329,52 @@ fn bounds_from_generic_predicates<'tcx>(
329
329
_ => { }
330
330
}
331
331
}
332
- let generics = if types. is_empty ( ) {
333
- "" . to_string ( )
334
- } else {
335
- format ! (
336
- "<{}>" ,
337
- types
338
- . keys( )
339
- . filter_map( |t| match t. kind( ) {
340
- ty:: Param ( _) => Some ( t. to_string( ) ) ,
341
- // Avoid suggesting the following:
342
- // fn foo<T, <T as Trait>::Bar>(_: T) where T: Trait, <T as Trait>::Bar: Other {}
343
- _ => None ,
344
- } )
345
- . collect:: <Vec <_>>( )
346
- . join( ", " )
347
- )
348
- } ;
332
+
349
333
let mut where_clauses = vec ! [ ] ;
334
+ let mut types_str = vec ! [ ] ;
350
335
for ( ty, bounds) in types {
351
- where_clauses
352
- . extend ( bounds. into_iter ( ) . map ( |bound| format ! ( "{}: {}" , ty, tcx. def_path_str( bound) ) ) ) ;
353
- }
354
- for projection in & projections {
355
- let p = projection. skip_binder ( ) ;
356
- // FIXME: this is not currently supported syntax, we should be looking at the `types` and
357
- // insert the associated types where they correspond, but for now let's be "lazy" and
358
- // propose this instead of the following valid resugaring:
359
- // `T: Trait, Trait::Assoc = K` → `T: Trait<Assoc = K>`
360
- where_clauses. push ( format ! ( "{} = {}" , tcx. def_path_str( p. projection_ty. def_id) , p. term) ) ;
336
+ if let ty:: Param ( _) = ty. kind ( ) {
337
+ let mut bounds_str = vec ! [ ] ;
338
+ for bound in bounds {
339
+ let mut projections_str = vec ! [ ] ;
340
+ for projection in & projections {
341
+ let p = projection. skip_binder ( ) ;
342
+ let alias_ty = p. projection_ty ;
343
+ if bound == tcx. parent ( alias_ty. def_id ) && alias_ty. self_ty ( ) == ty {
344
+ let name = tcx. item_name ( alias_ty. def_id ) ;
345
+ projections_str. push ( format ! ( "{} = {}" , name, p. term) ) ;
346
+ }
347
+ }
348
+ let bound_def_path = tcx. def_path_str ( bound) ;
349
+ if projections_str. is_empty ( ) {
350
+ where_clauses. push ( format ! ( "{}: {}" , ty, bound_def_path) ) ;
351
+ } else {
352
+ bounds_str. push ( format ! ( "{}<{}>" , bound_def_path, projections_str. join( ", " ) ) ) ;
353
+ }
354
+ }
355
+ if bounds_str. is_empty ( ) {
356
+ types_str. push ( ty. to_string ( ) ) ;
357
+ } else {
358
+ types_str. push ( format ! ( "{}: {}" , ty, bounds_str. join( " + " ) ) ) ;
359
+ }
360
+ } else {
361
+ // Avoid suggesting the following:
362
+ // fn foo<T, <T as Trait>::Bar>(_: T) where T: Trait, <T as Trait>::Bar: Other {}
363
+ where_clauses. extend (
364
+ bounds. into_iter ( ) . map ( |bound| format ! ( "{}: {}" , ty, tcx. def_path_str( bound) ) ) ,
365
+ ) ;
366
+ }
361
367
}
368
+
369
+ let generics =
370
+ if types_str. is_empty ( ) { "" . to_string ( ) } else { format ! ( "<{}>" , types_str. join( ", " ) ) } ;
371
+
362
372
let where_clauses = if where_clauses. is_empty ( ) {
363
- String :: new ( )
373
+ "" . to_string ( )
364
374
} else {
365
375
format ! ( " where {}" , where_clauses. join( ", " ) )
366
376
} ;
377
+
367
378
( generics, where_clauses)
368
379
}
369
380
0 commit comments