@@ -86,7 +86,8 @@ use rustc_middle::query::Providers;
8686use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
8787use rustc_middle:: ty:: print:: with_types_for_signature;
8888use rustc_middle:: ty:: {
89- self , GenericArgs , GenericArgsRef , GenericParamDefKind , Ty , TyCtxt , TypingMode ,
89+ self , GenericArgs , GenericArgsRef , GenericParamDefKind , OutlivesPredicate , Region , Ty , TyCtxt ,
90+ TypingMode ,
9091} ;
9192use rustc_middle:: { bug, span_bug} ;
9293use rustc_session:: parse:: feature_err;
@@ -335,6 +336,7 @@ fn bounds_from_generic_predicates<'tcx>(
335336 assoc : ty:: AssocItem ,
336337) -> ( String , String ) {
337338 let mut types: FxIndexMap < Ty < ' tcx > , Vec < DefId > > = FxIndexMap :: default ( ) ;
339+ let mut regions: FxIndexMap < Region < ' tcx > , Vec < Region < ' tcx > > > = FxIndexMap :: default ( ) ;
338340 let mut projections = vec ! [ ] ;
339341 for ( predicate, _) in predicates {
340342 debug ! ( "predicate {:?}" , predicate) ;
@@ -351,65 +353,101 @@ fn bounds_from_generic_predicates<'tcx>(
351353 ty:: ClauseKind :: Projection ( projection_pred) => {
352354 projections. push ( bound_predicate. rebind ( projection_pred) ) ;
353355 }
356+ ty:: ClauseKind :: RegionOutlives ( OutlivesPredicate ( a, b) ) => {
357+ regions. entry ( a) . or_default ( ) . push ( b) ;
358+ }
354359 _ => { }
355360 }
356361 }
357362
358363 let mut where_clauses = vec ! [ ] ;
359364 let generics = tcx. generics_of ( assoc. def_id ) ;
360- let types_str = generics
365+ let params = generics
361366 . own_params
362367 . 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) ) ;
368+ . filter ( |p| !matches ! ( p. kind, GenericParamDefKind :: Type { synthetic: true , .. } ) )
369+ . map ( |p| match tcx. mk_param_from_def ( p) {
370+ x if let Some ( ty) = x. as_type ( ) => {
371+ if let Some ( bounds) = types. get ( & ty) {
372+ let mut bounds_str = vec ! [ ] ;
373+ for bound in bounds. iter ( ) . copied ( ) {
374+ let mut projections_str = vec ! [ ] ;
375+ for projection in & projections {
376+ let p = projection. skip_binder ( ) ;
377+ if bound == tcx. parent ( p. projection_term . def_id )
378+ && p. projection_term . self_ty ( ) == ty
379+ {
380+ let name = tcx. item_name ( p. projection_term . def_id ) ;
381+ projections_str. push ( format ! ( "{} = {}" , name, p. term) ) ;
382+ }
383+ }
384+ let bound_def_path = if tcx. is_lang_item ( bound, LangItem :: MetaSized ) {
385+ String :: from ( "?Sized" )
386+ } else {
387+ tcx. def_path_str ( bound)
388+ } ;
389+ if projections_str. is_empty ( ) {
390+ where_clauses. push ( format ! ( "{}: {}" , ty, bound_def_path) ) ;
391+ } else {
392+ bounds_str. push ( format ! (
393+ "{}<{}>" ,
394+ bound_def_path,
395+ projections_str. join( ", " )
396+ ) ) ;
378397 }
379398 }
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) ) ;
399+ if bounds_str. is_empty ( ) {
400+ ty. to_string ( )
383401 } else {
384- bounds_str. push ( format ! (
385- "{}<{}>" ,
386- bound_def_path,
387- projections_str. join( ", " )
388- ) ) ;
402+ format ! ( "{}: {}" , ty, bounds_str. join( " + " ) )
389403 }
390- }
391- if bounds_str. is_empty ( ) {
404+ } else {
392405 ty. to_string ( )
406+ }
407+ }
408+ x if let Some ( ct) = x. as_const ( ) => {
409+ format ! ( "const {ct}: {}" , tcx. type_of( p. def_id) . skip_binder( ) )
410+ }
411+ x if let Some ( region) = x. as_region ( ) => {
412+ if let Some ( v) = regions. get ( & region)
413+ && !v. is_empty ( )
414+ {
415+ format ! (
416+ "{region}: {}" ,
417+ v. into_iter( ) . map( Region :: to_string) . collect:: <Vec <_>>( ) . join( " + " )
418+ )
393419 } else {
394- format ! ( "{}: {}" , ty , bounds_str . join ( " + " ) )
420+ region . to_string ( )
395421 }
396- } else {
397- ty. to_string ( )
422+ }
423+ _ if let Some ( span) = tcx. def_ident_span ( assoc. def_id ) => {
424+ span_bug ! ( span, "GenericParamDef isn't a type, const, or region" ) ;
425+ }
426+ _ => {
427+ bug ! ( "GenericParamDef isn't a type, const, or region" ) ;
398428 }
399429 } )
400430 . collect :: < Vec < _ > > ( ) ;
401431 for ( ty, bounds) in types. into_iter ( ) {
402432 if !matches ! ( ty. kind( ) , ty:: Param ( _) ) {
403433 // Avoid suggesting the following:
404434 // fn foo<T, <T as Trait>::Bar>(_: T) where T: Trait, <T as Trait>::Bar: Other {}
405- where_clauses. extend (
406- bounds. into_iter ( ) . map ( |bound| format ! ( "{}: {}" , ty, tcx. def_path_str( bound) ) ) ,
407- ) ;
435+ where_clauses. extend ( bounds. into_iter ( ) . map ( |bound| {
436+ format ! (
437+ "{}: {}" ,
438+ ty,
439+ if tcx. is_lang_item( bound, LangItem :: MetaSized ) {
440+ String :: from( "?Sized" )
441+ } else {
442+ tcx. def_path_str( bound)
443+ }
444+ )
445+ } ) ) ;
408446 }
409447 }
410448
411449 let generics =
412- if types_str . is_empty ( ) { "" . to_string ( ) } else { format ! ( "<{}>" , types_str . join( ", " ) ) } ;
450+ if params . is_empty ( ) { "" . to_string ( ) } else { format ! ( "<{}>" , params . join( ", " ) ) } ;
413451
414452 let where_clauses = if where_clauses. is_empty ( ) {
415453 "" . to_string ( )
0 commit comments