From 7b7023cb723775fa20bda42e97dbc44abe7ecb0c Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Sat, 6 Nov 2021 23:10:01 -0700 Subject: [PATCH] rustdoc: Refactor `Impl.{synthetic,blanket_impl}` into enum This change has two advantages: 1. It makes the possible states clearer, and it makes it impossible to construct invalid states, such as a blanket impl that is also an auto trait impl. 2. It shrinks the size of `Impl` a bit, since now there is only one field, rather than two. --- src/librustdoc/clean/auto_trait.rs | 3 +- src/librustdoc/clean/blanket_impl.rs | 3 +- src/librustdoc/clean/inline.rs | 7 ++-- src/librustdoc/clean/mod.rs | 3 +- src/librustdoc/clean/types.rs | 43 ++++++++++++++++++-- src/librustdoc/formats/cache.rs | 2 +- src/librustdoc/html/format.rs | 2 +- src/librustdoc/html/render/mod.rs | 11 +++-- src/librustdoc/html/render/print_item.rs | 2 +- src/librustdoc/html/render/write_shared.rs | 2 +- src/librustdoc/json/conversions.rs | 20 ++++----- src/librustdoc/passes/collect_trait_impls.rs | 4 +- 12 files changed, 66 insertions(+), 36 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 66f9cb45d70..3cac4c148b5 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -121,8 +121,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { for_: ty.clean(self.cx), items: Vec::new(), negative_polarity, - synthetic: true, - blanket_impl: None, + kind: ImplKind::Auto, }), cfg: None, }) diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index a880ce883be..9b80fe0736d 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -124,8 +124,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { .collect::>() .clean(self.cx), negative_polarity: false, - synthetic: false, - blanket_impl: Some(box trait_ref.self_ty().clean(self.cx)), + kind: ImplKind::Blanket(box trait_ref.self_ty().clean(self.cx)), }), cfg: None, }); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index ae7d970f40e..fccb53183ed 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -14,7 +14,9 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; -use crate::clean::{self, utils, Attributes, AttributesExt, ItemId, NestedAttributesExt, Type}; +use crate::clean::{ + self, utils, Attributes, AttributesExt, ImplKind, ItemId, NestedAttributesExt, Type, +}; use crate::core::DocContext; use crate::formats::item_type::ItemType; @@ -496,8 +498,7 @@ crate fn build_impl( for_, items: trait_items, negative_polarity: polarity.clean(cx), - synthetic: false, - blanket_impl: None, + kind: ImplKind::Normal, }), box merged_attrs, cx, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1239d6a0be4..862dfa5e324 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1895,8 +1895,7 @@ fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_> for_, items, negative_polarity: tcx.impl_polarity(def_id).clean(cx), - synthetic: false, - blanket_impl: None, + kind: ImplKind::Normal, }); Item::from_hir_id_and_parts(hir_id, None, kind, cx) }; diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index ae9280c46ff..47895616abc 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -393,8 +393,8 @@ impl Item { }; match kind { ItemKind::ModuleItem(Module { span, .. }) => *span, - ItemKind::ImplItem(Impl { synthetic: true, .. }) => Span::dummy(), - ItemKind::ImplItem(Impl { blanket_impl: Some(_), .. }) => { + ItemKind::ImplItem(Impl { kind: ImplKind::Auto, .. }) => Span::dummy(), + ItemKind::ImplItem(Impl { kind: ImplKind::Blanket(_), .. }) => { if let ItemId::Blanket { impl_id, .. } = self.def_id { rustc_span(impl_id, tcx) } else { @@ -2178,11 +2178,22 @@ crate struct Impl { crate for_: Type, crate items: Vec, crate negative_polarity: bool, - crate synthetic: bool, - crate blanket_impl: Option>, + crate kind: ImplKind, } impl Impl { + crate fn is_auto_impl(&self) -> bool { + self.kind.is_auto() + } + + crate fn is_blanket_impl(&self) -> bool { + self.kind.is_blanket() + } + + crate fn blanket_impl_ty(&self) -> Option<&Type> { + self.kind.as_blanket_ty() + } + crate fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxHashSet { self.trait_ .as_ref() @@ -2192,6 +2203,30 @@ impl Impl { } } +#[derive(Clone, Debug)] +crate enum ImplKind { + Normal, + Auto, + Blanket(Box), +} + +impl ImplKind { + crate fn is_auto(&self) -> bool { + matches!(self, ImplKind::Auto) + } + + crate fn is_blanket(&self) -> bool { + matches!(self, ImplKind::Blanket(_)) + } + + crate fn as_blanket_ty(&self) -> Option<&Type> { + match self { + ImplKind::Blanket(ty) => Some(ty), + _ => None, + } + } +} + #[derive(Clone, Debug)] crate struct Import { crate kind: ImportKind, diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 6b9c9a9669b..2a3998f4f9d 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -228,7 +228,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // Collect all the implementors of traits. if let clean::ImplItem(ref i) = *item.kind { if let Some(trait_) = &i.trait_ { - if i.blanket_impl.is_none() { + if !i.is_blanket_impl() { self.cache .implementors .entry(trait_.def_id()) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index c51bda60b73..5a4ff8dc837 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -997,7 +997,7 @@ impl clean::Impl { write!(f, " for ")?; } - if let Some(ref ty) = self.blanket_impl { + if let Some(ref ty) = self.blanket_impl_ty() { fmt_type(ty, f, use_absolute, cx)?; } else { fmt_type(&self.for_, f, use_absolute, cx)?; diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 25fef114d95..91bd1107d87 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1147,9 +1147,9 @@ fn render_assoc_items_inner( } let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) = - traits.iter().partition(|t| t.inner_impl().synthetic); + traits.iter().partition(|t| t.inner_impl().is_auto_impl()); let (blanket_impl, concrete): (Vec<&&Impl>, _) = - concrete.into_iter().partition(|t| t.inner_impl().blanket_impl.is_some()); + concrete.into_iter().partition(|t| t.inner_impl().is_blanket_impl()); let mut impls = Buffer::empty_from(w); render_impls(cx, &mut impls, &concrete, containing_item); @@ -2058,10 +2058,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { }; let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = - v.iter().partition::, _>(|i| i.inner_impl().synthetic); - let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) = concrete - .into_iter() - .partition::, _>(|i| i.inner_impl().blanket_impl.is_some()); + v.iter().partition::, _>(|i| i.inner_impl().is_auto_impl()); + let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) = + concrete.into_iter().partition::, _>(|i| i.inner_impl().is_blanket_impl()); let concrete_format = format_impls(concrete); let synthetic_format = format_impls(synthetic); diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index d07ef6db4c6..10afe18b33c 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -746,7 +746,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra }); let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) = - local.iter().partition(|i| i.inner_impl().synthetic); + local.iter().partition(|i| i.inner_impl().is_auto_impl()); synthetic.sort_by(|a, b| compare_impl(a, b, cx)); concrete.sort_by(|a, b| compare_impl(a, b, cx)); diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 978701746b7..cf12d668569 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -585,7 +585,7 @@ pub(super) fn write_shared( } else { Some(Implementor { text: imp.inner_impl().print(false, cx).to_string(), - synthetic: imp.inner_impl().synthetic, + synthetic: imp.inner_impl().is_auto_impl(), types: collect_paths_for_type(imp.inner_impl().for_.clone(), cache), }) } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 409d08b3298..94069b99c7d 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -500,21 +500,19 @@ impl FromWithTcx for Trait { impl FromWithTcx for Impl { fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self { let provided_trait_methods = impl_.provided_trait_methods(tcx); - let clean::Impl { - unsafety, - generics, - trait_, - for_, - items, - negative_polarity, - synthetic, - blanket_impl, - } = impl_; + let clean::Impl { unsafety, generics, trait_, for_, items, negative_polarity, kind } = + impl_; // FIXME: should `trait_` be a clean::Path equivalent in JSON? let trait_ = trait_.map(|path| { let did = path.def_id(); clean::ResolvedPath { path, did }.into_tcx(tcx) }); + // FIXME: use something like ImplKind in JSON? + let (synthetic, blanket_impl) = match kind { + clean::ImplKind::Normal => (false, None), + clean::ImplKind::Auto => (true, None), + clean::ImplKind::Blanket(ty) => (false, Some(*ty)), + }; Impl { is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe, generics: generics.into_tcx(tcx), @@ -527,7 +525,7 @@ impl FromWithTcx for Impl { items: ids(items), negative: negative_polarity, synthetic, - blanket_impl: blanket_impl.map(|x| (*x).into_tcx(tcx)), + blanket_impl: blanket_impl.map(|x| x.into_tcx(tcx)), } } } diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 77513b05ff2..ea50134f00d 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -111,12 +111,12 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate } new_items.retain(|it| { - if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind { + if let ImplItem(Impl { ref for_, ref trait_, ref kind, .. }) = *it.kind { cleaner.keep_impl( for_, trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait(), ) || trait_.as_ref().map_or(false, |t| cleaner.keep_impl_with_def_id(t.def_id().into())) - || blanket_impl.is_some() + || kind.is_blanket() } else { true }