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