@@ -85,7 +85,9 @@ use rustc_infer::traits::ObligationCause;
8585use rustc_middle:: query:: Providers ;
8686use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
8787use 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+ } ;
8991use rustc_middle:: { bug, span_bug} ;
9092use rustc_session:: parse:: feature_err;
9193use rustc_span:: def_id:: CRATE_DEF_ID ;
@@ -233,8 +235,7 @@ fn missing_items_err(
233235 } ;
234236
235237 // Obtain the level of indentation ending in `sugg_sp`.
236- let padding =
237- tcx. sess . source_map ( ) . indentation_before ( sugg_sp) . unwrap_or_else ( || String :: new ( ) ) ;
238+ let padding = tcx. sess . source_map ( ) . indentation_before ( sugg_sp) . unwrap_or_else ( String :: new) ;
238239 let ( mut missing_trait_item, mut missing_trait_item_none, mut missing_trait_item_label) =
239240 ( Vec :: new ( ) , Vec :: new ( ) , Vec :: new ( ) ) ;
240241
@@ -331,6 +332,7 @@ fn default_body_is_unstable(
331332fn bounds_from_generic_predicates < ' tcx > (
332333 tcx : TyCtxt < ' tcx > ,
333334 predicates : impl IntoIterator < Item = ( ty:: Clause < ' tcx > , Span ) > ,
335+ assoc : ty:: AssocItem ,
334336) -> ( String , String ) {
335337 let mut types: FxIndexMap < Ty < ' tcx > , Vec < DefId > > = FxIndexMap :: default ( ) ;
336338 let mut projections = vec ! [ ] ;
@@ -354,34 +356,50 @@ fn bounds_from_generic_predicates<'tcx>(
354356 }
355357
356358 let mut where_clauses = vec ! [ ] ;
357- let mut types_str = vec ! [ ] ;
358- for ( ty, bounds) in types {
359- if let ty:: Param ( _) = ty. kind ( ) {
360- let mut bounds_str = vec ! [ ] ;
361- for bound in bounds {
362- let mut projections_str = vec ! [ ] ;
363- for projection in & projections {
364- let p = projection. skip_binder ( ) ;
365- if bound == tcx. parent ( p. projection_term . def_id )
366- && p. projection_term . self_ty ( ) == ty
367- {
368- let name = tcx. item_name ( p. projection_term . def_id ) ;
369- projections_str. push ( format ! ( "{} = {}" , name, p. term) ) ;
359+ let generics = tcx. generics_of ( assoc. def_id ) ;
360+ let types_str = generics
361+ . own_params
362+ . iter ( )
363+ . filter ( |p| matches ! ( p. kind, GenericParamDefKind :: Type { synthetic: false , .. } ) )
364+ . map ( |p| {
365+ // we just checked that it's a type, so the unwrap can't fail
366+ let ty = tcx. mk_param_from_def ( p) . as_type ( ) . unwrap ( ) ;
367+ if let Some ( bounds) = types. get ( & ty) {
368+ let mut bounds_str = vec ! [ ] ;
369+ for bound in bounds. iter ( ) . copied ( ) {
370+ let mut projections_str = vec ! [ ] ;
371+ for projection in & projections {
372+ let p = projection. skip_binder ( ) ;
373+ if bound == tcx. parent ( p. projection_term . def_id )
374+ && p. projection_term . self_ty ( ) == ty
375+ {
376+ let name = tcx. item_name ( p. projection_term . def_id ) ;
377+ projections_str. push ( format ! ( "{} = {}" , name, p. term) ) ;
378+ }
379+ }
380+ let bound_def_path = tcx. def_path_str ( bound) ;
381+ if projections_str. is_empty ( ) {
382+ where_clauses. push ( format ! ( "{}: {}" , ty, bound_def_path) ) ;
383+ } else {
384+ bounds_str. push ( format ! (
385+ "{}<{}>" ,
386+ bound_def_path,
387+ projections_str. join( ", " )
388+ ) ) ;
370389 }
371390 }
372- let bound_def_path = tcx. def_path_str ( bound) ;
373- if projections_str. is_empty ( ) {
374- where_clauses. push ( format ! ( "{}: {}" , ty, bound_def_path) ) ;
391+ if bounds_str. is_empty ( ) {
392+ ty. to_string ( )
375393 } else {
376- bounds_str . push ( format ! ( "{}<{}> " , bound_def_path , projections_str . join( ", " ) ) ) ;
394+ format ! ( "{}: {} " , ty , bounds_str . join( " + " ) )
377395 }
378- }
379- if bounds_str. is_empty ( ) {
380- types_str. push ( ty. to_string ( ) ) ;
381396 } else {
382- types_str . push ( format ! ( "{}: {}" , ty , bounds_str . join ( " + " ) ) ) ;
397+ ty . to_string ( )
383398 }
384- } else {
399+ } )
400+ . collect :: < Vec < _ > > ( ) ;
401+ for ( ty, bounds) in types. into_iter ( ) {
402+ if !matches ! ( ty. kind( ) , ty:: Param ( _) ) {
385403 // Avoid suggesting the following:
386404 // fn foo<T, <T as Trait>::Bar>(_: T) where T: Trait, <T as Trait>::Bar: Other {}
387405 where_clauses. extend (
@@ -473,10 +491,10 @@ fn fn_sig_suggestion<'tcx>(
473491 let output = if !output. is_unit ( ) { format ! ( " -> {output}" ) } else { String :: new ( ) } ;
474492
475493 let safety = sig. safety . prefix_str ( ) ;
476- let ( generics, where_clauses) = bounds_from_generic_predicates ( tcx, predicates) ;
494+ let ( generics, where_clauses) = bounds_from_generic_predicates ( tcx, predicates, assoc ) ;
477495
478496 // FIXME: this is not entirely correct, as the lifetimes from borrowed params will
479- // not be present in the `fn` definition, not will we account for renamed
497+ // not be present in the `fn` definition, nor will we account for renamed
480498 // lifetimes between the `impl` and the `trait`, but this should be good enough to
481499 // fill in a significant portion of the missing code, and other subsequent
482500 // suggestions can help the user fix the code.
@@ -512,6 +530,7 @@ fn suggestion_signature<'tcx>(
512530 let ( generics, where_clauses) = bounds_from_generic_predicates (
513531 tcx,
514532 tcx. predicates_of ( assoc. def_id ) . instantiate_own ( tcx, args) ,
533+ assoc,
515534 ) ;
516535 format ! ( "type {}{generics} = /* Type */{where_clauses};" , assoc. name( ) )
517536 }
0 commit comments