@@ -68,9 +68,21 @@ impl clean::GenericParamDef {
6868
6969 Ok ( ( ) )
7070 }
71- clean:: GenericParamDefKind :: Type { bounds, default, .. } => {
71+ clean:: GenericParamDefKind :: Type { bounds, default, allow_unsized , .. } => {
7272 f. write_str ( self . name . as_str ( ) ) ?;
7373
74+ let filtered: Vec < _ > ;
75+ let bounds = if !allow_unsized {
76+ filtered = bounds
77+ . iter ( )
78+ . filter ( |b| !b. is_maybe_sized_bound ( cx. tcx ( ) ) )
79+ . cloned ( )
80+ . collect ( ) ;
81+ filtered. as_slice ( )
82+ } else {
83+ bounds. as_slice ( )
84+ } ;
85+
7486 if !bounds. is_empty ( ) {
7587 f. write_str ( ": " ) ?;
7688 print_generic_bounds ( bounds, cx) . fmt ( f) ?;
@@ -127,14 +139,45 @@ pub(crate) enum Ending {
127139 NoNewline ,
128140}
129141
130- fn print_where_predicate ( predicate : & clean:: WherePredicate , cx : & Context < ' _ > ) -> impl Display {
142+ fn print_where_predicate (
143+ predicate : & clean:: WherePredicate ,
144+ disallow_unsized : & FxHashSet < Symbol > ,
145+ cx : & Context < ' _ > ,
146+ ) -> impl Display {
131147 fmt:: from_fn ( move |f| {
132148 match predicate {
133149 clean:: WherePredicate :: BoundPredicate { ty, bounds, bound_params } => {
134- print_higher_ranked_params_with_space ( bound_params, cx, "for" ) . fmt ( f) ?;
135- ty. print ( cx) . fmt ( f) ?;
136- f. write_str ( ":" ) ?;
150+ let filtered: Vec < _ > ;
151+ let mut bounds_slice = bounds. as_slice ( ) ;
152+ // Check if the bound is on a generic type parameter that
153+ // does not accept unsized types.
154+ if let clean:: Type :: Generic ( symbol) = ty
155+ && disallow_unsized. contains ( symbol)
156+ {
157+ // Check if the predicate contains a `?Sized` bound on that generic type.
158+ // Even though the bound is syntactically present, we know that
159+ // another bound requires this generic to be `Sized`.
160+ // We omit the `?Sized` bound from the representation.
161+ // See: https://github.com/rust-lang/rust/issues/143197
162+ //
163+ // We do two passes to avoid allocating a new `Vec` and copying it
164+ // in the most common case: when `?Sized` is *not* present.
165+ if bounds. iter ( ) . any ( |b| b. is_maybe_sized_bound ( cx. tcx ( ) ) ) {
166+ filtered = bounds
167+ . iter ( )
168+ . filter ( |b| !b. is_maybe_sized_bound ( cx. tcx ( ) ) )
169+ . cloned ( )
170+ . collect ( ) ;
171+ bounds_slice = filtered. as_slice ( ) ;
172+ }
173+ } ;
174+ let bounds = bounds_slice;
175+
137176 if !bounds. is_empty ( ) {
177+ print_higher_ranked_params_with_space ( bound_params, cx, "for" ) . fmt ( f) ?;
178+ ty. print ( cx) . fmt ( f) ?;
179+ f. write_str ( ":" ) ?;
180+
138181 f. write_str ( " " ) ?;
139182 print_generic_bounds ( bounds, cx) . fmt ( f) ?;
140183 }
@@ -172,6 +215,8 @@ pub(crate) fn print_where_clause(
172215 if gens. where_predicates . is_empty ( ) {
173216 return None ;
174217 }
218+ let disallow_unsized: FxHashSet < _ > =
219+ gens. params . iter ( ) . filter ( |p| p. is_type ( ) && !p. allow_unsized ( ) ) . map ( |p| p. name ) . collect ( ) ;
175220
176221 Some ( fmt:: from_fn ( move |f| {
177222 let where_preds = fmt:: from_fn ( |f| {
@@ -184,7 +229,7 @@ pub(crate) fn print_where_clause(
184229 } else {
185230 f. write_str ( "\n " ) ?;
186231 }
187- print_where_predicate ( predicate, cx) . fmt ( f)
232+ print_where_predicate ( predicate, & disallow_unsized , cx) . fmt ( f)
188233 } )
189234 } )
190235 . joined ( "," , f)
@@ -1017,6 +1062,8 @@ fn fmt_type(
10171062 }
10181063 clean:: ImplTrait ( bounds) => {
10191064 f. write_str ( "impl " ) ?;
1065+ // TODO: Figure out if one of the bounds here is `?Sized`
1066+ // and whether another bound implies `Sized`.
10201067 print_generic_bounds ( bounds, cx) . fmt ( f)
10211068 }
10221069 clean:: QPath ( qpath) => qpath. print ( cx) . fmt ( f) ,
0 commit comments