@@ -85,7 +85,9 @@ use rustc_infer::traits::ObligationCause;
85
85
use rustc_middle:: query:: Providers ;
86
86
use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
87
87
use rustc_middle:: ty:: print:: with_types_for_signature;
88
- use rustc_middle:: ty:: { self , GenericArgs , GenericArgsRef , Ty , TyCtxt , TypingMode } ;
88
+ use rustc_middle:: ty:: {
89
+ self , GenericArgs , GenericArgsRef , GenericParamDefKind , Ty , TyCtxt , TypingMode ,
90
+ } ;
89
91
use rustc_middle:: { bug, span_bug} ;
90
92
use rustc_session:: parse:: feature_err;
91
93
use rustc_span:: def_id:: CRATE_DEF_ID ;
@@ -232,8 +234,7 @@ fn missing_items_err(
232
234
} ;
233
235
234
236
// Obtain the level of indentation ending in `sugg_sp`.
235
- let padding =
236
- tcx. sess . source_map ( ) . indentation_before ( sugg_sp) . unwrap_or_else ( || String :: new ( ) ) ;
237
+ let padding = tcx. sess . source_map ( ) . indentation_before ( sugg_sp) . unwrap_or_else ( String :: new) ;
237
238
let ( mut missing_trait_item, mut missing_trait_item_none, mut missing_trait_item_label) =
238
239
( Vec :: new ( ) , Vec :: new ( ) , Vec :: new ( ) ) ;
239
240
@@ -330,6 +331,7 @@ fn default_body_is_unstable(
330
331
fn bounds_from_generic_predicates < ' tcx > (
331
332
tcx : TyCtxt < ' tcx > ,
332
333
predicates : impl IntoIterator < Item = ( ty:: Clause < ' tcx > , Span ) > ,
334
+ assoc : ty:: AssocItem ,
333
335
) -> ( String , String ) {
334
336
let mut types: FxIndexMap < Ty < ' tcx > , Vec < DefId > > = FxIndexMap :: default ( ) ;
335
337
let mut projections = vec ! [ ] ;
@@ -353,34 +355,50 @@ fn bounds_from_generic_predicates<'tcx>(
353
355
}
354
356
355
357
let mut where_clauses = vec ! [ ] ;
356
- let mut types_str = vec ! [ ] ;
357
- for ( ty, bounds) in types {
358
- if let ty:: Param ( _) = ty. kind ( ) {
359
- let mut bounds_str = vec ! [ ] ;
360
- for bound in bounds {
361
- let mut projections_str = vec ! [ ] ;
362
- for projection in & projections {
363
- let p = projection. skip_binder ( ) ;
364
- if bound == tcx. parent ( p. projection_term . def_id )
365
- && p. projection_term . self_ty ( ) == ty
366
- {
367
- let name = tcx. item_name ( p. projection_term . def_id ) ;
368
- projections_str. push ( format ! ( "{} = {}" , name, p. term) ) ;
358
+ let generics = tcx. generics_of ( assoc. def_id ) ;
359
+ let types_str = generics
360
+ . own_params
361
+ . iter ( )
362
+ . filter ( |p| matches ! ( p. kind, GenericParamDefKind :: Type { synthetic: false , .. } ) )
363
+ . map ( |p| {
364
+ // we just checked that it's a type, so the unwrap can't fail
365
+ let ty = tcx. mk_param_from_def ( p) . as_type ( ) . unwrap ( ) ;
366
+ if let Some ( bounds) = types. get ( & ty) {
367
+ let mut bounds_str = vec ! [ ] ;
368
+ for bound in bounds. iter ( ) . copied ( ) {
369
+ let mut projections_str = vec ! [ ] ;
370
+ for projection in & projections {
371
+ let p = projection. skip_binder ( ) ;
372
+ if bound == tcx. parent ( p. projection_term . def_id )
373
+ && p. projection_term . self_ty ( ) == ty
374
+ {
375
+ let name = tcx. item_name ( p. projection_term . def_id ) ;
376
+ projections_str. push ( format ! ( "{} = {}" , name, p. term) ) ;
377
+ }
378
+ }
379
+ let bound_def_path = tcx. def_path_str ( bound) ;
380
+ if projections_str. is_empty ( ) {
381
+ where_clauses. push ( format ! ( "{}: {}" , ty, bound_def_path) ) ;
382
+ } else {
383
+ bounds_str. push ( format ! (
384
+ "{}<{}>" ,
385
+ bound_def_path,
386
+ projections_str. join( ", " )
387
+ ) ) ;
369
388
}
370
389
}
371
- let bound_def_path = tcx. def_path_str ( bound) ;
372
- if projections_str. is_empty ( ) {
373
- where_clauses. push ( format ! ( "{}: {}" , ty, bound_def_path) ) ;
390
+ if bounds_str. is_empty ( ) {
391
+ ty. to_string ( )
374
392
} else {
375
- bounds_str . push ( format ! ( "{}<{}> " , bound_def_path , projections_str . join( ", " ) ) ) ;
393
+ format ! ( "{}: {} " , ty , bounds_str . join( " + " ) )
376
394
}
377
- }
378
- if bounds_str. is_empty ( ) {
379
- types_str. push ( ty. to_string ( ) ) ;
380
395
} else {
381
- types_str . push ( format ! ( "{}: {}" , ty , bounds_str . join ( " + " ) ) ) ;
396
+ ty . to_string ( )
382
397
}
383
- } else {
398
+ } )
399
+ . collect :: < Vec < _ > > ( ) ;
400
+ for ( ty, bounds) in types. into_iter ( ) {
401
+ if !matches ! ( ty. kind( ) , ty:: Param ( _) ) {
384
402
// Avoid suggesting the following:
385
403
// fn foo<T, <T as Trait>::Bar>(_: T) where T: Trait, <T as Trait>::Bar: Other {}
386
404
where_clauses. extend (
@@ -472,10 +490,10 @@ fn fn_sig_suggestion<'tcx>(
472
490
let output = if !output. is_unit ( ) { format ! ( " -> {output}" ) } else { String :: new ( ) } ;
473
491
474
492
let safety = sig. safety . prefix_str ( ) ;
475
- let ( generics, where_clauses) = bounds_from_generic_predicates ( tcx, predicates) ;
493
+ let ( generics, where_clauses) = bounds_from_generic_predicates ( tcx, predicates, assoc ) ;
476
494
477
495
// FIXME: this is not entirely correct, as the lifetimes from borrowed params will
478
- // not be present in the `fn` definition, not will we account for renamed
496
+ // not be present in the `fn` definition, nor will we account for renamed
479
497
// lifetimes between the `impl` and the `trait`, but this should be good enough to
480
498
// fill in a significant portion of the missing code, and other subsequent
481
499
// suggestions can help the user fix the code.
@@ -511,6 +529,7 @@ fn suggestion_signature<'tcx>(
511
529
let ( generics, where_clauses) = bounds_from_generic_predicates (
512
530
tcx,
513
531
tcx. predicates_of ( assoc. def_id ) . instantiate_own ( tcx, args) ,
532
+ assoc,
514
533
) ;
515
534
format ! ( "type {}{generics} = /* Type */{where_clauses};" , assoc. name( ) )
516
535
}
0 commit comments