Auto merge of #93963 - GuillaumeGomez:reduce-clean-type-size, r=notriddle

rustdoc: Reduce clean::Type size

There is no need to keep the `DefId` around since it's allow used to compute if we should show a cast or not. As such, we can simply directly store the boolean.

I think it's not what you had in mind `@camelid` but I guess it's still an improvement? 😉

It was discussed in https://github.com/rust-lang/rust/pull/93941.

r? `@camelid`
This commit is contained in:
bors 2022-05-21 09:04:05 +00:00
commit 5f33adce1b
3 changed files with 220 additions and 213 deletions

View File

@ -379,18 +379,39 @@ impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
}
}
impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
fn clean(&self, cx: &mut DocContext<'_>) -> Type {
let lifted = self.lift_to_tcx(cx.tcx).unwrap();
fn clean_projection<'tcx>(
ty: ty::ProjectionTy<'tcx>,
cx: &mut DocContext<'_>,
def_id: Option<DefId>,
) -> Type {
let lifted = ty.lift_to_tcx(cx.tcx).unwrap();
let trait_ = lifted.trait_ref(cx.tcx).clean(cx);
let self_type = self.self_ty().clean(cx);
let self_type = ty.self_ty().clean(cx);
let self_def_id = if let Some(def_id) = def_id {
cx.tcx.opt_parent(def_id).or(Some(def_id))
} else {
self_type.def_id(&cx.cache)
};
let should_show_cast = compute_should_show_cast(self_def_id, &trait_, &self_type);
Type::QPath {
assoc: Box::new(projection_to_path_segment(*self, cx)),
self_def_id: self_type.def_id(&cx.cache),
assoc: Box::new(projection_to_path_segment(ty, cx)),
should_show_cast,
self_type: box self_type,
trait_,
}
}
impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
fn clean(&self, cx: &mut DocContext<'_>) -> Type {
clean_projection(*self, cx, None)
}
}
fn compute_should_show_cast(self_def_id: Option<DefId>, trait_: &Path, self_type: &Type) -> bool {
!trait_.segments.is_empty()
&& self_def_id
.zip(Some(trait_.def_id()))
.map_or(!self_type.is_self_type(), |(id, trait_)| id != trait_)
}
fn projection_to_path_segment(ty: ty::ProjectionTy<'_>, cx: &mut DocContext<'_>) -> PathSegment {
@ -413,19 +434,7 @@ impl Clean<GenericParamDef> for ty::GenericParamDef {
}
ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
let default = if has_default {
let mut default = cx.tcx.type_of(self.def_id).clean(cx);
// We need to reassign the `self_def_id`, if there's a parent (which is the
// `Self` type), so we can properly render `<Self as X>` casts, because the
// information about which type `Self` is, is only present here, but not in
// the cleaning process of the type itself. To resolve this and have the
// `self_def_id` set, we override it here.
// See https://github.com/rust-lang/rust/issues/85454
if let QPath { ref mut self_def_id, .. } = default {
*self_def_id = Some(cx.tcx.parent(self.def_id));
}
Some(default)
Some(clean_ty(cx.tcx.type_of(self.def_id), cx, Some(self.def_id)))
} else {
None
};
@ -1309,10 +1318,13 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
segments: trait_segments.iter().map(|x| x.clean(cx)).collect(),
};
register_res(cx, trait_.res);
let self_def_id = DefId::local(qself.hir_id.owner.local_def_index);
let self_type = qself.clean(cx);
let should_show_cast = compute_should_show_cast(Some(self_def_id), &trait_, &self_type);
Type::QPath {
assoc: Box::new(p.segments.last().expect("segments were empty").clean(cx)),
self_def_id: Some(DefId::local(qself.hir_id.owner.local_def_index)),
self_type: box qself.clean(cx),
should_show_cast,
self_type: box self_type,
trait_,
}
}
@ -1326,10 +1338,13 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
};
let trait_ = hir::Path { span, res, segments: &[] }.clean(cx);
register_res(cx, trait_.res);
let self_def_id = res.opt_def_id();
let self_type = qself.clean(cx);
let should_show_cast = compute_should_show_cast(self_def_id, &trait_, &self_type);
Type::QPath {
assoc: Box::new(segment.clean(cx)),
self_def_id: res.opt_def_id(),
self_type: box qself.clean(cx),
should_show_cast,
self_type: box self_type,
trait_,
}
}
@ -1515,10 +1530,9 @@ fn normalize<'tcx>(cx: &mut DocContext<'tcx>, ty: Ty<'_>) -> Option<Ty<'tcx>> {
}
}
impl<'tcx> Clean<Type> for Ty<'tcx> {
fn clean(&self, cx: &mut DocContext<'_>) -> Type {
trace!("cleaning type: {:?}", self);
let ty = normalize(cx, *self).unwrap_or(*self);
fn clean_ty<'tcx>(this: Ty<'tcx>, cx: &mut DocContext<'_>, def_id: Option<DefId>) -> Type {
trace!("cleaning type: {:?}", this);
let ty = normalize(cx, this).unwrap_or(this);
match *ty.kind() {
ty::Never => Primitive(PrimitiveType::Never),
ty::Bool => Primitive(PrimitiveType::Bool),
@ -1539,7 +1553,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
BorrowedRef { lifetime: r.clean(cx), mutability: mutbl, type_: box ty.clean(cx) }
}
ty::FnDef(..) | ty::FnPtr(_) => {
let ty = cx.tcx.lift(*self).expect("FnPtr lift failed");
let ty = cx.tcx.lift(this).expect("FnPtr lift failed");
let sig = ty.fn_sig(cx.tcx);
let decl = clean_fn_decl_from_did_and_sig(cx, None, sig);
BareFunction(box BareFunctionDecl {
@ -1572,7 +1586,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
let mut dids = obj.principal_def_id().into_iter().chain(obj.auto_traits());
let did = dids
.next()
.unwrap_or_else(|| panic!("found trait object `{:?}` with no traits?", self));
.unwrap_or_else(|| panic!("found trait object `{:?}` with no traits?", this));
let substs = match obj.principal() {
Some(principal) => principal.skip_binder().substs,
// marker traits have no substs.
@ -1616,7 +1630,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
}
ty::Tuple(t) => Tuple(t.iter().map(|t| t.clean(cx)).collect()),
ty::Projection(ref data) => data.clean(cx),
ty::Projection(ref data) => clean_projection(*data, cx, def_id),
ty::Param(ref p) => {
if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) {
@ -1663,17 +1677,11 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
let bindings: Vec<_> = bounds
.iter()
.filter_map(|bound| {
if let ty::PredicateKind::Projection(proj) =
bound.kind().skip_binder()
{
if proj.projection_ty.trait_ref(cx.tcx)
== trait_ref.skip_binder()
if let ty::PredicateKind::Projection(proj) = bound.kind().skip_binder()
{
if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() {
Some(TypeBinding {
assoc: projection_to_path_segment(
proj.projection_ty,
cx,
),
assoc: projection_to_path_segment(proj.projection_ty, cx),
kind: TypeBindingKind::Equality {
term: proj.term.clean(cx),
},
@ -1706,6 +1714,11 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
ty::Error(_) => panic!("Error"),
}
}
impl<'tcx> Clean<Type> for Ty<'tcx> {
fn clean(&self, cx: &mut DocContext<'_>) -> Type {
clean_ty(*self, cx, None)
}
}
impl<'tcx> Clean<Constant> for ty::Const<'tcx> {

View File

@ -1560,10 +1560,8 @@ pub(crate) enum Type {
QPath {
assoc: Box<PathSegment>,
self_type: Box<Type>,
/// FIXME: This is a hack that should be removed; see [this discussion][1].
///
/// [1]: https://github.com/rust-lang/rust/pull/85479#discussion_r635729093
self_def_id: Option<DefId>,
/// FIXME: compute this field on demand.
should_show_cast: bool,
trait_: Path,
},
@ -1576,7 +1574,7 @@ pub(crate) enum Type {
// `Type` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Type, 80);
rustc_data_structures::static_assert_size!(Type, 72);
impl Type {
/// When comparing types for equality, it can help to ignore `&` wrapping.
@ -2180,7 +2178,7 @@ pub(crate) enum GenericArg {
// `GenericArg` can occur many times in a single `Path`, so make sure it
// doesn't increase in size unexpectedly.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(GenericArg, 88);
rustc_data_structures::static_assert_size!(GenericArg, 80);
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub(crate) enum GenericArgs {

View File

@ -985,11 +985,7 @@ fn fmt_type<'cx>(
write!(f, "impl {}", print_generic_bounds(bounds, cx))
}
}
clean::QPath { ref assoc, ref self_type, ref trait_, ref self_def_id } => {
let should_show_cast = !trait_.segments.is_empty()
&& self_def_id
.zip(Some(trait_.def_id()))
.map_or(!self_type.is_self_type(), |(id, trait_)| id != trait_);
clean::QPath { ref assoc, ref self_type, ref trait_, should_show_cast } => {
if f.alternate() {
if should_show_cast {
write!(f, "<{:#} as {:#}>::", self_type.print(cx), trait_.print(cx))?