diff options
| author | binarycat <binarycat@envs.net> | 2025-03-16 15:42:04 -0500 |
|---|---|---|
| committer | binarycat <binarycat@envs.net> | 2025-03-22 12:47:05 -0500 |
| commit | b46412f6d7fde0c24780b0808aa7aefbc18d9e1e (patch) | |
| tree | 97d04d722b6eac31dd023b54928a128b717bfd58 /src/librustdoc/html | |
| parent | d497e43a1664eaad5e5850f5f8c11c9e16f5ef66 (diff) | |
| download | rust-b46412f6d7fde0c24780b0808aa7aefbc18d9e1e.tar.gz rust-b46412f6d7fde0c24780b0808aa7aefbc18d9e1e.zip | |
rustdoc: be more strict about "Methods from Deref"
hack: is_doc_subtype_of always returns true for TyAlias it's worth noting that this function is only used in the handling of "Methods from Deref", and we were previously assuming all generic parameters were meaningless, so this is still an improvment from the status quo. this change means that we will have strictly less false positives without adding any new false negitives. Co-authored-by: Guillaume Gomez <guillaume1.gomez@gmail.com>
Diffstat (limited to 'src/librustdoc/html')
| -rw-r--r-- | src/librustdoc/html/render/mod.rs | 16 | ||||
| -rw-r--r-- | src/librustdoc/html/render/sidebar.rs | 5 |
2 files changed, 18 insertions, 3 deletions
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index b2ad2fa773a..900de90c736 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -89,7 +89,7 @@ pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display { /// Specifies whether rendering directly implemented trait items or ones from a certain Deref /// impl. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub(crate) enum AssocItemRender<'a> { All, DerefFor { trait_: &'a clean::Path, type_: &'a clean::Type, deref_mut_: bool }, @@ -1296,7 +1296,8 @@ fn render_assoc_items_inner( info!("Documenting associated items of {:?}", containing_item.name); let cache = &cx.shared.cache; let Some(v) = cache.impls.get(&it) else { return }; - let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none()); + let (mut non_trait, traits): (Vec<_>, _) = + v.iter().partition(|i| i.inner_impl().trait_.is_none()); if !non_trait.is_empty() { let mut close_tags = <Vec<&str>>::with_capacity(1); let mut tmp_buf = String::new(); @@ -1314,6 +1315,16 @@ fn render_assoc_items_inner( AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => { let id = cx.derive_id(small_url_encode(format!("deref-methods-{:#}", type_.print(cx)))); + // the `impls.get` above only looks at the outermost type, + // and the Deref impl may only be implemented for certain + // values of generic parameters. + // for example, if an item impls `Deref<[u8]>`, + // we should not show methods from `[MaybeUninit<u8>]`. + // this `retain` filters out any instances where + // the types do not line up perfectly. + non_trait.retain(|impl_| { + type_.is_doc_subtype_of(&impl_.inner_impl().for_, &cx.shared.cache) + }); let derived_id = cx.derive_id(&id); close_tags.push("</details>"); write_str( @@ -1392,6 +1403,7 @@ fn render_assoc_items_inner( } } +/// `derefs` is the set of all deref targets that have already been handled. fn render_deref_methods( mut w: impl Write, cx: &Context<'_>, diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 3130815af0b..9c78dcdc571 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -533,7 +533,10 @@ fn sidebar_deref_methods<'a>( debug!("found inner_impl: {impls:?}"); let mut ret = impls .iter() - .filter(|i| i.inner_impl().trait_.is_none()) + .filter(|i| { + i.inner_impl().trait_.is_none() + && real_target.is_doc_subtype_of(&i.inner_impl().for_, &c) + }) .flat_map(|i| get_methods(i.inner_impl(), true, used_links, deref_mut, cx.tcx())) .collect::<Vec<_>>(); if !ret.is_empty() { |
