@@ -158,11 +158,6 @@ impl UnderspecifiedArgKind {
158
158
159
159
struct ClosureEraser < ' a , ' tcx > {
160
160
infcx : & ' a InferCtxt < ' tcx > ,
161
- // When recursing into types, if an ADT has type parameters with a default type we do *not*
162
- // want to replace that type parameter with `_`, as it will cause the normally hidden type
163
- // parameter to be rendered. The best example of this is `Vec<T, Alloc>`, which we want to
164
- // render as `Vec<T>` and not `Vec<T, _>` when `T` is unknown.
165
- do_not_hide_nested_type : bool ,
166
161
}
167
162
168
163
impl < ' a , ' tcx > ClosureEraser < ' a , ' tcx > {
@@ -177,8 +172,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'a, 'tcx> {
177
172
}
178
173
179
174
fn fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
180
- let prev = self . do_not_hide_nested_type ;
181
- let ty = match ty. kind ( ) {
175
+ match ty. kind ( ) {
182
176
ty:: Closure ( _, args) => {
183
177
// For a closure type, we turn it into a function pointer so that it gets rendered
184
178
// as `fn(args) -> Ret`.
@@ -188,52 +182,65 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'a, 'tcx> {
188
182
self . cx ( ) . signature_unclosure ( closure_sig, hir:: Safety :: Safe ) ,
189
183
)
190
184
}
191
- ty:: Adt ( def, _ ) => {
185
+ ty:: Adt ( def, args ) => {
192
186
let generics = self . cx ( ) . generics_of ( def. did ( ) ) ;
193
- if generics. own_params . iter ( ) . any ( |param| param. default_value ( self . cx ( ) ) . is_some ( ) )
194
- {
195
- // We have a type that has default types, like the allocator in Vec. We decided
196
- // to show `Vec` itself, because it hasn't yet been replaced by an `_` `Infer`,
197
- // but we want to ensure that the type parameter with default types does *not*
198
- // get replaced with `_` because then we'd end up with `Vec<_, _>`, instead of
199
- // `Vec<_>`.
200
- self . do_not_hide_nested_type = true ;
201
- ty. super_fold_with ( self )
202
- } else if ty. has_infer ( ) || self . do_not_hide_nested_type {
203
- // This type has an unsubstituted type variable, meaning that this type has a
204
- // (potentially deeply nested) type parameter from the corresponding type's
205
- // definition. We have explicitly asked this type to not be hidden. In either
206
- // case, we keep the type and don't substitute with `_` just yet.
207
- ty. super_fold_with ( self )
208
- } else {
209
- // When we have a type that doesn't have any inference variables, so we replace
187
+ let generics: Vec < bool > = generics
188
+ . own_params
189
+ . iter ( )
190
+ . map ( |param| param. default_value ( self . cx ( ) ) . is_some ( ) )
191
+ . collect ( ) ;
192
+ let mut all_infer = true ;
193
+ let ty = Ty :: new_adt (
194
+ self . cx ( ) ,
195
+ * def,
196
+ self . cx ( ) . mk_args_from_iter ( generics. into_iter ( ) . zip ( args. iter ( ) ) . map (
197
+ |( has_default, arg) | {
198
+ if has_default {
199
+ // We have a type param that has a default type, like the allocator
200
+ // in Vec. We decided to show `Vec` itself, because it hasn't yet
201
+ // been replaced by an `_` `Infer`, but we want to ensure that the
202
+ // type parameter with default types does *not* get replaced with
203
+ // `_` because then we'd end up with `Vec<_, _>`, instead of
204
+ // `Vec<_>`.
205
+ all_infer = false ;
206
+ arg
207
+ } else if arg. has_infer ( ) {
208
+ // This param has an unsubstituted type variable, meaning that this
209
+ // type has a (potentially deeply nested) type parameter from the
210
+ // corresponding type's definition. We have explicitly asked this
211
+ // type to not be hidden. In either case, we keep the type and don't
212
+ // substitute with `_` just yet.
213
+ all_infer = false ;
214
+ arg. fold_with ( self )
215
+ } else {
216
+ self . new_infer ( ) . into ( )
217
+ }
218
+ } ,
219
+ ) ) ,
220
+ ) ;
221
+ if all_infer {
222
+ // We have a type that doesn't have any inference variables, so we replace
210
223
// the whole thing with `_`. The type system already knows about this type in
211
224
// its entirety and it is redundant to specify it for the user. The user only
212
225
// needs to specify the type parameters that we *couldn't* figure out.
213
226
self . new_infer ( )
227
+ } else {
228
+ ty
214
229
}
215
230
}
216
- _ if ty. has_infer ( ) || self . do_not_hide_nested_type => {
231
+ _ if ty. has_infer ( ) => {
217
232
// This type has a (potentially nested) type parameter that we couldn't figure out.
218
233
// We will print this depth of type, so at least the type name and at least one of
219
- // its type parameters. We unset `do_not_hide_nested_type` because this type can't
220
- // have type parameter defaults until next type we hit an ADT.
221
- self . do_not_hide_nested_type = false ;
234
+ // its type parameters.
222
235
ty. super_fold_with ( self )
223
236
}
224
237
// We don't have an unknown type parameter anywhere, replace with `_`.
225
238
_ => self . new_infer ( ) ,
226
- } ;
227
- self . do_not_hide_nested_type = prev;
228
- ty
239
+ }
229
240
}
230
241
231
242
fn fold_const ( & mut self , c : ty:: Const < ' tcx > ) -> ty:: Const < ' tcx > {
232
- let prev = self . do_not_hide_nested_type ;
233
243
// Avoid accidentally erasing the type of the const.
234
- self . do_not_hide_nested_type = true ;
235
- let c = c. super_fold_with ( self ) ;
236
- self . do_not_hide_nested_type = prev;
237
244
c
238
245
}
239
246
}
@@ -281,7 +288,7 @@ fn ty_to_string<'tcx>(
281
288
let ty = infcx. resolve_vars_if_possible ( ty) ;
282
289
// We use `fn` ptr syntax for closures, but this only works when the closure does not capture
283
290
// anything. We also remove all type parameters that are fully known to the type system.
284
- let ty = ty. fold_with ( & mut ClosureEraser { infcx, do_not_hide_nested_type : false } ) ;
291
+ let ty = ty. fold_with ( & mut ClosureEraser { infcx } ) ;
285
292
286
293
match ( ty. kind ( ) , called_method_def_id) {
287
294
// We don't want the regular output for `fn`s because it includes its path in
0 commit comments