Skip to content

Commit 0c38f31

Browse files
Add tests for recursive deref
1 parent 8a473ca commit 0c38f31

File tree

7 files changed

+169
-8
lines changed

7 files changed

+169
-8
lines changed

src/librustdoc/passes/collect_trait_impls.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
8181
// scan through included items ahead of time to splice in Deref targets to the "valid" sets
8282
for it in &new_items {
8383
if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = *it.kind {
84-
if cleaner.keep_impl(for_)
85-
&& trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait()
84+
if trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait()
85+
&& cleaner.keep_impl(for_)
8686
{
8787
let target = items
8888
.iter()
@@ -221,8 +221,11 @@ impl BadImplStripper {
221221
true
222222
} else if let Some(prim) = ty.primitive_type() {
223223
self.prims.contains(&prim)
224-
} else if let Some(did) = ty.def_id_no_primitives() {
225-
self.keep_impl_with_def_id(did.into())
224+
} else if ty.def_id_no_primitives().is_some() {
225+
// We want to keep *ALL* deref implementations in case some of them are used in
226+
// the current crate.
227+
// FIXME: Try to filter the one actually used...
228+
true
226229
} else {
227230
false
228231
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// check-pass
2+
3+
// ICE found in https://github.com/rust-lang/rust/issues/83123
4+
5+
pub struct Attribute;
6+
7+
pub struct Map<'hir> {}
8+
impl<'hir> Map<'hir> {
9+
pub fn attrs(&self) -> &'hir [Attribute] { &[] }
10+
}
11+
12+
pub struct List<T>(T);
13+
14+
impl<T> std::ops::Deref for List<T> {
15+
type Target = [T];
16+
fn deref(&self) -> &[T] {
17+
&[]
18+
}
19+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// #26207: Show all methods reachable via Deref impls, recursing through multiple dereferencing
2+
// levels and across multiple crates.
3+
4+
// @has 'foo/struct.Foo.html'
5+
// @has '-' '//*[@id="deref-methods-PathBuf"]' 'Methods from Deref<Target = PathBuf>'
6+
// @has '-' '//*[@class="impl-items"]//*[@id="method.as_path"]' 'pub fn as_path(&self)'
7+
// @has '-' '//*[@id="deref-methods-Path"]' 'Methods from Deref<Target = Path>'
8+
// @has '-' '//*[@class="impl-items"]//*[@id="method.exists"]' 'pub fn exists(&self)'
9+
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-PathBuf"]' 'Methods from Deref<Target=PathBuf>'
10+
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.as_path"]' 'as_path'
11+
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Path"]' 'Methods from Deref<Target=Path>'
12+
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.exists"]' 'exists'
13+
14+
#![crate_name = "foo"]
15+
16+
use std::ops::Deref;
17+
use std::path::PathBuf;
18+
19+
pub struct Foo(PathBuf);
20+
21+
impl Deref for Foo {
22+
type Target = PathBuf;
23+
fn deref(&self) -> &PathBuf { &self.0 }
24+
}

src/test/rustdoc/deref-recursive.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// #26207: Show all methods reachable via Deref impls, recursing through multiple dereferencing
2+
// levels if needed.
3+
4+
// @has 'foo/struct.Foo.html'
5+
// @has '-' '//*[@id="deref-methods-Bar"]' 'Methods from Deref<Target = Bar>'
6+
// @has '-' '//*[@class="impl-items"]//*[@id="method.bar"]' 'pub fn bar(&self)'
7+
// @has '-' '//*[@id="deref-methods-Baz"]' 'Methods from Deref<Target = Baz>'
8+
// @has '-' '//*[@class="impl-items"]//*[@id="method.baz"]' 'pub fn baz(&self)'
9+
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Bar"]' 'Methods from Deref<Target=Bar>'
10+
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.bar"]' 'bar'
11+
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Baz"]' 'Methods from Deref<Target=Baz>'
12+
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.baz"]' 'baz'
13+
14+
#![crate_name = "foo"]
15+
16+
use std::ops::Deref;
17+
18+
pub struct Foo(Bar);
19+
pub struct Bar(Baz);
20+
pub struct Baz;
21+
22+
impl Deref for Foo {
23+
type Target = Bar;
24+
fn deref(&self) -> &Bar { &self.0 }
25+
}
26+
27+
impl Deref for Bar {
28+
type Target = Baz;
29+
fn deref(&self) -> &Baz { &self.0 }
30+
}
31+
32+
impl Bar {
33+
/// This appears under `Foo` methods
34+
pub fn bar(&self) {}
35+
}
36+
37+
impl Baz {
38+
/// This should also appear in `Foo` methods when recursing
39+
pub fn baz(&self) {}
40+
}

src/test/rustdoc/deref-typedef.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
#![crate_name = "foo"]
22

33
// @has 'foo/struct.Bar.html'
4-
// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref<Target = FooJ>'
4+
// @has '-' '//*[@id="deref-methods-FooJ"]' 'Methods from Deref<Target = FooJ>'
55
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_a"]' 'pub fn foo_a(&self)'
66
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_b"]' 'pub fn foo_b(&self)'
77
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)'
88
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_j"]' 'pub fn foo_j(&self)'
9-
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods"]' 'Methods from Deref<Target=FooJ>'
9+
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-FooJ"]' 'Methods from Deref<Target=FooJ>'
1010
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_a"]' 'foo_a'
1111
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_b"]' 'foo_b'
1212
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_c"]' 'foo_c'

src/test/rustdoc/recursive-deref-sidebar.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ impl Deref for A {
1515
fn deref(&self) -> &B { todo!() }
1616
}
1717

18-
// @!has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_c'
18+
// @has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_c'
1919
impl Deref for B {
2020
type Target = C;
2121
fn deref(&self) -> &C { todo!() }

src/test/rustdoc/recursive-deref.rs

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use std::ops::Deref;
22

3+
// Cyclic deref with the parent (which is not the top parent).
34
pub struct A;
45
pub struct B;
6+
pub struct C;
57

68
// @has recursive_deref/struct.A.html '//h3[@class="code-header in-band"]' 'impl Deref for A'
79
impl Deref for A {
@@ -14,7 +16,80 @@ impl Deref for A {
1416

1517
// @has recursive_deref/struct.B.html '//h3[@class="code-header in-band"]' 'impl Deref for B'
1618
impl Deref for B {
17-
type Target = A;
19+
type Target = C;
20+
21+
fn deref(&self) -> &Self::Target {
22+
panic!()
23+
}
24+
}
25+
26+
// @has recursive_deref/struct.C.html '//h3[@class="code-header in-band"]' 'impl Deref for C'
27+
impl Deref for C {
28+
type Target = B;
29+
30+
fn deref(&self) -> &Self::Target {
31+
panic!()
32+
}
33+
}
34+
35+
// Cyclic deref with the grand-parent (which is not the top parent).
36+
pub struct D;
37+
pub struct E;
38+
pub struct F;
39+
pub struct G;
40+
41+
// @has recursive_deref/struct.D.html '//h3[@class="code-header in-band"]' 'impl Deref for D'
42+
impl Deref for D {
43+
type Target = E;
44+
45+
fn deref(&self) -> &Self::Target {
46+
panic!()
47+
}
48+
}
49+
50+
// @has recursive_deref/struct.E.html '//h3[@class="code-header in-band"]' 'impl Deref for E'
51+
impl Deref for E {
52+
type Target = F;
53+
54+
fn deref(&self) -> &Self::Target {
55+
panic!()
56+
}
57+
}
58+
59+
// @has recursive_deref/struct.F.html '//h3[@class="code-header in-band"]' 'impl Deref for F'
60+
impl Deref for F {
61+
type Target = G;
62+
63+
fn deref(&self) -> &Self::Target {
64+
panic!()
65+
}
66+
}
67+
68+
// @has recursive_deref/struct.G.html '//h3[@class="code-header in-band"]' 'impl Deref for G'
69+
impl Deref for G {
70+
type Target = E;
71+
72+
fn deref(&self) -> &Self::Target {
73+
panic!()
74+
}
75+
}
76+
77+
// Cyclic deref with top parent.
78+
pub struct H;
79+
pub struct I;
80+
81+
// @has recursive_deref/struct.H.html '//h3[@class="code-header in-band"]' 'impl Deref for H'
82+
impl Deref for H {
83+
type Target = I;
84+
85+
fn deref(&self) -> &Self::Target {
86+
panic!()
87+
}
88+
}
89+
90+
// @has recursive_deref/struct.I.html '//h3[@class="code-header in-band"]' 'impl Deref for I'
91+
impl Deref for I {
92+
type Target = H;
1893

1994
fn deref(&self) -> &Self::Target {
2095
panic!()

0 commit comments

Comments
 (0)