@@ -13,7 +13,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
1313use rustc_errors:: { Applicability , Diag , E0038 , E0276 , MultiSpan , struct_span_code_err} ;
1414use rustc_hir:: def_id:: { DefId , LocalDefId } ;
1515use rustc_hir:: intravisit:: Visitor ;
16- use rustc_hir:: { self as hir, AmbigArg , LangItem } ;
16+ use rustc_hir:: { self as hir, AmbigArg } ;
1717use rustc_infer:: traits:: solve:: Goal ;
1818use rustc_infer:: traits:: {
1919 DynCompatibilityViolation , Obligation , ObligationCause , ObligationCauseCode ,
@@ -334,19 +334,26 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti
334334 let trait_ref = tcx. impl_trait_ref ( impl_def_id) ?. instantiate_identity ( ) ;
335335 let mut w = "impl" . to_owned ( ) ;
336336
337- let args = ty:: GenericArgs :: identity_for_item ( tcx, impl_def_id) ;
337+ #[ derive( Debug , Default ) ]
338+ struct SizednessFound {
339+ sized : bool ,
340+ meta_sized : bool ,
341+ }
338342
339- // FIXME: Currently only handles ?Sized.
340- // Needs to support ?Move and ?DynSized when they are implemented.
341- let mut types_without_default_bounds = FxIndexSet :: default ( ) ;
342- let sized_trait = tcx. lang_items ( ) . sized_trait ( ) ;
343+ let mut types_with_sizedness_bounds = FxIndexMap :: < _ , SizednessFound > :: default ( ) ;
344+
345+ let args = ty:: GenericArgs :: identity_for_item ( tcx, impl_def_id) ;
343346
344347 let arg_names = args. iter ( ) . map ( |k| k. to_string ( ) ) . filter ( |k| k != "'_" ) . collect :: < Vec < _ > > ( ) ;
345348 if !arg_names. is_empty ( ) {
346- types_without_default_bounds. extend ( args. types ( ) ) ;
347349 w. push ( '<' ) ;
348350 w. push_str ( & arg_names. join ( ", " ) ) ;
349351 w. push ( '>' ) ;
352+
353+ for ty in args. types ( ) {
354+ // `PointeeSized` params might have no predicates.
355+ types_with_sizedness_bounds. insert ( ty, SizednessFound :: default ( ) ) ;
356+ }
350357 }
351358
352359 write ! (
@@ -358,24 +365,47 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti
358365 )
359366 . unwrap ( ) ;
360367
361- // The predicates will contain default bounds like `T: Sized`. We need to
362- // remove these bounds, and add `T: ?Sized` to any untouched type parameters.
363368 let predicates = tcx. predicates_of ( impl_def_id) . predicates ;
364- let mut pretty_predicates =
365- Vec :: with_capacity ( predicates. len ( ) + types_without_default_bounds. len ( ) ) ;
369+ let mut pretty_predicates = Vec :: with_capacity ( predicates. len ( ) ) ;
370+
371+ let sized_trait = tcx. lang_items ( ) . sized_trait ( ) ;
372+ let meta_sized_trait = tcx. lang_items ( ) . meta_sized_trait ( ) ;
366373
367374 for ( p, _) in predicates {
368- if let Some ( poly_trait_ref) = p. as_trait_clause ( ) {
369- if Some ( poly_trait_ref. def_id ( ) ) == sized_trait {
370- // FIXME(#120456) - is `swap_remove` correct?
371- types_without_default_bounds. swap_remove ( & poly_trait_ref. self_ty ( ) . skip_binder ( ) ) ;
375+ // Accumulate the sizedness bounds for each self ty.
376+ if let Some ( trait_clause) = p. as_trait_clause ( ) {
377+ let self_ty = trait_clause. self_ty ( ) . skip_binder ( ) ;
378+ let sizedness_of = types_with_sizedness_bounds. entry ( self_ty) . or_default ( ) ;
379+ if Some ( trait_clause. def_id ( ) ) == sized_trait {
380+ sizedness_of. sized = true ;
381+ continue ;
382+ } else if Some ( trait_clause. def_id ( ) ) == meta_sized_trait {
383+ sizedness_of. meta_sized = true ;
372384 continue ;
373385 }
374386 }
387+
375388 pretty_predicates. push ( p. to_string ( ) ) ;
376389 }
377390
378- pretty_predicates. extend ( types_without_default_bounds. iter ( ) . map ( |ty| format ! ( "{ty}: ?Sized" ) ) ) ;
391+ for ( ty, sizedness) in types_with_sizedness_bounds {
392+ if !tcx. features ( ) . sized_hierarchy ( ) {
393+ if sizedness. sized {
394+ // Maybe a default bound, don't write anything.
395+ } else {
396+ pretty_predicates. push ( format ! ( "{ty}: ?Sized" ) ) ;
397+ }
398+ } else {
399+ if sizedness. sized {
400+ // Maybe a default bound, don't write anything.
401+ pretty_predicates. push ( format ! ( "{ty}: Sized" ) ) ;
402+ } else if sizedness. meta_sized {
403+ pretty_predicates. push ( format ! ( "{ty}: MetaSized" ) ) ;
404+ } else {
405+ pretty_predicates. push ( format ! ( "{ty}: PointeeSized" ) ) ;
406+ }
407+ }
408+ }
379409
380410 if !pretty_predicates. is_empty ( ) {
381411 write ! ( w, "\n where {}" , pretty_predicates. join( ", " ) ) . unwrap ( ) ;
0 commit comments