Skip to content

Commit 576db13

Browse files
committed
Simplify recursive logic
1 parent 6005619 commit 576db13

File tree

1 file changed

+49
-42
lines changed

1 file changed

+49
-42
lines changed

compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs

+49-42
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use rustc_middle::ty::{
1818
TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults,
1919
};
2020
use rustc_span::{BytePos, DUMMY_SP, FileName, Ident, Span, sym};
21+
use rustc_type_ir::inherent::*;
2122
use rustc_type_ir::visit::TypeVisitableExt;
2223
use tracing::{debug, instrument, warn};
2324

@@ -158,11 +159,6 @@ impl UnderspecifiedArgKind {
158159

159160
struct 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

168164
impl<'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

Comments
 (0)