Skip to content

Commit 9fc3fc3

Browse files
authored
Rollup merge of #97130 - notriddle:notriddle/collect-trait-impls-dup, r=GuillaumeGomez
rustdoc: avoid including impl blocks with filled-in generics Fixes #94937 # Before ![image](https://user-images.githubusercontent.com/1593513/168933282-02ccc4ae-9c89-4836-ba34-e2bd83946105.png) # After ![image](https://user-images.githubusercontent.com/1593513/168933255-4c17407d-d8d1-406e-87f5-9ea809437173.png)
2 parents 3ed9bbe + 434adff commit 9fc3fc3

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

src/librustdoc/passes/collect_trait_impls.rs

+29-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::visit::DocVisitor;
99

1010
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1111
use rustc_hir::def_id::DefId;
12-
use rustc_middle::ty::DefIdTree;
12+
use rustc_middle::ty::{self, DefIdTree};
1313
use rustc_span::symbol::sym;
1414

1515
pub(crate) const COLLECT_TRAIT_IMPLS: Pass = Pass {
@@ -81,8 +81,35 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
8181
// Do not calculate blanket impl list for docs that are not going to be rendered.
8282
// While the `impl` blocks themselves are only in `libcore`, the module with `doc`
8383
// attached is directly included in `libstd` as well.
84+
let tcx = cx.tcx;
8485
if did.is_local() {
85-
for def_id in prim.impls(cx.tcx) {
86+
for def_id in prim.impls(tcx).filter(|def_id| {
87+
// Avoid including impl blocks with filled-in generics.
88+
// https://github.com/rust-lang/rust/issues/94937
89+
//
90+
// FIXME(notriddle): https://github.com/rust-lang/rust/issues/97129
91+
//
92+
// This tactic of using inherent impl blocks for getting
93+
// auto traits and blanket impls is a hack. What we really
94+
// want is to check if `[T]` impls `Send`, which has
95+
// nothing to do with the inherent impl.
96+
//
97+
// Rustdoc currently uses these `impl` block as a source of
98+
// the `Ty`, as well as the `ParamEnv`, `SubstsRef`, and
99+
// `Generics`. To avoid relying on the `impl` block, these
100+
// things would need to be created from wholecloth, in a
101+
// form that is valid for use in type inference.
102+
let ty = tcx.type_of(def_id);
103+
match ty.kind() {
104+
ty::Slice(ty)
105+
| ty::Ref(_, ty, _)
106+
| ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
107+
matches!(ty.kind(), ty::Param(..))
108+
}
109+
ty::Tuple(tys) => tys.iter().all(|ty| matches!(ty.kind(), ty::Param(..))),
110+
_ => true,
111+
}
112+
}) {
86113
let impls = get_auto_trait_and_blanket_impls(cx, def_id);
87114
new_items_external.extend(impls.filter(|i| cx.inlined.insert(i.item_id)));
88115
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// compile-flags: --crate-type lib --edition 2018
2+
3+
#![crate_name = "foo"]
4+
#![feature(rustdoc_internals)]
5+
6+
// @has foo/primitive.slice.html '//a[@class="primitive"]' 'slice'
7+
// @has - '//span[@class="in-band"]' 'Primitive Type slice'
8+
// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
9+
// @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations'
10+
// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Send for [T] where T: Send'
11+
// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Sync for [T] where T: Sync'
12+
#[doc(primitive = "slice")]
13+
/// this is a test!
14+
mod slice_prim {}

0 commit comments

Comments
 (0)