From d91946b3f4ea04bc205b5796fc4af0f13069d204 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Sun, 22 Aug 2021 18:11:16 -0700 Subject: [PATCH 01/16] Remove `Path.global` --- src/librustdoc/clean/inline.rs | 1 - src/librustdoc/clean/mod.rs | 7 +------ src/librustdoc/clean/types.rs | 4 +--- src/librustdoc/clean/utils.rs | 3 +-- 4 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 4a888b22332ee..daff902aaa5d6 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -526,7 +526,6 @@ fn build_module( item.ident.name, clean::ImportSource { path: clean::Path { - global: false, res, segments: vec![clean::PathSegment { name: prim_ty.as_sym(), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 49fc93f3feabc..a7960807f4c15 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1277,7 +1277,6 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { let trait_segments = &segments[..segments.len() - 1]; let trait_def = cx.tcx.associated_item(p.res.def_id()).container.id(); let trait_path = self::Path { - global: p.is_global(), res: Res::Def(DefKind::Trait, trait_def), segments: trait_segments.clean(cx), }; @@ -1728,11 +1727,7 @@ impl Clean for hir::VariantData<'_> { impl Clean for hir::Path<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> Path { - Path { - global: self.is_global(), - res: self.res, - segments: if self.is_global() { &self.segments[1..] } else { &self.segments }.clean(cx), - } + Path { res: self.res, segments: self.segments.clean(cx) } } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 248ff339514ed..7b0d331045c7d 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1967,7 +1967,6 @@ impl Span { #[derive(Clone, PartialEq, Eq, Debug, Hash)] crate struct Path { - crate global: bool, crate res: Res, crate segments: Vec, } @@ -1982,8 +1981,7 @@ impl Path { } crate fn whole_name(&self) -> String { - String::from(if self.global { "::" } else { "" }) - + &self.segments.iter().map(|s| s.name.to_string()).collect::>().join("::") + self.segments.iter().map(|s| s.name.to_string()).collect::>().join("::") } /// Checks if this is a `T::Name` path for an associated type. diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 33d460d587a51..55dfa2711db67 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -148,7 +148,6 @@ pub(super) fn external_path( let def_kind = cx.tcx.def_kind(did); let name = cx.tcx.item_name(did); Path { - global: false, res: Res::Def(def_kind, did), segments: vec![PathSegment { name, @@ -199,7 +198,7 @@ crate fn strip_path(path: &Path) -> Path { }) .collect(); - Path { global: path.global, res: path.res, segments } + Path { res: path.res, segments } } crate fn qpath_to_string(p: &hir::QPath<'_>) -> String { From 4c6385ff935d8121c5cc4c44b62a2b0ae0118a35 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Mon, 23 Aug 2021 21:01:56 -0700 Subject: [PATCH 02/16] Make `Impl.trait_` a `Path`, not a `Type` It should only ever be a `ResolvedPath`, so this (a) enforces that, and (b) reduces the size of `Impl`. I had to update a test because the order of the rendered auto trait impl bounds changed. I think the order changed because rustdoc sorts auto trait bounds using their `Debug` output. --- src/librustdoc/clean/auto_trait.rs | 2 +- src/librustdoc/clean/blanket_impl.rs | 4 +- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 8 ++- src/librustdoc/clean/types.rs | 56 ++++++++++++++------ src/librustdoc/formats/mod.rs | 2 +- src/librustdoc/html/format.rs | 9 ++++ src/librustdoc/html/render/mod.rs | 4 +- src/librustdoc/json/conversions.rs | 7 ++- src/librustdoc/passes/collect_trait_impls.rs | 4 +- 10 files changed, 73 insertions(+), 25 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 1436e51f31820..c83a191baf54f 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -118,7 +118,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { span: Span::dummy(), unsafety: hir::Unsafety::Normal, generics: new_generics, - trait_: Some(trait_ref.clean(self.cx).get_trait_type().unwrap()), + trait_: Some(trait_ref.clean(self.cx).get_trait_type().unwrap().expect_path()), for_: ty.clean(self.cx), items: Vec::new(), negative_polarity, diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 8135d4a2085dd..4385c1adc09fa 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -114,7 +114,9 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { .clean(self.cx), // FIXME(eddyb) compute both `trait_` and `for_` from // the post-inference `trait_ref`, as it's more accurate. - trait_: Some(trait_ref.clean(self.cx).get_trait_type().unwrap()), + trait_: Some( + trait_ref.clean(self.cx).get_trait_type().unwrap().expect_path(), + ), for_: ty.clean(self.cx), items: self .cx diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index daff902aaa5d6..7a08e54d4b141 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -483,7 +483,7 @@ crate fn build_impl( span: clean::types::rustc_span(did, cx.tcx), unsafety: hir::Unsafety::Normal, generics, - trait_, + trait_: trait_.map(|t| t.expect_path()), for_, items: trait_items, negative_polarity: polarity.clean(cx), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a7960807f4c15..21389fa38a870 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -903,6 +903,12 @@ impl Clean for hir::TraitRef<'_> { } } +impl Clean for hir::TraitRef<'_> { + fn clean(&self, cx: &mut DocContext<'_>) -> Path { + self.path.clean(cx) + } +} + impl Clean for hir::PolyTraitRef<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> PolyTrait { PolyTrait { @@ -1902,7 +1908,7 @@ fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_> DefKind::TyAlias => Some(tcx.type_of(did).clean(cx)), _ => None, }); - let mut make_item = |trait_: Option, for_: Type, items: Vec| { + let mut make_item = |trait_: Option, for_: Type, items: Vec| { let kind = ImplItem(Impl { span: types::rustc_span(tcx.hir().local_def_id(hir_id).to_def_id(), tcx), unsafety: impl_.unsafety, diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 7b0d331045c7d..a5f71c4a84955 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1473,6 +1473,15 @@ impl Type { } } + // FIXME: temporary + #[track_caller] + crate fn expect_path(self) -> Path { + match self { + ResolvedPath { path, .. } => path, + _ => panic!("not a ResolvedPath: {:?}", self), + } + } + crate fn is_self_type(&self) -> bool { match *self { Generic(name) => name == kw::SelfUpper, @@ -1481,21 +1490,8 @@ impl Type { } crate fn generics(&self) -> Option> { - match *self { - ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| { - if let GenericArgs::AngleBracketed { ref args, .. } = seg.args { - Some( - args.iter() - .filter_map(|arg| match arg { - GenericArg::Type(ty) => Some(ty), - _ => None, - }) - .collect(), - ) - } else { - None - } - }), + match self { + ResolvedPath { path, .. } => path.generics(), _ => None, } } @@ -1993,6 +1989,34 @@ impl Path { _ => false, } } + + crate fn generics(&self) -> Option> { + self.segments.last().and_then(|seg| { + if let GenericArgs::AngleBracketed { ref args, .. } = seg.args { + Some( + args.iter() + .filter_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + _ => None, + }) + .collect(), + ) + } else { + None + } + }) + } +} + +// FIXME: this is temporary +impl GetDefId for Path { + fn def_id(&self) -> Option { + Some(self.res.def_id()) + } + + fn def_id_full(&self, _: &Cache) -> Option { + self.def_id() + } } #[derive(Clone, PartialEq, Eq, Debug, Hash)] @@ -2136,7 +2160,7 @@ crate struct Impl { crate span: Span, crate unsafety: hir::Unsafety, crate generics: Generics, - crate trait_: Option, + crate trait_: Option, crate for_: Type, crate items: Vec, crate negative_polarity: bool, diff --git a/src/librustdoc/formats/mod.rs b/src/librustdoc/formats/mod.rs index 6060b0560cf3c..86e867d4006aa 100644 --- a/src/librustdoc/formats/mod.rs +++ b/src/librustdoc/formats/mod.rs @@ -14,7 +14,7 @@ use crate::formats::cache::Cache; /// impl. crate enum AssocItemRender<'a> { All, - DerefFor { trait_: &'a clean::Type, type_: &'a clean::Type, deref_mut_: bool }, + DerefFor { trait_: &'a clean::Path, type_: &'a clean::Type, deref_mut_: bool }, } /// For different handling of associated items from the Deref target of a type rather than the type diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index bcd78b2adc085..4338ed7160c10 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -979,6 +979,15 @@ impl clean::Type { } } +impl clean::Path { + crate fn print<'b, 'a: 'b, 'tcx: 'a>( + &'a self, + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'b + Captures<'tcx> { + display_fn(move |f| resolved_path(f, self.res.def_id(), self, false, false, cx)) + } +} + impl clean::Impl { crate fn print<'a, 'tcx: 'a>( &'a self, diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 1f27357f6c6ea..83cd2af169afd 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2056,10 +2056,10 @@ fn sidebar_struct(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, s: &clea fn get_id_for_impl_on_foreign_type( for_: &clean::Type, - trait_: &clean::Type, + trait_: &clean::Path, cx: &Context<'_>, ) -> String { - small_url_encode(format!("impl-{:#}-for-{:#}", trait_.print(cx), for_.print(cx),)) + small_url_encode(format!("impl-{:#}-for-{:#}", trait_.print(cx), for_.print(cx))) } fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String, String)> { diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index ea81b041c3bc6..df9a07499acc4 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -507,6 +507,11 @@ impl FromWithTcx for Impl { blanket_impl, span: _span, } = impl_; + // FIXME: should `trait_` be a Path in JSON? + let trait_ = trait_.map(|path| { + let did = path.res.def_id(); + clean::ResolvedPath { path, did }.into_tcx(tcx) + }); Impl { is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe, generics: generics.into_tcx(tcx), @@ -514,7 +519,7 @@ impl FromWithTcx for Impl { .into_iter() .map(|x| x.to_string()) .collect(), - trait_: trait_.map(|x| x.into_tcx(tcx)), + trait_, for_: for_.into_tcx(tcx), items: ids(items), negative: negative_polarity, diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index eefe50caa345e..e8aa37c8868d8 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -78,7 +78,9 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { new_items.retain(|it| { if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind { cleaner.keep_impl(for_) - || trait_.as_ref().map_or(false, |t| cleaner.keep_impl(t)) + || trait_ + .as_ref() + .map_or(false, |t| cleaner.keep_impl_with_def_id(t.res.def_id().into())) || blanket_impl.is_some() } else { true From 91d3b7201e239c9966d43c0eaf1a4b636b0e06a8 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Tue, 24 Aug 2021 10:15:19 -0700 Subject: [PATCH 03/16] Use `Path` instead of `Type` in `PolyTrait` The change to `impl Clean for hir::TraitRef<'_>` was necessary to fix a test failure for `src/test/rustdoc/trait-alias-mention.rs`. Here's why: The old code path was through `impl Clean for hir::TraitRef<'_>`, which called `resolve_type`, which in turn called `register_res`. Now, because `PolyTrait` uses a `Path` instead of a `Type`, the impl of `Clean` was being run, which did not call `register_res`, causing the trait alias to not be recorded in the `external_paths` cache. --- src/librustdoc/clean/auto_trait.rs | 208 +++++++++++---------------- src/librustdoc/clean/blanket_impl.rs | 4 +- src/librustdoc/clean/inline.rs | 44 +++--- src/librustdoc/clean/mod.rs | 31 ++-- src/librustdoc/clean/simplify.rs | 8 +- src/librustdoc/clean/types.rs | 49 +++---- src/librustdoc/clean/utils.rs | 36 +---- src/librustdoc/html/format.rs | 66 ++++----- src/librustdoc/html/render/cache.rs | 16 +-- src/librustdoc/html/render/mod.rs | 20 +-- src/librustdoc/json/conversions.rs | 32 +++-- 11 files changed, 208 insertions(+), 306 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index c83a191baf54f..fe3edd4112bce 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -118,7 +118,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { span: Span::dummy(), unsafety: hir::Unsafety::Normal, generics: new_generics, - trait_: Some(trait_ref.clean(self.cx).get_trait_type().unwrap().expect_path()), + trait_: Some(trait_ref.clean(self.cx).get_trait_path().unwrap()), for_: ty.clean(self.cx), items: Vec::new(), negative_polarity, @@ -353,48 +353,35 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { if let Some(data) = ty_to_fn.get(&ty) { let (poly_trait, output) = (data.0.as_ref().unwrap().clone(), data.1.as_ref().cloned().map(Box::new)); - let new_ty = match poly_trait.trait_ { - Type::ResolvedPath { ref path, ref did } => { - let mut new_path = path.clone(); - let last_segment = - new_path.segments.pop().expect("segments were empty"); - - let (old_input, old_output) = match last_segment.args { - GenericArgs::AngleBracketed { args, .. } => { - let types = args - .iter() - .filter_map(|arg| match arg { - GenericArg::Type(ty) => Some(ty.clone()), - _ => None, - }) - .collect(); - (types, None) - } - GenericArgs::Parenthesized { inputs, output, .. } => { - (inputs, output) - } - }; + let mut new_path = poly_trait.trait_.clone(); + let last_segment = new_path.segments.pop().expect("segments were empty"); + + let (old_input, old_output) = match last_segment.args { + GenericArgs::AngleBracketed { args, .. } => { + let types = args + .iter() + .filter_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty.clone()), + _ => None, + }) + .collect(); + (types, None) + } + GenericArgs::Parenthesized { inputs, output } => (inputs, output), + }; - if old_output.is_some() && old_output != output { - panic!( - "Output mismatch for {:?} {:?} {:?}", - ty, old_output, data.1 - ); - } + if old_output.is_some() && old_output != output { + panic!("Output mismatch for {:?} {:?} {:?}", ty, old_output, data.1); + } - let new_params = - GenericArgs::Parenthesized { inputs: old_input, output }; + let new_params = GenericArgs::Parenthesized { inputs: old_input, output }; - new_path - .segments - .push(PathSegment { name: last_segment.name, args: new_params }); + new_path + .segments + .push(PathSegment { name: last_segment.name, args: new_params }); - Type::ResolvedPath { path: new_path, did: *did } - } - _ => panic!("Unexpected data: {:?}, {:?}", ty, data), - }; bounds.insert(GenericBound::TraitBound( - PolyTrait { trait_: new_ty, generic_params: poly_trait.generic_params }, + PolyTrait { trait_: new_path, generic_params: poly_trait.generic_params }, hir::TraitBoundModifier::None, )); } @@ -476,7 +463,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { let mut has_sized = FxHashSet::default(); let mut ty_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default(); let mut lifetime_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default(); - let mut ty_to_traits: FxHashMap> = Default::default(); + let mut ty_to_traits: FxHashMap> = Default::default(); let mut ty_to_fn: FxHashMap, Option)> = Default::default(); @@ -511,11 +498,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { if b.is_sized_bound(self.cx) { has_sized.insert(ty.clone()); } else if !b - .get_trait_type() - .and_then(|t| { + .get_trait_path() + .and_then(|trait_| { ty_to_traits .get(&ty) - .map(|bounds| bounds.contains(&strip_type(t.clone()))) + .map(|bounds| bounds.contains(&strip_path(trait_.clone()))) }) .unwrap_or(false) { @@ -532,7 +519,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // that we don't end up with duplicate bounds (e.g., for<'b, 'b>) for_generics.extend(p.generic_params.clone()); p.generic_params = for_generics.into_iter().collect(); - self.is_fn_ty(&p.trait_) + self.is_fn_trait(&p.trait_) } _ => false, }; @@ -558,78 +545,59 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { match lhs { Type::QPath { name: left_name, ref self_type, ref trait_, .. } => { let ty = &*self_type; - match **trait_ { - Type::ResolvedPath { path: ref trait_path, ref did } => { - let mut new_trait_path = trait_path.clone(); - - if self.is_fn_ty(trait_) && left_name == sym::Output { - ty_to_fn - .entry(*ty.clone()) - .and_modify(|e| *e = (e.0.clone(), Some(rhs.clone()))) - .or_insert((None, Some(rhs))); - continue; - } - - let args = &mut new_trait_path - .segments - .last_mut() - .expect("segments were empty") - .args; - - match args { - // Convert something like ' = u8' - // to 'T: Iterator' - GenericArgs::AngleBracketed { - ref mut bindings, .. - } => { - bindings.push(TypeBinding { - name: left_name, - kind: TypeBindingKind::Equality { ty: rhs }, - }); - } - GenericArgs::Parenthesized { .. } => { - existing_predicates.push(WherePredicate::EqPredicate { - lhs: lhs.clone(), - rhs, - }); - continue; // If something other than a Fn ends up - // with parenthesis, leave it alone - } - } - - let bounds = ty_to_bounds.entry(*ty.clone()).or_default(); - - bounds.insert(GenericBound::TraitBound( - PolyTrait { - trait_: Type::ResolvedPath { - path: new_trait_path, - did: *did, - }, - generic_params: Vec::new(), - }, - hir::TraitBoundModifier::None, - )); - - // Remove any existing 'plain' bound (e.g., 'T: Iterator`) so - // that we don't see a - // duplicate bound like `T: Iterator + Iterator` - // on the docs page. - bounds.remove(&GenericBound::TraitBound( - PolyTrait { - trait_: *trait_.clone(), - generic_params: Vec::new(), - }, - hir::TraitBoundModifier::None, - )); - // Avoid creating any new duplicate bounds later in the outer - // loop - ty_to_traits - .entry(*ty.clone()) - .or_default() - .insert(*trait_.clone()); + let mut new_trait = *trait_.clone(); + + if self.is_fn_trait(trait_) && left_name == sym::Output { + ty_to_fn + .entry(*ty.clone()) + .and_modify(|e| *e = (e.0.clone(), Some(rhs.clone()))) + .or_insert((None, Some(rhs))); + continue; + } + + let args = &mut new_trait + .segments + .last_mut() + .expect("segments were empty") + .args; + + match args { + // Convert something like ' = u8' + // to 'T: Iterator' + GenericArgs::AngleBracketed { ref mut bindings, .. } => { + bindings.push(TypeBinding { + name: left_name, + kind: TypeBindingKind::Equality { ty: rhs }, + }); + } + GenericArgs::Parenthesized { .. } => { + existing_predicates.push(WherePredicate::EqPredicate { + lhs: lhs.clone(), + rhs, + }); + continue; // If something other than a Fn ends up + // with parenthesis, leave it alone } - _ => panic!("Unexpected trait {:?} for {:?}", trait_, item_def_id), } + + let bounds = ty_to_bounds.entry(*ty.clone()).or_default(); + + bounds.insert(GenericBound::TraitBound( + PolyTrait { trait_: new_trait, generic_params: Vec::new() }, + hir::TraitBoundModifier::None, + )); + + // Remove any existing 'plain' bound (e.g., 'T: Iterator`) so + // that we don't see a + // duplicate bound like `T: Iterator + Iterator` + // on the docs page. + bounds.remove(&GenericBound::TraitBound( + PolyTrait { trait_: *trait_.clone(), generic_params: Vec::new() }, + hir::TraitBoundModifier::None, + )); + // Avoid creating any new duplicate bounds later in the outer + // loop + ty_to_traits.entry(*ty.clone()).or_default().insert(*trait_.clone()); } _ => panic!("Unexpected LHS {:?} for {:?}", lhs, item_def_id), } @@ -721,16 +689,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { vec.sort_by_cached_key(|x| format!("{:?}", x)) } - fn is_fn_ty(&self, ty: &Type) -> bool { + fn is_fn_trait(&self, path: &Path) -> bool { let tcx = self.cx.tcx; - match ty { - &Type::ResolvedPath { did, .. } => { - did == tcx.require_lang_item(LangItem::Fn, None) - || did == tcx.require_lang_item(LangItem::FnMut, None) - || did == tcx.require_lang_item(LangItem::FnOnce, None) - } - _ => false, - } + let did = path.res.def_id(); + did == tcx.require_lang_item(LangItem::Fn, None) + || did == tcx.require_lang_item(LangItem::FnMut, None) + || did == tcx.require_lang_item(LangItem::FnOnce, None) } } diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 4385c1adc09fa..410b6a42d7610 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -114,9 +114,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { .clean(self.cx), // FIXME(eddyb) compute both `trait_` and `for_` from // the post-inference `trait_ref`, as it's more accurate. - trait_: Some( - trait_ref.clean(self.cx).get_trait_type().unwrap().expect_path(), - ), + trait_: Some(trait_ref.clean(self.cx).get_trait_path().unwrap()), for_: ty.clean(self.cx), items: self .cx diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 7a08e54d4b141..bee10e72fa056 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -455,11 +455,20 @@ crate fn build_impl( } // Return if the trait itself or any types of the generic parameters are doc(hidden). - let mut stack: Vec<&Type> = trait_.iter().collect(); - stack.push(&for_); + let mut stack: Vec<&Type> = vec![&for_]; + + if let Some(did) = trait_.as_ref().map(|t| t.res.def_id()) { + if tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden) { + return; + } + } + if let Some(generics) = trait_.as_ref().and_then(|t| t.generics()) { + stack.extend(generics); + } + while let Some(ty) = stack.pop() { if let Some(did) = ty.def_id() { - if cx.tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden) { + if tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden) { return; } } @@ -468,8 +477,8 @@ crate fn build_impl( } } - if let Some(trait_did) = trait_.def_id() { - record_extern_trait(cx, trait_did); + if let Some(did) = trait_.as_ref().map(|t| t.res.def_id()) { + record_extern_trait(cx, did); } let (merged_attrs, cfg) = merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs); @@ -483,7 +492,7 @@ crate fn build_impl( span: clean::types::rustc_span(did, cx.tcx), unsafety: hir::Unsafety::Normal, generics, - trait_: trait_.map(|t| t.expect_path()), + trait_, for_, items: trait_items, negative_polarity: polarity.clean(cx), @@ -620,11 +629,10 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean: ref mut bounds, .. } if *s == kw::SelfUpper => { - bounds.retain(|bound| match *bound { - clean::GenericBound::TraitBound( - clean::PolyTrait { trait_: clean::ResolvedPath { did, .. }, .. }, - _, - ) => did != trait_did, + bounds.retain(|bound| match bound { + clean::GenericBound::TraitBound(clean::PolyTrait { trait_, .. }, _) => { + trait_.res.def_id() != trait_did + } _ => true, }); } @@ -632,18 +640,12 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean: } } - g.where_predicates.retain(|pred| match *pred { + g.where_predicates.retain(|pred| match pred { clean::WherePredicate::BoundPredicate { - ty: - clean::QPath { - self_type: box clean::Generic(ref s), - trait_: box clean::ResolvedPath { did, .. }, - name: ref _name, - .. - }, - ref bounds, + ty: clean::QPath { self_type: box clean::Generic(ref s), trait_, name: _, .. }, + bounds, .. - } => !(bounds.is_empty() || *s == kw::SelfUpper && did == trait_did), + } => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.res.def_id() == trait_did), _ => true, }); g diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 21389fa38a870..285314a5cb612 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -152,8 +152,8 @@ impl Clean for hir::GenericBound<'_> { } } -impl Clean for (ty::TraitRef<'_>, &[TypeBinding]) { - fn clean(&self, cx: &mut DocContext<'_>) -> Type { +impl Clean for (ty::TraitRef<'_>, &[TypeBinding]) { + fn clean(&self, cx: &mut DocContext<'_>) -> Path { let (trait_ref, bounds) = *self; let kind = cx.tcx.def_kind(trait_ref.def_id).into(); if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) { @@ -168,7 +168,7 @@ impl Clean for (ty::TraitRef<'_>, &[TypeBinding]) { debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs); - ResolvedPath { path, did: trait_ref.def_id } + path } } @@ -905,7 +905,9 @@ impl Clean for hir::TraitRef<'_> { impl Clean for hir::TraitRef<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> Path { - self.path.clean(cx) + let path = self.path.clean(cx); + register_res(cx, path.res); + path } } @@ -1111,9 +1113,8 @@ impl Clean for ty::AssocItem { if *name != my_name { return None; } - match **trait_ { - ResolvedPath { did, .. } if did == self.container.id() => {} - _ => return None, + if trait_.res.def_id() != self.container.id() { + return None; } match **self_type { Generic(ref s) if *s == kw::SelfUpper => {} @@ -1286,11 +1287,12 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { res: Res::Def(DefKind::Trait, trait_def), segments: trait_segments.clean(cx), }; + register_res(cx, trait_path.res); Type::QPath { name: p.segments.last().expect("segments were empty").ident.name, self_def_id: Some(DefId::local(qself.hir_id.owner.local_def_index)), self_type: box qself.clean(cx), - trait_: box resolve_type(cx, trait_path), + trait_: box trait_path, } } hir::QPath::TypeRelative(ref qself, ref segment) => { @@ -1302,11 +1304,12 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { _ => bug!("clean: expected associated type, found `{:?}`", ty), }; let trait_path = hir::Path { span, res, segments: &[] }.clean(cx); + register_res(cx, trait_path.res); Type::QPath { name: segment.ident.name, self_def_id: res.opt_def_id(), self_type: box qself.clean(cx), - trait_: box resolve_type(cx, trait_path), + trait_: box trait_path, } } hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"), @@ -1475,10 +1478,7 @@ impl<'tcx> Clean for Ty<'tcx> { let empty = cx.tcx.intern_substs(&[]); let path = external_path(cx, did, false, vec![], empty); inline::record_extern_fqn(cx, did, ItemType::Trait); - let bound = PolyTrait { - trait_: ResolvedPath { path, did }, - generic_params: Vec::new(), - }; + let bound = PolyTrait { trait_: path, generic_params: Vec::new() }; bounds.push(bound); } @@ -1491,10 +1491,7 @@ impl<'tcx> Clean for Ty<'tcx> { } let path = external_path(cx, did, false, bindings, substs); - bounds.insert( - 0, - PolyTrait { trait_: ResolvedPath { path, did }, generic_params: Vec::new() }, - ); + bounds.insert(0, PolyTrait { trait_: path, generic_params: Vec::new() }); DynTrait(bounds, lifetime) } diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 257af6ab91016..101fdd465b70d 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -99,17 +99,13 @@ crate fn merge_bounds( clean::GenericBound::TraitBound(ref mut tr, _) => tr, clean::GenericBound::Outlives(..) => return false, }; - let (did, path) = match trait_ref.trait_ { - clean::ResolvedPath { did, ref mut path, .. } => (did, path), - _ => return false, - }; // If this QPath's trait `trait_did` is the same as, or a supertrait // of, the bound's trait `did` then we can keep going, otherwise // this is just a plain old equality bound. - if !trait_is_same_or_supertrait(cx, did, trait_did) { + if !trait_is_same_or_supertrait(cx, trait_ref.trait_.res.def_id(), trait_did) { return false; } - let last = path.segments.last_mut().expect("segments were empty"); + let last = trait_ref.trait_.segments.last_mut().expect("segments were empty"); match last.args { PP::AngleBracketed { ref mut bindings, .. } => { bindings.push(clean::TypeBinding { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index a5f71c4a84955..da06737394d53 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1114,7 +1114,7 @@ impl GenericBound { let path = external_path(cx, did, false, vec![], empty); inline::record_extern_fqn(cx, did, ItemType::Trait); GenericBound::TraitBound( - PolyTrait { trait_: ResolvedPath { path, did }, generic_params: Vec::new() }, + PolyTrait { trait_: path, generic_params: Vec::new() }, hir::TraitBoundModifier::Maybe, ) } @@ -1136,7 +1136,7 @@ impl GenericBound { None } - crate fn get_trait_type(&self) -> Option { + crate fn get_trait_path(&self) -> Option { if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self { Some(trait_.clone()) } else { @@ -1368,7 +1368,7 @@ crate struct TraitAlias { /// A trait reference, which may have higher ranked lifetimes. #[derive(Clone, PartialEq, Eq, Debug, Hash)] crate struct PolyTrait { - crate trait_: Type, + crate trait_: Path, crate generic_params: Vec, } @@ -1408,7 +1408,8 @@ crate enum Type { name: Symbol, self_type: Box, self_def_id: Option, - trait_: Box, + // FIXME: remove this `Box`; it's unnecessary + trait_: Box, }, // `_` @@ -1473,15 +1474,6 @@ impl Type { } } - // FIXME: temporary - #[track_caller] - crate fn expect_path(self) -> Path { - match self { - ResolvedPath { path, .. } => path, - _ => panic!("not a ResolvedPath: {:?}", self), - } - } - crate fn is_self_type(&self) -> bool { match *self { Generic(name) => name == kw::SelfUpper, @@ -1496,19 +1488,6 @@ impl Type { } } - crate fn bindings(&self) -> Option<&[TypeBinding]> { - match *self { - ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| { - if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args { - Some(&**bindings) - } else { - None - } - }), - _ => None, - } - } - crate fn is_full_generic(&self) -> bool { matches!(self, Type::Generic(_)) } @@ -1522,17 +1501,13 @@ impl Type { QPath { self_type, trait_, name, .. } => (self_type, trait_, name), _ => return None, }; - let trait_did = match **trait_ { - ResolvedPath { did, .. } => did, - _ => return None, - }; - Some((&self_, trait_did, *name)) + Some((&self_, trait_.res.def_id(), *name)) } fn inner_def_id(&self, cache: Option<&Cache>) -> Option { let t: PrimitiveType = match *self { ResolvedPath { did, .. } => return Some(did), - DynTrait(ref bounds, _) => return bounds[0].trait_.inner_def_id(cache), + DynTrait(ref bounds, _) => return Some(bounds[0].trait_.res.def_id()), Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()), BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference, BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache), @@ -2006,6 +1981,16 @@ impl Path { } }) } + + crate fn bindings(&self) -> Option<&[TypeBinding]> { + self.segments.last().and_then(|seg| { + if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args { + Some(&**bindings) + } else { + None + } + }) + } } // FIXME: this is temporary diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 55dfa2711db67..487efdc060f09 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -2,7 +2,7 @@ use crate::clean::auto_trait::AutoTraitFinder; use crate::clean::blanket_impl::BlanketImplFinder; use crate::clean::{ inline, Clean, Crate, ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item, - ItemKind, Lifetime, Path, PathSegment, PolyTrait, Primitive, PrimitiveType, ResolvedPath, Type, + ItemKind, Lifetime, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding, Visibility, }; use crate::core::DocContext; @@ -156,39 +156,7 @@ pub(super) fn external_path( } } -crate fn strip_type(ty: Type) -> Type { - match ty { - Type::ResolvedPath { path, did } => Type::ResolvedPath { path: strip_path(&path), did }, - Type::DynTrait(mut bounds, lt) => { - let first = bounds.remove(0); - let stripped_trait = strip_type(first.trait_); - - bounds.insert( - 0, - PolyTrait { trait_: stripped_trait, generic_params: first.generic_params }, - ); - Type::DynTrait(bounds, lt) - } - Type::Tuple(inner_tys) => { - Type::Tuple(inner_tys.iter().map(|t| strip_type(t.clone())).collect()) - } - Type::Slice(inner_ty) => Type::Slice(Box::new(strip_type(*inner_ty))), - Type::Array(inner_ty, s) => Type::Array(Box::new(strip_type(*inner_ty)), s), - Type::RawPointer(m, inner_ty) => Type::RawPointer(m, Box::new(strip_type(*inner_ty))), - Type::BorrowedRef { lifetime, mutability, type_ } => { - Type::BorrowedRef { lifetime, mutability, type_: Box::new(strip_type(*type_)) } - } - Type::QPath { name, self_type, trait_, self_def_id } => Type::QPath { - name, - self_def_id, - self_type: Box::new(strip_type(*self_type)), - trait_: Box::new(strip_type(*trait_)), - }, - _ => ty, - } -} - -crate fn strip_path(path: &Path) -> Path { +crate fn strip_path(path: Path) -> Path { let segments = path .segments .iter() diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 4338ed7160c10..7093bcf6adf1c 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -18,9 +18,7 @@ use rustc_middle::ty::TyCtxt; use rustc_span::def_id::CRATE_DEF_INDEX; use rustc_target::spec::abi::Abi; -use crate::clean::{ - self, utils::find_nearest_parent_module, ExternalCrate, GetDefId, ItemId, PrimitiveType, -}; +use crate::clean::{self, utils::find_nearest_parent_module, ExternalCrate, ItemId, PrimitiveType}; use crate::formats::item_type::ItemType; use crate::html::escape::Escape; use crate::html::render::cache::ExternalLocation; @@ -914,15 +912,10 @@ fn fmt_type<'cx>( } } clean::QPath { ref name, ref self_type, ref trait_, ref self_def_id } => { - let should_show_cast = match *trait_ { - box clean::ResolvedPath { ref path, .. } => { - !path.segments.is_empty() - && self_def_id - .zip(trait_.def_id()) - .map_or(!self_type.is_self_type(), |(id, trait_)| id != trait_) - } - _ => true, - }; + let should_show_cast = !trait_.segments.is_empty() + && self_def_id + .zip(Some(trait_.res.def_id())) + .map_or(!self_type.is_self_type(), |(id, trait_)| id != trait_); if f.alternate() { if should_show_cast { write!(f, "<{:#} as {:#}>::", self_type.print(cx), trait_.print(cx))? @@ -936,36 +929,31 @@ fn fmt_type<'cx>( write!(f, "{}::", self_type.print(cx))? } }; - match *trait_ { - // It's pretty unsightly to look at `::C` in output, and - // we've got hyperlinking on our side, so try to avoid longer - // notation as much as possible by making `C` a hyperlink to trait - // `B` to disambiguate. - // - // FIXME: this is still a lossy conversion and there should probably - // be a better way of representing this in general? Most of - // the ugliness comes from inlining across crates where - // everything comes in as a fully resolved QPath (hard to - // look at). - box clean::ResolvedPath { did, .. } => { - match href(did, cx) { - Ok((ref url, _, ref path)) if !f.alternate() => { - write!( - f, - "::C` in output, and + // we've got hyperlinking on our side, so try to avoid longer + // notation as much as possible by making `C` a hyperlink to trait + // `B` to disambiguate. + // + // FIXME: this is still a lossy conversion and there should probably + // be a better way of representing this in general? Most of + // the ugliness comes from inlining across crates where + // everything comes in as a fully resolved QPath (hard to + // look at). + match href(trait_.res.def_id(), cx) { + Ok((ref url, _, ref path)) if !f.alternate() => { + write!( + f, + "{name}", - url = url, - shortty = ItemType::AssocType, - name = name, - path = path.join("::") - )?; - } - _ => write!(f, "{}", name)?, - } - Ok(()) + url = url, + shortty = ItemType::AssocType, + name = name, + path = path.join("::") + )?; } - _ => write!(f, "{}", name), + _ => write!(f, "{}", name)?, } + Ok(()) } } } diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index edd1d8b98fc64..7336b8b41ac16 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -226,16 +226,13 @@ fn get_index_type(clean_type: &clean::Type) -> RenderType { fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option { match *clean_type { clean::ResolvedPath { ref path, .. } => { - let segments = &path.segments; - let path_segment = segments.iter().last().unwrap_or_else(|| { - panic!( - "get_index_type_name(clean_type: {:?}, accept_generic: {:?}) had length zero path", - clean_type, accept_generic - ) - }); + let path_segment = path.segments.last().unwrap(); Some(path_segment.name) } - clean::DynTrait(ref bounds, _) => get_index_type_name(&bounds[0].trait_, accept_generic), + clean::DynTrait(ref bounds, _) => { + let path = &bounds[0].trait_; + Some(path.segments.last().unwrap().name) + } clean::Generic(s) if accept_generic => Some(s), clean::Primitive(ref p) => Some(p.as_sym()), clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_, accept_generic), @@ -324,7 +321,8 @@ crate fn get_real_types<'tcx>( } if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) { for bound in bound.get_bounds().unwrap_or(&[]) { - if let Some(ty) = bound.get_trait_type() { + if let Some(path) = bound.get_trait_path() { + let ty = Type::ResolvedPath { did: path.res.def_id(), path }; let adds = get_real_types(generics, &ty, tcx, recurse + 1, res); nb_added += adds; if adds == 0 && !ty.is_full_generic() { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 83cd2af169afd..7423699900319 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2370,6 +2370,15 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec { let mut visited = FxHashSet::default(); let mut work = VecDeque::new(); + let mut process_path = |did: DefId| { + let get_extern = || cache.external_paths.get(&did).map(|s| s.0.clone()); + let fqp = cache.exact_paths.get(&did).cloned().or_else(get_extern); + + if let Some(path) = fqp { + out.push(path.join("::")); + } + }; + work.push_back(first_ty); while let Some(ty) = work.pop_front() { @@ -2378,14 +2387,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec { } match ty { - clean::Type::ResolvedPath { did, .. } => { - let get_extern = || cache.external_paths.get(&did).map(|s| s.0.clone()); - let fqp = cache.exact_paths.get(&did).cloned().or_else(get_extern); - - if let Some(path) = fqp { - out.push(path.join("::")); - } - } + clean::Type::ResolvedPath { did, .. } => process_path(did), clean::Type::Tuple(tys) => { work.extend(tys.into_iter()); } @@ -2403,7 +2405,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec { } clean::Type::QPath { self_type, trait_, .. } => { work.push_back(*self_type); - work.push_back(*trait_); + process_path(trait_.res.def_id()); } _ => {} } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index df9a07499acc4..10320baaf93d0 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -363,8 +363,11 @@ impl FromWithTcx for GenericBound { use clean::GenericBound::*; match bound { TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => { + // FIXME: should `trait_` be a clean::Path equivalent in JSON? + let trait_ = + clean::ResolvedPath { did: trait_.res.def_id(), path: trait_ }.into_tcx(tcx); GenericBound::TraitBound { - trait_: trait_.into_tcx(tcx), + trait_, generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(), modifier: from_trait_bound_modifier(modifier), } @@ -394,15 +397,12 @@ impl FromWithTcx for Type { param_names: Vec::new(), }, DynTrait(mut bounds, lt) => { - let (path, id) = match bounds.remove(0).trait_ { - ResolvedPath { path, did, .. } => (path, did), - _ => unreachable!(), - }; + let first_trait = bounds.remove(0).trait_; Type::ResolvedPath { - name: path.whole_name(), - id: from_item_id(id.into()), - args: path + name: first_trait.whole_name(), + id: from_item_id(first_trait.res.def_id().into()), + args: first_trait .segments .last() .map(|args| Box::new(args.clone().args.into_tcx(tcx))), @@ -434,11 +434,15 @@ impl FromWithTcx for Type { mutable: mutability == ast::Mutability::Mut, type_: Box::new((*type_).into_tcx(tcx)), }, - QPath { name, self_type, trait_, .. } => Type::QualifiedPath { - name: name.to_string(), - self_type: Box::new((*self_type).into_tcx(tcx)), - trait_: Box::new((*trait_).into_tcx(tcx)), - }, + QPath { name, self_type, trait_, .. } => { + // FIXME: should `trait_` be a clean::Path equivalent in JSON? + let trait_ = ResolvedPath { did: trait_.res.def_id(), path: *trait_ }.into_tcx(tcx); + Type::QualifiedPath { + name: name.to_string(), + self_type: Box::new((*self_type).into_tcx(tcx)), + trait_: Box::new(trait_), + } + } } } } @@ -507,7 +511,7 @@ impl FromWithTcx for Impl { blanket_impl, span: _span, } = impl_; - // FIXME: should `trait_` be a Path in JSON? + // FIXME: should `trait_` be a clean::Path equivalent in JSON? let trait_ = trait_.map(|path| { let did = path.res.def_id(); clean::ResolvedPath { path, did }.into_tcx(tcx) From b8351c30e4c96e7cea91edc169a404c3c66ebff7 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Thu, 26 Aug 2021 17:32:54 -0700 Subject: [PATCH 04/16] Avoid unnecessary matches by changing `Clean` impl --- src/librustdoc/clean/auto_trait.rs | 2 +- src/librustdoc/clean/blanket_impl.rs | 2 +- src/librustdoc/clean/inline.rs | 5 +---- src/librustdoc/clean/mod.rs | 14 ++++---------- 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index fe3edd4112bce..cbc010698c7d4 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -118,7 +118,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { span: Span::dummy(), unsafety: hir::Unsafety::Normal, generics: new_generics, - trait_: Some(trait_ref.clean(self.cx).get_trait_path().unwrap()), + trait_: Some(trait_ref.clean(self.cx)), for_: ty.clean(self.cx), items: Vec::new(), negative_polarity, diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 410b6a42d7610..340d9f311b150 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -114,7 +114,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { .clean(self.cx), // FIXME(eddyb) compute both `trait_` and `for_` from // the post-inference `trait_ref`, as it's more accurate. - trait_: Some(trait_ref.clean(self.cx).get_trait_path().unwrap()), + trait_: Some(trait_ref.clean(self.cx)), for_: ty.clean(self.cx), items: self .cx diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index bee10e72fa056..d1ee257fb3284 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -446,10 +446,7 @@ crate fn build_impl( ), }; let polarity = tcx.impl_polarity(did); - let trait_ = associated_trait.clean(cx).map(|bound| match bound { - clean::GenericBound::TraitBound(polyt, _) => polyt.trait_, - clean::GenericBound::Outlives(..) => unreachable!(), - }); + let trait_ = associated_trait.clean(cx); if trait_.def_id() == tcx.lang_items().deref_trait() { super::build_deref_target_impls(cx, &trait_items, ret); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 285314a5cb612..3c10fadeff368 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -172,12 +172,9 @@ impl Clean for (ty::TraitRef<'_>, &[TypeBinding]) { } } -impl<'tcx> Clean for ty::TraitRef<'tcx> { - fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound { - GenericBound::TraitBound( - PolyTrait { trait_: (*self, &[][..]).clean(cx), generic_params: vec![] }, - hir::TraitBoundModifier::None, - ) +impl Clean for ty::TraitRef<'tcx> { + fn clean(&self, cx: &mut DocContext<'_>) -> Path { + (*self, &[][..]).clean(cx) } } @@ -384,10 +381,7 @@ impl<'tcx> Clean for ty::ProjectionPredicate<'tcx> { impl<'tcx> Clean for ty::ProjectionTy<'tcx> { fn clean(&self, cx: &mut DocContext<'_>) -> Type { let lifted = self.lift_to_tcx(cx.tcx).unwrap(); - let trait_ = match lifted.trait_ref(cx.tcx).clean(cx) { - GenericBound::TraitBound(t, _) => t.trait_, - GenericBound::Outlives(_) => panic!("cleaning a trait got a lifetime"), - }; + let trait_ = lifted.trait_ref(cx.tcx).clean(cx); let self_type = self.self_ty().clean(cx); Type::QPath { name: cx.tcx.associated_item(self.item_def_id).ident.name, From e20bb157a2b2f413c187ab33ddc626a3e69adff8 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Thu, 26 Aug 2021 17:36:48 -0700 Subject: [PATCH 05/16] Remove unnecessary `Box` in `Type::QPath` --- src/librustdoc/clean/auto_trait.rs | 6 +++--- src/librustdoc/clean/mod.rs | 14 +++++++------- src/librustdoc/clean/types.rs | 3 +-- src/librustdoc/json/conversions.rs | 2 +- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index cbc010698c7d4..20fb91eba39a1 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -545,7 +545,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { match lhs { Type::QPath { name: left_name, ref self_type, ref trait_, .. } => { let ty = &*self_type; - let mut new_trait = *trait_.clone(); + let mut new_trait = trait_.clone(); if self.is_fn_trait(trait_) && left_name == sym::Output { ty_to_fn @@ -592,12 +592,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // duplicate bound like `T: Iterator + Iterator` // on the docs page. bounds.remove(&GenericBound::TraitBound( - PolyTrait { trait_: *trait_.clone(), generic_params: Vec::new() }, + PolyTrait { trait_: trait_.clone(), generic_params: Vec::new() }, hir::TraitBoundModifier::None, )); // Avoid creating any new duplicate bounds later in the outer // loop - ty_to_traits.entry(*ty.clone()).or_default().insert(*trait_.clone()); + ty_to_traits.entry(*ty.clone()).or_default().insert(trait_.clone()); } _ => panic!("Unexpected LHS {:?} for {:?}", lhs, item_def_id), } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3c10fadeff368..73e56a610fbb3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -387,7 +387,7 @@ impl<'tcx> Clean for ty::ProjectionTy<'tcx> { name: cx.tcx.associated_item(self.item_def_id).ident.name, self_def_id: self_type.def_id(), self_type: box self_type, - trait_: box trait_, + trait_, } } } @@ -1277,16 +1277,16 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { let segments = if p.is_global() { &p.segments[1..] } else { &p.segments }; let trait_segments = &segments[..segments.len() - 1]; let trait_def = cx.tcx.associated_item(p.res.def_id()).container.id(); - let trait_path = self::Path { + let trait_ = self::Path { res: Res::Def(DefKind::Trait, trait_def), segments: trait_segments.clean(cx), }; - register_res(cx, trait_path.res); + register_res(cx, trait_.res); Type::QPath { name: p.segments.last().expect("segments were empty").ident.name, self_def_id: Some(DefId::local(qself.hir_id.owner.local_def_index)), self_type: box qself.clean(cx), - trait_: box trait_path, + trait_, } } hir::QPath::TypeRelative(ref qself, ref segment) => { @@ -1297,13 +1297,13 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { ty::Error(_) => return Type::Infer, _ => bug!("clean: expected associated type, found `{:?}`", ty), }; - let trait_path = hir::Path { span, res, segments: &[] }.clean(cx); - register_res(cx, trait_path.res); + let trait_ = hir::Path { span, res, segments: &[] }.clean(cx); + register_res(cx, trait_.res); Type::QPath { name: segment.ident.name, self_def_id: res.opt_def_id(), self_type: box qself.clean(cx), - trait_: box trait_path, + trait_, } } hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"), diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index da06737394d53..b57e8a0ed2aa8 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1408,8 +1408,7 @@ crate enum Type { name: Symbol, self_type: Box, self_def_id: Option, - // FIXME: remove this `Box`; it's unnecessary - trait_: Box, + trait_: Path, }, // `_` diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 10320baaf93d0..fda540aa186b0 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -436,7 +436,7 @@ impl FromWithTcx for Type { }, QPath { name, self_type, trait_, .. } => { // FIXME: should `trait_` be a clean::Path equivalent in JSON? - let trait_ = ResolvedPath { did: trait_.res.def_id(), path: *trait_ }.into_tcx(tcx); + let trait_ = ResolvedPath { did: trait_.res.def_id(), path: trait_ }.into_tcx(tcx); Type::QualifiedPath { name: name.to_string(), self_type: Box::new((*self_type).into_tcx(tcx)), From 4128a3dc1fe1324cdc127901d8ccecfc4fe61984 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Thu, 26 Aug 2021 17:49:58 -0700 Subject: [PATCH 06/16] Remove unused `Clean` impl --- src/librustdoc/clean/mod.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 73e56a610fbb3..fd284a1c9268d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -890,13 +890,6 @@ impl Clean for hir::IsAuto { } } -impl Clean for hir::TraitRef<'_> { - fn clean(&self, cx: &mut DocContext<'_>) -> Type { - let path = self.path.clean(cx); - resolve_type(cx, path) - } -} - impl Clean for hir::TraitRef<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> Path { let path = self.path.clean(cx); From a83112fe3e4adac459a73ea0f8018b7eab719238 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Thu, 26 Aug 2021 19:16:58 -0700 Subject: [PATCH 07/16] Remove temporary `GetDefId` impl for `Path` --- src/librustdoc/clean/inline.rs | 4 +- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/clean/types.rs | 20 ++-- src/librustdoc/formats/cache.rs | 20 ++-- src/librustdoc/formats/mod.rs | 8 +- src/librustdoc/html/render/mod.rs | 96 ++++++++------------ src/librustdoc/passes/collect_trait_impls.rs | 4 +- src/librustdoc/passes/stripper.rs | 2 +- 8 files changed, 63 insertions(+), 93 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index d1ee257fb3284..5fb3a98ca5b87 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -447,7 +447,7 @@ crate fn build_impl( }; let polarity = tcx.impl_polarity(did); let trait_ = associated_trait.clean(cx); - if trait_.def_id() == tcx.lang_items().deref_trait() { + if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() { super::build_deref_target_impls(cx, &trait_items, ret); } @@ -481,7 +481,7 @@ crate fn build_impl( let (merged_attrs, cfg) = merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs); trace!("merged_attrs={:?}", merged_attrs); - trace!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id()); + trace!("build_impl: impl {:?} for {:?}", trait_.as_ref().map(|t| t.def_id()), for_.def_id()); ret.push(clean::Item::from_def_id_and_attrs_and_parts( did, None, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index fd284a1c9268d..c52953573ac65 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1883,7 +1883,7 @@ fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_> // If this impl block is an implementation of the Deref trait, then we // need to try inlining the target's inherent impl blocks as well. - if trait_.def_id() == tcx.lang_items().deref_trait() { + if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() { build_deref_target_impls(cx, &items, &mut ret); } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index b57e8a0ed2aa8..a7a7f05ecfedc 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1122,7 +1122,7 @@ impl GenericBound { crate fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool { use rustc_hir::TraitBoundModifier as TBM; if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self { - if trait_.def_id() == cx.tcx.lang_items().sized_trait() { + if Some(trait_.def_id()) == cx.tcx.lang_items().sized_trait() { return true; } } @@ -1942,6 +1942,10 @@ crate struct Path { } impl Path { + crate fn def_id(&self) -> DefId { + self.res.def_id() + } + crate fn last(&self) -> Symbol { self.segments.last().expect("segments were empty").name } @@ -1992,17 +1996,6 @@ impl Path { } } -// FIXME: this is temporary -impl GetDefId for Path { - fn def_id(&self) -> Option { - Some(self.res.def_id()) - } - - fn def_id_full(&self, _: &Cache) -> Option { - self.def_id() - } -} - #[derive(Clone, PartialEq, Eq, Debug, Hash)] crate enum GenericArg { Lifetime(Lifetime), @@ -2155,7 +2148,8 @@ crate struct Impl { impl Impl { crate fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxHashSet { self.trait_ - .def_id() + .as_ref() + .map(|t| t.def_id()) .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.ident.name).collect()) .unwrap_or_default() } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index bcfcc3d70395c..dd1cf2a866dd4 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -201,7 +201,9 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // masked crate then remove it completely. if let clean::ImplItem(ref i) = *item.kind { if self.cache.masked_crates.contains(&item.def_id.krate()) - || i.trait_.def_id().map_or(false, |d| self.cache.masked_crates.contains(&d.krate)) + || i.trait_ + .as_ref() + .map_or(false, |t| self.cache.masked_crates.contains(&t.def_id().krate)) || i.for_.def_id().map_or(false, |d| self.cache.masked_crates.contains(&d.krate)) { return None; @@ -221,11 +223,11 @@ 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(did) = i.trait_.def_id() { + if let Some(trait_) = &i.trait_ { if i.blanket_impl.is_none() { self.cache .implementors - .entry(did) + .entry(trait_.def_id()) .or_default() .push(Impl { impl_item: item.clone() }); } @@ -400,12 +402,8 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { } clean::DynTrait(ref bounds, _) | clean::BorrowedRef { type_: box clean::DynTrait(ref bounds, _), .. } => { - if let Some(did) = bounds[0].trait_.def_id() { - self.cache.parent_stack.push(did); - true - } else { - false - } + self.cache.parent_stack.push(bounds[0].trait_.def_id()); + true } ref t => { let prim_did = t @@ -439,9 +437,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { } clean::DynTrait(ref bounds, _) | clean::BorrowedRef { type_: box clean::DynTrait(ref bounds, _), .. } => { - if let Some(did) = bounds[0].trait_.def_id() { - dids.insert(did); - } + dids.insert(bounds[0].trait_.def_id()); } ref t => { let did = t diff --git a/src/librustdoc/formats/mod.rs b/src/librustdoc/formats/mod.rs index 86e867d4006aa..4f0c5a9edee71 100644 --- a/src/librustdoc/formats/mod.rs +++ b/src/librustdoc/formats/mod.rs @@ -7,8 +7,6 @@ use rustc_hir::def_id::DefId; crate use renderer::{run_format, FormatRenderer}; use crate::clean; -use crate::clean::types::GetDefId; -use crate::formats::cache::Cache; /// Specifies whether rendering directly implemented trait items or ones from a certain Deref /// impl. @@ -40,10 +38,6 @@ impl Impl { } crate fn trait_did(&self) -> Option { - self.inner_impl().trait_.def_id() - } - - crate fn trait_did_full(&self, cache: &Cache) -> Option { - self.inner_impl().trait_.def_id_full(cache) + self.inner_impl().trait_.as_ref().map(|t| t.def_id()) } } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 7423699900319..e936750c6d37f 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -687,18 +687,12 @@ fn short_item_info( // Render the list of items inside one of the sections "Trait Implementations", // "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages). -fn render_impls( - cx: &Context<'_>, - w: &mut Buffer, - traits: &[&&Impl], - containing_item: &clean::Item, -) { - let cache = cx.cache(); +fn render_impls(cx: &Context<'_>, w: &mut Buffer, impls: &[&&Impl], containing_item: &clean::Item) { let tcx = cx.tcx(); - let mut impls = traits + let mut rendered_impls = impls .iter() .map(|i| { - let did = i.trait_did_full(cache).unwrap(); + let did = i.trait_did().unwrap(); let provided_trait_methods = i.inner_impl().provided_trait_methods(tcx); let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_trait_methods); let mut buffer = if w.is_for_html() { Buffer::html() } else { Buffer::new() }; @@ -722,8 +716,8 @@ fn render_impls( buffer.into_inner() }) .collect::>(); - impls.sort(); - w.write_str(&impls.join("")); + rendered_impls.sort(); + w.write_str(&rendered_impls.join("")); } fn naive_assoc_href(it: &clean::Item, link: AssocItemLink<'_>, cx: &Context<'_>) -> String { @@ -1068,13 +1062,11 @@ fn render_assoc_items( return; } if !traits.is_empty() { - let deref_impl = traits.iter().find(|t| { - t.inner_impl().trait_.def_id_full(cache) == cx.tcx().lang_items().deref_trait() - }); + let deref_impl = + traits.iter().find(|t| t.trait_did() == cx.tcx().lang_items().deref_trait()); if let Some(impl_) = deref_impl { - let has_deref_mut = traits.iter().any(|t| { - t.inner_impl().trait_.def_id_full(cache) == cx.tcx().lang_items().deref_mut_trait() - }); + let has_deref_mut = + traits.iter().any(|t| t.trait_did() == cx.tcx().lang_items().deref_mut_trait()); render_deref_methods(w, cx, impl_, containing_item, has_deref_mut); } let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) = @@ -1192,45 +1184,39 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String { let mut out = Buffer::html(); - let mut trait_ = String::new(); if let Some(did) = decl.output.def_id_full(cx.cache()) { if let Some(impls) = cx.cache().impls.get(&did) { for i in impls { let impl_ = i.inner_impl(); - if impl_.trait_.def_id().map_or(false, |d| { - cx.cache().traits.get(&d).map(|t| t.is_notable).unwrap_or(false) - }) { - if out.is_empty() { - write!( - &mut out, - "
Notable traits for {}
\ - ", - impl_.for_.print(cx) - ); - trait_.push_str(&impl_.for_.print(cx).to_string()); - } + if let Some(trait_) = &impl_.trait_ { + let trait_did = trait_.def_id(); - //use the "where" class here to make it small - write!( - &mut out, - "{}", - impl_.print(false, cx) - ); - let t_did = impl_.trait_.def_id_full(cx.cache()).unwrap(); - for it in &impl_.items { - if let clean::TypedefItem(ref tydef, _) = *it.kind { - out.push_str(" "); - assoc_type( + if cx.cache().traits.get(&trait_did).map_or(false, |t| t.is_notable) { + if out.is_empty() { + write!( &mut out, - it, - &[], - Some(&tydef.type_), - AssocItemLink::GotoSource(t_did.into(), &FxHashSet::default()), - "", - cx, + "
Notable traits for {}
\ + ", + impl_.for_.print(cx) ); - out.push_str(";
"); + } + + //use the "where" class here to make it small + write!( + &mut out, + "{}", + impl_.print(false, cx) + ); + for it in &impl_.items { + if let clean::TypedefItem(ref tydef, _) = *it.kind { + out.push_str(" "); + let empty_set = FxHashSet::default(); + let src_link = + AssocItemLink::GotoSource(trait_did.into(), &empty_set); + assoc_type(&mut out, it, &[], Some(&tydef.type_), src_link, "", cx); + out.push_str(";"); + } } } } @@ -1273,7 +1259,7 @@ fn render_impl( ) { let cache = cx.cache(); let traits = &cache.traits; - let trait_ = i.trait_did_full(cache).map(|did| &traits[&did]); + let trait_ = i.trait_did().map(|did| &traits[&did]); let mut close_tags = String::new(); // For trait implementations, the `interesting` output contains all methods that have doc @@ -1503,7 +1489,7 @@ fn render_impl( if i.items.iter().any(|m| m.name == n) { continue; } - let did = i.trait_.as_ref().unwrap().def_id_full(cx.cache()).unwrap(); + let did = i.trait_.as_ref().unwrap().def_id(); let provided_methods = i.provided_trait_methods(cx.tcx()); let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_methods); @@ -1887,9 +1873,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { } if v.iter().any(|i| i.inner_impl().trait_.is_some()) { - if let Some(impl_) = v.iter().filter(|i| i.inner_impl().trait_.is_some()).find(|i| { - i.inner_impl().trait_.def_id_full(cache) == cx.tcx().lang_items().deref_trait() - }) { + if let Some(impl_) = + v.iter().find(|i| i.trait_did() == cx.tcx().lang_items().deref_trait()) + { sidebar_deref_methods(cx, out, impl_, v); } @@ -1987,9 +1973,7 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V } } } - let deref_mut = v.iter().filter(|i| i.inner_impl().trait_.is_some()).any(|i| { - i.inner_impl().trait_.def_id_full(c) == cx.tcx().lang_items().deref_mut_trait() - }); + let deref_mut = v.iter().any(|i| i.trait_did() == cx.tcx().lang_items().deref_mut_trait()); let inner_impl = target .def_id_full(c) .or_else(|| { diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index e8aa37c8868d8..72e631df89a59 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -57,7 +57,9 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { // scan through included items ahead of time to splice in Deref targets to the "valid" sets for it in &new_items { if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = *it.kind { - if cleaner.keep_impl(for_) && trait_.def_id() == cx.tcx.lang_items().deref_trait() { + if cleaner.keep_impl(for_) + && trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait() + { let target = items .iter() .find_map(|item| match *item.kind { diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index 90300dbd16b13..8b1fd662f85fd 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -134,7 +134,7 @@ impl<'a> DocFolder for ImplStripper<'a> { return None; } } - if let Some(did) = imp.trait_.def_id() { + if let Some(did) = imp.trait_.as_ref().map(|t| t.def_id()) { if did.is_local() && !self.retained.contains(&did.into()) { debug!("ImplStripper: impl item for stripped trait; removing"); return None; From eec21d21763abbb76b8feac31265128a8e2691b0 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Fri, 27 Aug 2021 16:26:11 -0700 Subject: [PATCH 08/16] Avoid intermediate `collect()` --- src/librustdoc/clean/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index a7a7f05ecfedc..05709cc2f4df8 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1955,7 +1955,7 @@ impl Path { } crate fn whole_name(&self) -> String { - self.segments.iter().map(|s| s.name.to_string()).collect::>().join("::") + self.segments.iter().map(|s| s.name.to_string()).intersperse("::".into()).collect() } /// Checks if this is a `T::Name` path for an associated type. From d4675aad5c5ff63b43e59618f8ab01236ae4f98a Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Fri, 27 Aug 2021 19:05:22 -0700 Subject: [PATCH 09/16] Turn some comments into docs --- src/librustdoc/clean/auto_trait.rs | 114 ++++++++++++++--------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 20fb91eba39a1..f375af4837f75 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -166,16 +166,16 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { .clone() } - // This method calculates two things: Lifetime constraints of the form 'a: 'b, - // and region constraints of the form ReVar: 'a - // - // This is essentially a simplified version of lexical_region_resolve. However, - // handle_lifetimes determines what *needs be* true in order for an impl to hold. - // lexical_region_resolve, along with much of the rest of the compiler, is concerned - // with determining if a given set up constraints/predicates *are* met, given some - // starting conditions (e.g., user-provided code). For this reason, it's easier - // to perform the calculations we need on our own, rather than trying to make - // existing inference/solver code do what we want. + /// This method calculates two things: Lifetime constraints of the form `'a: 'b`, + /// and region constraints of the form `RegionVid: 'a` + /// + /// This is essentially a simplified version of lexical_region_resolve. However, + /// handle_lifetimes determines what *needs be* true in order for an impl to hold. + /// lexical_region_resolve, along with much of the rest of the compiler, is concerned + /// with determining if a given set up constraints/predicates *are* met, given some + /// starting conditions (e.g., user-provided code). For this reason, it's easier + /// to perform the calculations we need on our own, rather than trying to make + /// existing inference/solver code do what we want. fn handle_lifetimes<'cx>( regions: &RegionConstraintData<'cx>, names_map: &FxHashMap, @@ -410,15 +410,15 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { .collect() } - // Converts the calculated ParamEnv and lifetime information to a clean::Generics, suitable for - // display on the docs page. Cleaning the Predicates produces sub-optimal `WherePredicate`s, - // so we fix them up: - // - // * Multiple bounds for the same type are coalesced into one: e.g., 'T: Copy', 'T: Debug' - // becomes 'T: Copy + Debug' - // * Fn bounds are handled specially - instead of leaving it as 'T: Fn(), = - // K', we use the dedicated syntax 'T: Fn() -> K' - // * We explicitly add a '?Sized' bound if we didn't find any 'Sized' predicates for a type + /// Converts the calculated `ParamEnv` and lifetime information to a [`clean::Generics`](Generics), suitable for + /// display on the docs page. Cleaning the `Predicates` produces sub-optimal [`WherePredicate`]s, + /// so we fix them up: + /// + /// * Multiple bounds for the same type are coalesced into one: e.g., `T: Copy`, `T: Debug` + /// becomes `T: Copy + Debug` + /// * `Fn` bounds are handled specially - instead of leaving it as `T: Fn(), = + /// K`, we use the dedicated syntax `T: Fn() -> K` + /// * We explicitly add a `?Sized` bound if we didn't find any `Sized` predicates for a type fn param_env_to_generics( &mut self, item_def_id: DefId, @@ -632,11 +632,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { Generics { params: generic_params, where_predicates: existing_predicates } } - // Ensure that the predicates are in a consistent order. The precise - // ordering doesn't actually matter, but it's important that - // a given set of predicates always appears in the same order - - // both for visual consistency between 'rustdoc' runs, and to - // make writing tests much easier + /// Ensure that the predicates are in a consistent order. The precise + /// ordering doesn't actually matter, but it's important that + /// a given set of predicates always appears in the same order - + /// both for visual consistency between 'rustdoc' runs, and to + /// make writing tests much easier #[inline] fn sort_where_predicates(&self, mut predicates: &mut Vec) { // We should never have identical bounds - and if we do, @@ -645,11 +645,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { self.unstable_debug_sort(&mut predicates); } - // Ensure that the bounds are in a consistent order. The precise - // ordering doesn't actually matter, but it's important that - // a given set of bounds always appears in the same order - - // both for visual consistency between 'rustdoc' runs, and to - // make writing tests much easier + /// Ensure that the bounds are in a consistent order. The precise + /// ordering doesn't actually matter, but it's important that + /// a given set of bounds always appears in the same order - + /// both for visual consistency between 'rustdoc' runs, and to + /// make writing tests much easier #[inline] fn sort_where_bounds(&self, mut bounds: &mut Vec) { // We should never have identical bounds - and if we do, @@ -658,33 +658,33 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { self.unstable_debug_sort(&mut bounds); } - // This might look horrendously hacky, but it's actually not that bad. - // - // For performance reasons, we use several different FxHashMaps - // in the process of computing the final set of where predicates. - // However, the iteration order of a HashMap is completely unspecified. - // In fact, the iteration of an FxHashMap can even vary between platforms, - // since FxHasher has different behavior for 32-bit and 64-bit platforms. - // - // Obviously, it's extremely undesirable for documentation rendering - // to be dependent on the platform it's run on. Apart from being confusing - // to end users, it makes writing tests much more difficult, as predicates - // can appear in any order in the final result. - // - // To solve this problem, we sort WherePredicates and GenericBounds - // by their Debug string. The thing to keep in mind is that we don't really - // care what the final order is - we're synthesizing an impl or bound - // ourselves, so any order can be considered equally valid. By sorting the - // predicates and bounds, however, we ensure that for a given codebase, all - // auto-trait impls always render in exactly the same way. - // - // Using the Debug implementation for sorting prevents us from needing to - // write quite a bit of almost entirely useless code (e.g., how should two - // Types be sorted relative to each other). It also allows us to solve the - // problem for both WherePredicates and GenericBounds at the same time. This - // approach is probably somewhat slower, but the small number of items - // involved (impls rarely have more than a few bounds) means that it - // shouldn't matter in practice. + /// This might look horrendously hacky, but it's actually not that bad. + /// + /// For performance reasons, we use several different FxHashMaps + /// in the process of computing the final set of where predicates. + /// However, the iteration order of a HashMap is completely unspecified. + /// In fact, the iteration of an FxHashMap can even vary between platforms, + /// since FxHasher has different behavior for 32-bit and 64-bit platforms. + /// + /// Obviously, it's extremely undesirable for documentation rendering + /// to be dependent on the platform it's run on. Apart from being confusing + /// to end users, it makes writing tests much more difficult, as predicates + /// can appear in any order in the final result. + /// + /// To solve this problem, we sort WherePredicates and GenericBounds + /// by their Debug string. The thing to keep in mind is that we don't really + /// care what the final order is - we're synthesizing an impl or bound + /// ourselves, so any order can be considered equally valid. By sorting the + /// predicates and bounds, however, we ensure that for a given codebase, all + /// auto-trait impls always render in exactly the same way. + /// + /// Using the Debug implementation for sorting prevents us from needing to + /// write quite a bit of almost entirely useless code (e.g., how should two + /// Types be sorted relative to each other). It also allows us to solve the + /// problem for both WherePredicates and GenericBounds at the same time. This + /// approach is probably somewhat slower, but the small number of items + /// involved (impls rarely have more than a few bounds) means that it + /// shouldn't matter in practice. fn unstable_debug_sort(&self, vec: &mut Vec) { vec.sort_by_cached_key(|x| format!("{:?}", x)) } @@ -705,7 +705,7 @@ fn region_name(region: Region<'_>) -> Option { } } -// Replaces all ReVars in a type with ty::Region's, using the provided map +/// Replaces all [`ty::RegionVid`]s in a type with [`ty::Region`]s, using the provided map. struct RegionReplacer<'a, 'tcx> { vid_to_region: &'a FxHashMap>, tcx: TyCtxt<'tcx>, From e4ce68baa841af3077fa3ef82fac0a33f0e61d20 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Sat, 28 Aug 2021 20:25:09 -0700 Subject: [PATCH 10/16] Update `clean::Type` docs They've barely been updated since this version of `rustdoc` (originally called `rustdoc_ng`) was checked into the tree! Note that the formatting of a couple `Type` variants changed; rustfmt seems to change formatting based on whether all variants have docs. --- src/librustdoc/clean/types.rs | 54 +++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 05709cc2f4df8..3373cee917229 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1372,49 +1372,49 @@ crate struct PolyTrait { crate generic_params: Vec, } -/// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original -/// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most -/// importantly, it does not preserve mutability or boxes. +/// Rustdoc's representation of types, mostly based on the [`hir::Ty`]. #[derive(Clone, PartialEq, Eq, Debug, Hash)] crate enum Type { - /// Structs/enums/traits (most that would be an `hir::TyKind::Path`). - ResolvedPath { - path: Path, - did: DefId, - }, - /// `dyn for<'a> Trait<'a> + Send + 'static` + /// A named type, which could be a trait. + /// + /// This is mostly Rustdoc's version of [`hir::Path`]. + ResolvedPath { path: Path, did: DefId }, + /// A `dyn Trait` object: `dyn for<'a> Trait<'a> + Send + 'static` DynTrait(Vec, Option), - /// For parameterized types, so the consumer of the JSON don't go - /// looking for types which don't exist anywhere. + /// A type parameter. Generic(Symbol), - /// Primitives are the fixed-size numeric types (plus int/usize/float), char, - /// arrays, slices, and tuples. + /// A primitive (aka, builtin) type. Primitive(PrimitiveType), - /// `extern "ABI" fn` + /// A function pointer: `extern "ABI" fn(...) -> ...` BareFunction(Box), + /// A tuple type: `(i32, &str)`. Tuple(Vec), + /// A slice type (does *not* include the `&`): `[i32]` Slice(Box), - /// The `String` field is about the size or the constant representing the array's length. + /// An array type. + /// + /// The `String` field is a stringified version of the array's length parameter. Array(Box, String), + /// A raw pointer type: `*const i32`, `*mut i32` RawPointer(Mutability, Box), - BorrowedRef { - lifetime: Option, - mutability: Mutability, - type_: Box, - }, + /// A reference type: `&i32`, `&'a mut Foo` + BorrowedRef { lifetime: Option, mutability: Mutability, type_: Box }, - // `::Name` + /// A qualified path to an associated item: `::Name` QPath { name: Symbol, self_type: Box, + /// 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, trait_: Path, }, - // `_` + /// A type that is inferred: `_` Infer, - // `impl TraitA + TraitB + ...` + /// An `impl Trait`: `impl TraitA + TraitB + ...` ImplTrait(Vec), } @@ -1538,8 +1538,12 @@ impl GetDefId for Type { } } -/// N.B. this has to be different from `hir::PrimTy` because it also includes types that aren't -/// paths, like `Unit`. +/// A primitive (aka, builtin) type. +/// +/// This represents things like `i32`, `str`, etc. +/// +/// N.B. This has to be different from [`hir::PrimTy`] because it also includes types that aren't +/// paths, like [`Self::Unit`]. #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)] crate enum PrimitiveType { Isize, From 82b52e1951622062ce26a185dca58a8b472b4ec8 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Sat, 28 Aug 2021 20:38:05 -0700 Subject: [PATCH 11/16] Remove outdated comment `CACHE_KEY` no longer exists. --- src/librustdoc/clean/types.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 3373cee917229..9b74d130941d8 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -120,8 +120,7 @@ crate struct Crate { crate module: Item, crate externs: Vec, crate primitives: ThinVec<(DefId, PrimitiveType)>, - // These are later on moved into `CACHEKEY`, leaving the map empty. - // Only here so that they can be filtered through the rustdoc passes. + /// Only here so that they can be filtered through the rustdoc passes. crate external_traits: Rc>>, crate collapsed: bool, } From 962e45144390d3f8b7482d5dfbc3d739881f514e Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Sat, 28 Aug 2021 20:46:53 -0700 Subject: [PATCH 12/16] Replace all uses of `path.res.def_id()` with `path.def_id()` --- src/librustdoc/clean/auto_trait.rs | 2 +- src/librustdoc/clean/inline.rs | 8 ++++---- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/clean/simplify.rs | 2 +- src/librustdoc/clean/types.rs | 4 ++-- src/librustdoc/html/format.rs | 6 +++--- src/librustdoc/html/render/cache.rs | 2 +- src/librustdoc/html/render/mod.rs | 2 +- src/librustdoc/json/conversions.rs | 8 ++++---- src/librustdoc/passes/collect_trait_impls.rs | 2 +- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index f375af4837f75..e771714ed6119 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -691,7 +691,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { fn is_fn_trait(&self, path: &Path) -> bool { let tcx = self.cx.tcx; - let did = path.res.def_id(); + let did = path.def_id(); did == tcx.require_lang_item(LangItem::Fn, None) || did == tcx.require_lang_item(LangItem::FnMut, None) || did == tcx.require_lang_item(LangItem::FnOnce, None) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 5fb3a98ca5b87..ebf61fd104843 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -454,7 +454,7 @@ crate fn build_impl( // Return if the trait itself or any types of the generic parameters are doc(hidden). let mut stack: Vec<&Type> = vec![&for_]; - if let Some(did) = trait_.as_ref().map(|t| t.res.def_id()) { + if let Some(did) = trait_.as_ref().map(|t| t.def_id()) { if tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden) { return; } @@ -474,7 +474,7 @@ crate fn build_impl( } } - if let Some(did) = trait_.as_ref().map(|t| t.res.def_id()) { + if let Some(did) = trait_.as_ref().map(|t| t.def_id()) { record_extern_trait(cx, did); } @@ -628,7 +628,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean: } if *s == kw::SelfUpper => { bounds.retain(|bound| match bound { clean::GenericBound::TraitBound(clean::PolyTrait { trait_, .. }, _) => { - trait_.res.def_id() != trait_did + trait_.def_id() != trait_did } _ => true, }); @@ -642,7 +642,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean: ty: clean::QPath { self_type: box clean::Generic(ref s), trait_, name: _, .. }, bounds, .. - } => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.res.def_id() == trait_did), + } => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.def_id() == trait_did), _ => true, }); g diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c52953573ac65..9451664674b59 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1100,7 +1100,7 @@ impl Clean for ty::AssocItem { if *name != my_name { return None; } - if trait_.res.def_id() != self.container.id() { + if trait_.def_id() != self.container.id() { return None; } match **self_type { diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 101fdd465b70d..4c81e75e8d630 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -102,7 +102,7 @@ crate fn merge_bounds( // If this QPath's trait `trait_did` is the same as, or a supertrait // of, the bound's trait `did` then we can keep going, otherwise // this is just a plain old equality bound. - if !trait_is_same_or_supertrait(cx, trait_ref.trait_.res.def_id(), trait_did) { + if !trait_is_same_or_supertrait(cx, trait_ref.trait_.def_id(), trait_did) { return false; } let last = trait_ref.trait_.segments.last_mut().expect("segments were empty"); diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 9b74d130941d8..d259ed3cdfa7e 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1499,13 +1499,13 @@ impl Type { QPath { self_type, trait_, name, .. } => (self_type, trait_, name), _ => return None, }; - Some((&self_, trait_.res.def_id(), *name)) + Some((&self_, trait_.def_id(), *name)) } fn inner_def_id(&self, cache: Option<&Cache>) -> Option { let t: PrimitiveType = match *self { ResolvedPath { did, .. } => return Some(did), - DynTrait(ref bounds, _) => return Some(bounds[0].trait_.res.def_id()), + DynTrait(ref bounds, _) => return Some(bounds[0].trait_.def_id()), Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()), BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference, BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache), diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 7093bcf6adf1c..9cd10481ef03d 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -914,7 +914,7 @@ fn fmt_type<'cx>( clean::QPath { ref name, ref self_type, ref trait_, ref self_def_id } => { let should_show_cast = !trait_.segments.is_empty() && self_def_id - .zip(Some(trait_.res.def_id())) + .zip(Some(trait_.def_id())) .map_or(!self_type.is_self_type(), |(id, trait_)| id != trait_); if f.alternate() { if should_show_cast { @@ -939,7 +939,7 @@ fn fmt_type<'cx>( // the ugliness comes from inlining across crates where // everything comes in as a fully resolved QPath (hard to // look at). - match href(trait_.res.def_id(), cx) { + match href(trait_.def_id(), cx) { Ok((ref url, _, ref path)) if !f.alternate() => { write!( f, @@ -972,7 +972,7 @@ impl clean::Path { &'a self, cx: &'a Context<'tcx>, ) -> impl fmt::Display + 'b + Captures<'tcx> { - display_fn(move |f| resolved_path(f, self.res.def_id(), self, false, false, cx)) + display_fn(move |f| resolved_path(f, self.def_id(), self, false, false, cx)) } } diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 7336b8b41ac16..9c05c80d55dfe 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -322,7 +322,7 @@ crate fn get_real_types<'tcx>( if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) { for bound in bound.get_bounds().unwrap_or(&[]) { if let Some(path) = bound.get_trait_path() { - let ty = Type::ResolvedPath { did: path.res.def_id(), path }; + let ty = Type::ResolvedPath { did: path.def_id(), path }; let adds = get_real_types(generics, &ty, tcx, recurse + 1, res); nb_added += adds; if adds == 0 && !ty.is_full_generic() { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index e936750c6d37f..6b213da50a79c 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2389,7 +2389,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec { } clean::Type::QPath { self_type, trait_, .. } => { work.push_back(*self_type); - process_path(trait_.res.def_id()); + process_path(trait_.def_id()); } _ => {} } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index fda540aa186b0..1f2479a302f95 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -365,7 +365,7 @@ impl FromWithTcx for GenericBound { TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => { // FIXME: should `trait_` be a clean::Path equivalent in JSON? let trait_ = - clean::ResolvedPath { did: trait_.res.def_id(), path: trait_ }.into_tcx(tcx); + clean::ResolvedPath { did: trait_.def_id(), path: trait_ }.into_tcx(tcx); GenericBound::TraitBound { trait_, generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(), @@ -401,7 +401,7 @@ impl FromWithTcx for Type { Type::ResolvedPath { name: first_trait.whole_name(), - id: from_item_id(first_trait.res.def_id().into()), + id: from_item_id(first_trait.def_id().into()), args: first_trait .segments .last() @@ -436,7 +436,7 @@ impl FromWithTcx for Type { }, QPath { name, self_type, trait_, .. } => { // FIXME: should `trait_` be a clean::Path equivalent in JSON? - let trait_ = ResolvedPath { did: trait_.res.def_id(), path: trait_ }.into_tcx(tcx); + let trait_ = ResolvedPath { did: trait_.def_id(), path: trait_ }.into_tcx(tcx); Type::QualifiedPath { name: name.to_string(), self_type: Box::new((*self_type).into_tcx(tcx)), @@ -513,7 +513,7 @@ impl FromWithTcx for Impl { } = impl_; // FIXME: should `trait_` be a clean::Path equivalent in JSON? let trait_ = trait_.map(|path| { - let did = path.res.def_id(); + let did = path.def_id(); clean::ResolvedPath { path, did }.into_tcx(tcx) }); Impl { diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 72e631df89a59..319dd7b42b0ee 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -82,7 +82,7 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { cleaner.keep_impl(for_) || trait_ .as_ref() - .map_or(false, |t| cleaner.keep_impl_with_def_id(t.res.def_id().into())) + .map_or(false, |t| cleaner.keep_impl_with_def_id(t.def_id().into())) || blanket_impl.is_some() } else { true From 5f744f33f60f1961e756adf30606a08076350182 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 29 Sep 2021 11:43:14 -0700 Subject: [PATCH 13/16] Explain `ResolvedPath` vs `hir::Path` Co-authored-by: Joshua Nelson --- src/librustdoc/clean/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index d259ed3cdfa7e..df6e030aeef71 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1376,7 +1376,7 @@ crate struct PolyTrait { crate enum Type { /// A named type, which could be a trait. /// - /// This is mostly Rustdoc's version of [`hir::Path`]. + /// This is mostly Rustdoc's version of [`hir::Path`]. It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics. ResolvedPath { path: Path, did: DefId }, /// A `dyn Trait` object: `dyn for<'a> Trait<'a> + Send + 'static` DynTrait(Vec, Option), From f9f3c9feb49172ce4015f6e81815b70051ba683c Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Sun, 3 Oct 2021 11:18:47 -0700 Subject: [PATCH 14/16] Rename `strip_path` to `strip_path_generics` The new name is more descriptive of what the function does. --- src/librustdoc/clean/auto_trait.rs | 2 +- src/librustdoc/clean/utils.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index e771714ed6119..f9d1666977134 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -502,7 +502,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { .and_then(|trait_| { ty_to_traits .get(&ty) - .map(|bounds| bounds.contains(&strip_path(trait_.clone()))) + .map(|bounds| bounds.contains(&strip_path_generics(trait_.clone()))) }) .unwrap_or(false) { diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 487efdc060f09..1449b8acf0cd7 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -156,7 +156,8 @@ pub(super) fn external_path( } } -crate fn strip_path(path: Path) -> Path { +/// Remove the generic arguments from a path. +crate fn strip_path_generics(path: Path) -> Path { let segments = path .segments .iter() From f359b316df4e42369b91cbd39fec2925fe1a2fd7 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Sun, 3 Oct 2021 12:29:17 -0700 Subject: [PATCH 15/16] Fix a place that used the old `Path` representation --- src/librustdoc/clean/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9451664674b59..668088bb0a59a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1267,8 +1267,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { return normalized_value.clean(cx); } - let segments = if p.is_global() { &p.segments[1..] } else { &p.segments }; - let trait_segments = &segments[..segments.len() - 1]; + let trait_segments = &p.segments[..p.segments.len() - 1]; let trait_def = cx.tcx.associated_item(p.res.def_id()).container.id(); let trait_ = self::Path { res: Res::Def(DefKind::Trait, trait_def), From ebbcafbfa3d7dde58a548621a2003d26c1005fd4 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Sun, 3 Oct 2021 12:40:53 -0700 Subject: [PATCH 16/16] Fix implementation of `clean::Path::whole_name()` I think that before this commit, the path `::std::vec::Vec` would have rendered as `{{root}}::std::vec::Vec`. Now, it should render correctly as `::std::vec::Vec`. --- src/librustdoc/clean/types.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index df6e030aeef71..2e09768a8ef75 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1958,7 +1958,11 @@ impl Path { } crate fn whole_name(&self) -> String { - self.segments.iter().map(|s| s.name.to_string()).intersperse("::".into()).collect() + self.segments + .iter() + .map(|s| if s.name == kw::PathRoot { String::new() } else { s.name.to_string() }) + .intersperse("::".into()) + .collect() } /// Checks if this is a `T::Name` path for an associated type.