From f5ac93b94b611bd9193b81c7eae85a3afe835549 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 17 May 2022 17:27:14 -0700 Subject: [PATCH 1/3] rustdoc: avoid including impl blocks with filled-in generics Fixes #94937 --- src/librustdoc/passes/collect_trait_impls.rs | 29 ++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 3b7ca7dc3c519..0dc1c9d966313 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -9,7 +9,7 @@ use crate::visit::DocVisitor; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def_id::DefId; -use rustc_middle::ty::DefIdTree; +use rustc_middle::ty::{self, DefIdTree}; use rustc_span::symbol::sym; crate const COLLECT_TRAIT_IMPLS: Pass = Pass { @@ -81,8 +81,33 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate // Do not calculate blanket impl list for docs that are not going to be rendered. // While the `impl` blocks themselves are only in `libcore`, the module with `doc` // attached is directly included in `libstd` as well. + let tcx = cx.tcx; if did.is_local() { - for def_id in prim.impls(cx.tcx) { + for def_id in prim.impls(tcx).filter(|def_id| { + // Avoid including impl blocks with filled-in generics. + // https://github.com/rust-lang/rust/issues/94937 + // + // FIXME(notriddle): https://github.com/rust-lang/rust/issues/97129 + // + // This tactic of using inherent impl blocks for getting + // auto traits and blanket impls is a hack. What we really + // want is to check if `[T]` impls `Send`, which has + // nothing to do with the inherent impl. + // + // Rustdoc currently uses these `impl` block as a source of + // the `Ty`, as well as the `ParamEnv`, `SubstsRef`, and + // `Generics`. To avoid relying on the `impl` block, these + // things would need to be created from wholecloth, in a + // form that is valid for use in type inference. + let ty = tcx.type_of(def_id); + match ty.kind() { + ty::Slice(ty) => matches!(ty.kind(), ty::Param(..)), + ty::Ref(_region, ty, _mutbl) => matches!(ty.kind(), ty::Param(..)), + ty::RawPtr(ty::TypeAndMut { ty, .. }) => matches!(ty.kind(), ty::Param(..)), + ty::Tuple(tys) => tys.iter().all(|ty| matches!(ty.kind(), ty::Param(..))), + _ => true, + } + }) { let impls = get_auto_trait_and_blanket_impls(cx, def_id); new_items_external.extend(impls.filter(|i| cx.inlined.insert(i.item_id))); } From 57450c637c9ea45023c438f2b6ef5c8cd637e6e6 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 1 Jun 2022 08:40:19 -0700 Subject: [PATCH 2/3] Update src/librustdoc/passes/collect_trait_impls.rs Co-authored-by: Guillaume Gomez --- src/librustdoc/passes/collect_trait_impls.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 0dc1c9d966313..a042a68a2a1bc 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -101,9 +101,11 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate // form that is valid for use in type inference. let ty = tcx.type_of(def_id); match ty.kind() { - ty::Slice(ty) => matches!(ty.kind(), ty::Param(..)), - ty::Ref(_region, ty, _mutbl) => matches!(ty.kind(), ty::Param(..)), - ty::RawPtr(ty::TypeAndMut { ty, .. }) => matches!(ty.kind(), ty::Param(..)), + ty::Slice(ty) + | ty::Ref(_, ty, _) + | ty::RawPtr(ty::TypeAndMut { ty, .. }) => { + matches!(ty.kind(), ty::Param(..)) + } ty::Tuple(tys) => tys.iter().all(|ty| matches!(ty.kind(), ty::Param(..))), _ => true, } From 434adfff42a3992aaa4c0a1471ee71fb136a61cb Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 1 Jun 2022 11:00:25 -0700 Subject: [PATCH 3/3] rustdoc: add test case for auto traits on slice primitive --- src/test/rustdoc/primitive-slice-auto-trait.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/test/rustdoc/primitive-slice-auto-trait.rs diff --git a/src/test/rustdoc/primitive-slice-auto-trait.rs b/src/test/rustdoc/primitive-slice-auto-trait.rs new file mode 100644 index 0000000000000..b3f511bc1f153 --- /dev/null +++ b/src/test/rustdoc/primitive-slice-auto-trait.rs @@ -0,0 +1,14 @@ +// compile-flags: --crate-type lib --edition 2018 + +#![crate_name = "foo"] +#![feature(rustdoc_internals)] + +// @has foo/primitive.slice.html '//a[@class="primitive"]' 'slice' +// @has - '//span[@class="in-band"]' 'Primitive Type slice' +// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' +// @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations' +// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Send for [T] where T: Send' +// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Sync for [T] where T: Sync' +#[doc(primitive = "slice")] +/// this is a test! +mod slice_prim {}