@@ -18,6 +18,7 @@ use rustc_middle::ty::{
1818 TypeFoldable , TypeFolder , TypeSuperFoldable , TypeckResults ,
1919} ;
2020use rustc_span:: { BytePos , DUMMY_SP , FileName , Ident , Span , sym} ;
21+ use rustc_type_ir:: inherent:: * ;
2122use rustc_type_ir:: visit:: TypeVisitableExt ;
2223use tracing:: { debug, instrument, warn} ;
2324
@@ -158,11 +159,6 @@ impl UnderspecifiedArgKind {
158159
159160struct ClosureEraser < ' a , ' tcx > {
160161 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 ,
166162}
167163
168164impl < ' a , ' tcx > ClosureEraser < ' a , ' tcx > {
@@ -177,8 +173,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'a, 'tcx> {
177173 }
178174
179175 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 ( ) {
176+ match ty. kind ( ) {
182177 ty:: Closure ( _, args) => {
183178 // For a closure type, we turn it into a function pointer so that it gets rendered
184179 // as `fn(args) -> Ret`.
@@ -188,52 +183,64 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'a, 'tcx> {
188183 self . cx ( ) . signature_unclosure ( closure_sig, hir:: Safety :: Safe ) ,
189184 )
190185 }
191- ty:: Adt ( def, _) => {
186+ ty:: Adt ( _, args) if !args. iter ( ) . any ( |a| a. has_infer ( ) ) => {
187+ // We have a type that doesn't have any inference variables, so we replace
188+ // the whole thing with `_`. The type system already knows about this type in
189+ // its entirety and it is redundant to specify it for the user. The user only
190+ // needs to specify the type parameters that we *couldn't* figure out.
191+ self . new_infer ( )
192+ }
193+ ty:: Adt ( def, args) => {
192194 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
210- // the whole thing with `_`. The type system already knows about this type in
211- // its entirety and it is redundant to specify it for the user. The user only
212- // needs to specify the type parameters that we *couldn't* figure out.
213- self . new_infer ( )
214- }
195+ let generics: Vec < bool > = generics
196+ . own_params
197+ . iter ( )
198+ . map ( |param| param. default_value ( self . cx ( ) ) . is_some ( ) )
199+ . collect ( ) ;
200+ let ty = Ty :: new_adt (
201+ self . cx ( ) ,
202+ * def,
203+ self . cx ( ) . mk_args_from_iter ( generics. into_iter ( ) . zip ( args. iter ( ) ) . map (
204+ |( has_default, arg) | {
205+ if arg. has_infer ( ) {
206+ // This param has an unsubstituted type variable, meaning that this
207+ // type has a (potentially deeply nested) type parameter from the
208+ // corresponding type's definition. We have explicitly asked this
209+ // type to not be hidden. In either case, we keep the type and don't
210+ // substitute with `_` just yet.
211+ arg. fold_with ( self )
212+ } else if has_default {
213+ // We have a type param that has a default type, like the allocator
214+ // in Vec. We decided to show `Vec` itself, because it hasn't yet
215+ // been replaced by an `_` `Infer`, but we want to ensure that the
216+ // type parameter with default types does *not* get replaced with
217+ // `_` because then we'd end up with `Vec<_, _>`, instead of
218+ // `Vec<_>`.
219+ arg
220+ } else if let GenericArgKind :: Type ( _) = arg. kind ( ) {
221+ // We don't replace lifetime or const params, only type params.
222+ self . new_infer ( ) . into ( )
223+ } else {
224+ arg. fold_with ( self )
225+ }
226+ } ,
227+ ) ) ,
228+ ) ;
229+ ty
215230 }
216- _ if ty. has_infer ( ) || self . do_not_hide_nested_type => {
231+ _ if ty. has_infer ( ) => {
217232 // This type has a (potentially nested) type parameter that we couldn't figure out.
218233 // 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.
222235 ty. super_fold_with ( self )
223236 }
224237 // We don't have an unknown type parameter anywhere, replace with `_`.
225238 _ => self . new_infer ( ) ,
226- } ;
227- self . do_not_hide_nested_type = prev;
228- ty
239+ }
229240 }
230241
231242 fn fold_const ( & mut self , c : ty:: Const < ' tcx > ) -> ty:: Const < ' tcx > {
232- let prev = self . do_not_hide_nested_type ;
233243 // 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;
237244 c
238245 }
239246}
@@ -281,7 +288,7 @@ fn ty_to_string<'tcx>(
281288 let ty = infcx. resolve_vars_if_possible ( ty) ;
282289 // We use `fn` ptr syntax for closures, but this only works when the closure does not capture
283290 // 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 } ) ;
285292
286293 match ( ty. kind ( ) , called_method_def_id) {
287294 // We don't want the regular output for `fn`s because it includes its path in
0 commit comments