Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustdoc: Reduce clean::Type size #93963

Merged
merged 2 commits into from
May 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 52 additions & 39 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
};
Expand Down Expand Up @@ -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_,
}
}
Expand All @@ -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_,
}
}
Expand Down Expand Up @@ -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),
Expand All @@ -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 {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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),
},
Expand Down Expand Up @@ -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> {
Expand Down
10 changes: 4 additions & 6 deletions src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1560,10 +1560,8 @@ 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,
},

Expand All @@ -1576,7 +1574,7 @@ 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.
Expand Down Expand Up @@ -2180,7 +2178,7 @@ 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)]
crate enum GenericArgs {
Expand Down
6 changes: 1 addition & 5 deletions src/librustdoc/html/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -982,11 +982,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))?
Expand Down