@@ -11,15 +11,15 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
1111use rustc_errors:: { Applicability , Diag , E0038 , E0276 , MultiSpan , struct_span_code_err} ;
1212use rustc_hir:: def_id:: { DefId , LocalDefId } ;
1313use rustc_hir:: intravisit:: Visitor ;
14- use rustc_hir:: { self as hir, AmbigArg , LangItem } ;
14+ use rustc_hir:: { self as hir, AmbigArg } ;
1515use rustc_infer:: traits:: {
1616 DynCompatibilityViolation , Obligation , ObligationCause , ObligationCauseCode ,
1717 PredicateObligation , SelectionError ,
1818} ;
1919use rustc_middle:: ty:: print:: { PrintTraitRefExt as _, with_no_trimmed_paths} ;
2020use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
2121use rustc_span:: { ErrorGuaranteed , ExpnKind , Span } ;
22- use tracing:: { info, instrument} ;
22+ use tracing:: { debug , info, instrument} ;
2323
2424pub use self :: overflow:: * ;
2525use crate :: error_reporting:: TypeErrCtxt ;
@@ -338,19 +338,26 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti
338338 let trait_ref = tcx. impl_trait_ref ( impl_def_id) ?. instantiate_identity ( ) ;
339339 let mut w = "impl" . to_owned ( ) ;
340340
341- let args = ty:: GenericArgs :: identity_for_item ( tcx, impl_def_id) ;
341+ #[ derive( Debug , Default ) ]
342+ struct SizednessFound {
343+ sized : bool ,
344+ metasized : bool ,
345+ }
342346
343- // FIXME: Currently only handles ?Sized.
344- // Needs to support ?Move and ?DynSized when they are implemented.
345- let mut types_without_default_bounds = FxIndexSet :: default ( ) ;
346- let sized_trait = tcx. lang_items ( ) . sized_trait ( ) ;
347+ let mut types_with_sizedness_bounds = FxIndexMap :: < _ , SizednessFound > :: default ( ) ;
348+
349+ let args = ty:: GenericArgs :: identity_for_item ( tcx, impl_def_id) ;
347350
348351 let arg_names = args. iter ( ) . map ( |k| k. to_string ( ) ) . filter ( |k| k != "'_" ) . collect :: < Vec < _ > > ( ) ;
349352 if !arg_names. is_empty ( ) {
350- types_without_default_bounds. extend ( args. types ( ) ) ;
351353 w. push ( '<' ) ;
352354 w. push_str ( & arg_names. join ( ", " ) ) ;
353355 w. push ( '>' ) ;
356+
357+ for ty in args. types ( ) {
358+ // `PointeeSized` params might have no predicates.
359+ types_with_sizedness_bounds. insert ( ty, SizednessFound :: default ( ) ) ;
360+ }
354361 }
355362
356363 write ! (
@@ -362,24 +369,48 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti
362369 )
363370 . unwrap ( ) ;
364371
365- // The predicates will contain default bounds like `T: Sized`. We need to
366- // remove these bounds, and add `T: ?Sized` to any untouched type parameters.
367372 let predicates = tcx. predicates_of ( impl_def_id) . predicates ;
368- let mut pretty_predicates =
369- Vec :: with_capacity ( predicates. len ( ) + types_without_default_bounds. len ( ) ) ;
373+ let mut pretty_predicates = Vec :: with_capacity ( predicates. len ( ) ) ;
374+
375+ let sized_trait = tcx. lang_items ( ) . sized_trait ( ) ;
376+ let metasized_trait = tcx. lang_items ( ) . metasized_trait ( ) ;
370377
371378 for ( p, _) in predicates {
372- if let Some ( poly_trait_ref) = p. as_trait_clause ( ) {
373- if Some ( poly_trait_ref. def_id ( ) ) == sized_trait {
374- // FIXME(#120456) - is `swap_remove` correct?
375- types_without_default_bounds. swap_remove ( & poly_trait_ref. self_ty ( ) . skip_binder ( ) ) ;
379+ // Accumulate the sizedness bounds for each self ty.
380+ if let Some ( trait_clause) = p. as_trait_clause ( ) {
381+ let self_ty = trait_clause. self_ty ( ) . skip_binder ( ) ;
382+ let sizedness_of = types_with_sizedness_bounds. entry ( self_ty) . or_default ( ) ;
383+ if Some ( trait_clause. def_id ( ) ) == sized_trait {
384+ sizedness_of. sized = true ;
385+ continue ;
386+ } else if Some ( trait_clause. def_id ( ) ) == metasized_trait {
387+ sizedness_of. metasized = true ;
376388 continue ;
377389 }
378390 }
391+
379392 pretty_predicates. push ( p. to_string ( ) ) ;
380393 }
381394
382- pretty_predicates. extend ( types_without_default_bounds. iter ( ) . map ( |ty| format ! ( "{ty}: ?Sized" ) ) ) ;
395+ for ( ty, sizedness) in types_with_sizedness_bounds {
396+ debug ! ( ?ty, ?sizedness) ;
397+ if !tcx. features ( ) . sized_hierarchy ( ) {
398+ if sizedness. sized {
399+ // Maybe a default bound, don't write anything.
400+ } else {
401+ pretty_predicates. push ( format ! ( "{ty}: ?Sized" ) ) ;
402+ }
403+ } else {
404+ if sizedness. sized {
405+ // Maybe a default bound, don't write anything.
406+ pretty_predicates. push ( format ! ( "{ty}: Sized" ) ) ;
407+ } else if sizedness. metasized {
408+ pretty_predicates. push ( format ! ( "{ty}: MetaSized" ) ) ;
409+ } else {
410+ pretty_predicates. push ( format ! ( "{ty}: PointeeSized" ) ) ;
411+ }
412+ }
413+ }
383414
384415 if !pretty_predicates. is_empty ( ) {
385416 write ! ( w, "\n where {}" , pretty_predicates. join( ", " ) ) . unwrap ( ) ;
0 commit comments