Add tests for recursive deref
This commit is contained in:
parent
8a473ca346
commit
0c38f31bf2
@ -81,8 +81,8 @@ 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_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait()
|
||||
if trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait()
|
||||
&& cleaner.keep_impl(for_)
|
||||
{
|
||||
let target = items
|
||||
.iter()
|
||||
@ -221,8 +221,11 @@ impl BadImplStripper {
|
||||
true
|
||||
} else if let Some(prim) = ty.primitive_type() {
|
||||
self.prims.contains(&prim)
|
||||
} else if let Some(did) = ty.def_id_no_primitives() {
|
||||
self.keep_impl_with_def_id(did.into())
|
||||
} else if ty.def_id_no_primitives().is_some() {
|
||||
// We want to keep *ALL* deref implementations in case some of them are used in
|
||||
// the current crate.
|
||||
// FIXME: Try to filter the one actually used...
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
19
src/test/rustdoc-ui/recursive-deref-ice.rs
Normal file
19
src/test/rustdoc-ui/recursive-deref-ice.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// check-pass
|
||||
|
||||
// ICE found in https://github.com/rust-lang/rust/issues/83123
|
||||
|
||||
pub struct Attribute;
|
||||
|
||||
pub struct Map<'hir> {}
|
||||
impl<'hir> Map<'hir> {
|
||||
pub fn attrs(&self) -> &'hir [Attribute] { &[] }
|
||||
}
|
||||
|
||||
pub struct List<T>(T);
|
||||
|
||||
impl<T> std::ops::Deref for List<T> {
|
||||
type Target = [T];
|
||||
fn deref(&self) -> &[T] {
|
||||
&[]
|
||||
}
|
||||
}
|
24
src/test/rustdoc/deref-recursive-pathbuf.rs
Normal file
24
src/test/rustdoc/deref-recursive-pathbuf.rs
Normal file
@ -0,0 +1,24 @@
|
||||
// #26207: Show all methods reachable via Deref impls, recursing through multiple dereferencing
|
||||
// levels and across multiple crates.
|
||||
|
||||
// @has 'foo/struct.Foo.html'
|
||||
// @has '-' '//*[@id="deref-methods-PathBuf"]' 'Methods from Deref<Target = PathBuf>'
|
||||
// @has '-' '//*[@class="impl-items"]//*[@id="method.as_path"]' 'pub fn as_path(&self)'
|
||||
// @has '-' '//*[@id="deref-methods-Path"]' 'Methods from Deref<Target = Path>'
|
||||
// @has '-' '//*[@class="impl-items"]//*[@id="method.exists"]' 'pub fn exists(&self)'
|
||||
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-PathBuf"]' 'Methods from Deref<Target=PathBuf>'
|
||||
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.as_path"]' 'as_path'
|
||||
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Path"]' 'Methods from Deref<Target=Path>'
|
||||
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.exists"]' 'exists'
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub struct Foo(PathBuf);
|
||||
|
||||
impl Deref for Foo {
|
||||
type Target = PathBuf;
|
||||
fn deref(&self) -> &PathBuf { &self.0 }
|
||||
}
|
40
src/test/rustdoc/deref-recursive.rs
Normal file
40
src/test/rustdoc/deref-recursive.rs
Normal file
@ -0,0 +1,40 @@
|
||||
// #26207: Show all methods reachable via Deref impls, recursing through multiple dereferencing
|
||||
// levels if needed.
|
||||
|
||||
// @has 'foo/struct.Foo.html'
|
||||
// @has '-' '//*[@id="deref-methods-Bar"]' 'Methods from Deref<Target = Bar>'
|
||||
// @has '-' '//*[@class="impl-items"]//*[@id="method.bar"]' 'pub fn bar(&self)'
|
||||
// @has '-' '//*[@id="deref-methods-Baz"]' 'Methods from Deref<Target = Baz>'
|
||||
// @has '-' '//*[@class="impl-items"]//*[@id="method.baz"]' 'pub fn baz(&self)'
|
||||
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Bar"]' 'Methods from Deref<Target=Bar>'
|
||||
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.bar"]' 'bar'
|
||||
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Baz"]' 'Methods from Deref<Target=Baz>'
|
||||
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.baz"]' 'baz'
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
pub struct Foo(Bar);
|
||||
pub struct Bar(Baz);
|
||||
pub struct Baz;
|
||||
|
||||
impl Deref for Foo {
|
||||
type Target = Bar;
|
||||
fn deref(&self) -> &Bar { &self.0 }
|
||||
}
|
||||
|
||||
impl Deref for Bar {
|
||||
type Target = Baz;
|
||||
fn deref(&self) -> &Baz { &self.0 }
|
||||
}
|
||||
|
||||
impl Bar {
|
||||
/// This appears under `Foo` methods
|
||||
pub fn bar(&self) {}
|
||||
}
|
||||
|
||||
impl Baz {
|
||||
/// This should also appear in `Foo` methods when recursing
|
||||
pub fn baz(&self) {}
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// @has 'foo/struct.Bar.html'
|
||||
// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref<Target = FooJ>'
|
||||
// @has '-' '//*[@id="deref-methods-FooJ"]' 'Methods from Deref<Target = FooJ>'
|
||||
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_a"]' 'pub fn foo_a(&self)'
|
||||
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_b"]' 'pub fn foo_b(&self)'
|
||||
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)'
|
||||
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_j"]' 'pub fn foo_j(&self)'
|
||||
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods"]' 'Methods from Deref<Target=FooJ>'
|
||||
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-FooJ"]' 'Methods from Deref<Target=FooJ>'
|
||||
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_a"]' 'foo_a'
|
||||
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_b"]' 'foo_b'
|
||||
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_c"]' 'foo_c'
|
||||
|
@ -15,7 +15,7 @@ impl Deref for A {
|
||||
fn deref(&self) -> &B { todo!() }
|
||||
}
|
||||
|
||||
// @!has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_c'
|
||||
// @has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_c'
|
||||
impl Deref for B {
|
||||
type Target = C;
|
||||
fn deref(&self) -> &C { todo!() }
|
||||
|
@ -1,7 +1,9 @@
|
||||
use std::ops::Deref;
|
||||
|
||||
// Cyclic deref with the parent (which is not the top parent).
|
||||
pub struct A;
|
||||
pub struct B;
|
||||
pub struct C;
|
||||
|
||||
// @has recursive_deref/struct.A.html '//h3[@class="code-header in-band"]' 'impl Deref for A'
|
||||
impl Deref for A {
|
||||
@ -14,7 +16,80 @@ impl Deref for A {
|
||||
|
||||
// @has recursive_deref/struct.B.html '//h3[@class="code-header in-band"]' 'impl Deref for B'
|
||||
impl Deref for B {
|
||||
type Target = A;
|
||||
type Target = C;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
// @has recursive_deref/struct.C.html '//h3[@class="code-header in-band"]' 'impl Deref for C'
|
||||
impl Deref for C {
|
||||
type Target = B;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
// Cyclic deref with the grand-parent (which is not the top parent).
|
||||
pub struct D;
|
||||
pub struct E;
|
||||
pub struct F;
|
||||
pub struct G;
|
||||
|
||||
// @has recursive_deref/struct.D.html '//h3[@class="code-header in-band"]' 'impl Deref for D'
|
||||
impl Deref for D {
|
||||
type Target = E;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
// @has recursive_deref/struct.E.html '//h3[@class="code-header in-band"]' 'impl Deref for E'
|
||||
impl Deref for E {
|
||||
type Target = F;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
// @has recursive_deref/struct.F.html '//h3[@class="code-header in-band"]' 'impl Deref for F'
|
||||
impl Deref for F {
|
||||
type Target = G;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
// @has recursive_deref/struct.G.html '//h3[@class="code-header in-band"]' 'impl Deref for G'
|
||||
impl Deref for G {
|
||||
type Target = E;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
// Cyclic deref with top parent.
|
||||
pub struct H;
|
||||
pub struct I;
|
||||
|
||||
// @has recursive_deref/struct.H.html '//h3[@class="code-header in-band"]' 'impl Deref for H'
|
||||
impl Deref for H {
|
||||
type Target = I;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
// @has recursive_deref/struct.I.html '//h3[@class="code-header in-band"]' 'impl Deref for I'
|
||||
impl Deref for I {
|
||||
type Target = H;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
panic!()
|
||||
|
Loading…
x
Reference in New Issue
Block a user