Print only blanket implementations on reference primitive type
This commit is contained in:
parent
6c585fcce5
commit
900cda2043
2 changed files with 133 additions and 67 deletions
|
@ -616,7 +616,7 @@ fn short_item_info(
|
||||||
pub(crate) fn render_impls(
|
pub(crate) fn render_impls(
|
||||||
cx: &mut Context<'_>,
|
cx: &mut Context<'_>,
|
||||||
w: &mut Buffer,
|
w: &mut Buffer,
|
||||||
impls: &[&&Impl],
|
impls: &[&Impl],
|
||||||
containing_item: &clean::Item,
|
containing_item: &clean::Item,
|
||||||
toggle_open_by_default: bool,
|
toggle_open_by_default: bool,
|
||||||
) {
|
) {
|
||||||
|
@ -1039,9 +1039,9 @@ pub(crate) fn render_all_impls(
|
||||||
w: &mut Buffer,
|
w: &mut Buffer,
|
||||||
cx: &mut Context<'_>,
|
cx: &mut Context<'_>,
|
||||||
containing_item: &clean::Item,
|
containing_item: &clean::Item,
|
||||||
concrete: &[&&Impl],
|
concrete: &[&Impl],
|
||||||
synthetic: &[&&Impl],
|
synthetic: &[&Impl],
|
||||||
blanket_impl: &[&&Impl],
|
blanket_impl: &[&Impl],
|
||||||
) {
|
) {
|
||||||
let mut impls = Buffer::empty_from(w);
|
let mut impls = Buffer::empty_from(w);
|
||||||
render_impls(cx, &mut impls, concrete, containing_item, true);
|
render_impls(cx, &mut impls, concrete, containing_item, true);
|
||||||
|
@ -1158,9 +1158,9 @@ fn render_assoc_items_inner(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) =
|
let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
|
||||||
traits.iter().partition(|t| t.inner_impl().kind.is_auto());
|
traits.into_iter().partition(|t| t.inner_impl().kind.is_auto());
|
||||||
let (blanket_impl, concrete): (Vec<&&Impl>, _) =
|
let (blanket_impl, concrete): (Vec<&Impl>, _) =
|
||||||
concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket());
|
concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket());
|
||||||
|
|
||||||
render_all_impls(w, cx, containing_item, &concrete, &synthetic, &blanket_impl);
|
render_all_impls(w, cx, containing_item, &concrete, &synthetic, &blanket_impl);
|
||||||
|
@ -1968,6 +1968,70 @@ fn small_url_encode(s: String) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn sidebar_render_assoc_items(
|
||||||
|
cx: &Context<'_>,
|
||||||
|
out: &mut Buffer,
|
||||||
|
id_map: &mut IdMap,
|
||||||
|
concrete: Vec<&Impl>,
|
||||||
|
synthetic: Vec<&Impl>,
|
||||||
|
blanket_impl: Vec<&Impl>,
|
||||||
|
) {
|
||||||
|
let format_impls = |impls: Vec<&Impl>, id_map: &mut IdMap| {
|
||||||
|
let mut links = FxHashSet::default();
|
||||||
|
|
||||||
|
let mut ret = impls
|
||||||
|
.iter()
|
||||||
|
.filter_map(|it| {
|
||||||
|
let trait_ = it.inner_impl().trait_.as_ref()?;
|
||||||
|
let encoded =
|
||||||
|
id_map.derive(get_id_for_impl(&it.inner_impl().for_, Some(trait_), cx));
|
||||||
|
|
||||||
|
let i_display = format!("{:#}", trait_.print(cx));
|
||||||
|
let out = Escape(&i_display);
|
||||||
|
let prefix = match it.inner_impl().polarity {
|
||||||
|
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
|
||||||
|
ty::ImplPolarity::Negative => "!",
|
||||||
|
};
|
||||||
|
let generated = format!("<a href=\"#{}\">{}{}</a>", encoded, prefix, out);
|
||||||
|
if links.insert(generated.clone()) { Some(generated) } else { None }
|
||||||
|
})
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
ret.sort();
|
||||||
|
ret
|
||||||
|
};
|
||||||
|
|
||||||
|
let concrete_format = format_impls(concrete, id_map);
|
||||||
|
let synthetic_format = format_impls(synthetic, id_map);
|
||||||
|
let blanket_format = format_impls(blanket_impl, id_map);
|
||||||
|
|
||||||
|
if !concrete_format.is_empty() {
|
||||||
|
print_sidebar_block(
|
||||||
|
out,
|
||||||
|
"trait-implementations",
|
||||||
|
"Trait Implementations",
|
||||||
|
concrete_format.iter(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !synthetic_format.is_empty() {
|
||||||
|
print_sidebar_block(
|
||||||
|
out,
|
||||||
|
"synthetic-implementations",
|
||||||
|
"Auto Trait Implementations",
|
||||||
|
synthetic_format.iter(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !blanket_format.is_empty() {
|
||||||
|
print_sidebar_block(
|
||||||
|
out,
|
||||||
|
"blanket-implementations",
|
||||||
|
"Blanket Implementations",
|
||||||
|
blanket_format.iter(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
|
fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
|
||||||
let did = it.item_id.expect_def_id();
|
let did = it.item_id.expect_def_id();
|
||||||
let cache = cx.cache();
|
let cache = cx.cache();
|
||||||
|
@ -2016,65 +2080,12 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
|
||||||
sidebar_deref_methods(cx, out, impl_, v, &mut derefs, &mut used_links);
|
sidebar_deref_methods(cx, out, impl_, v, &mut derefs, &mut used_links);
|
||||||
}
|
}
|
||||||
|
|
||||||
let format_impls = |impls: Vec<&Impl>, id_map: &mut IdMap| {
|
|
||||||
let mut links = FxHashSet::default();
|
|
||||||
|
|
||||||
let mut ret = impls
|
|
||||||
.iter()
|
|
||||||
.filter_map(|it| {
|
|
||||||
let trait_ = it.inner_impl().trait_.as_ref()?;
|
|
||||||
let encoded =
|
|
||||||
id_map.derive(get_id_for_impl(&it.inner_impl().for_, Some(trait_), cx));
|
|
||||||
|
|
||||||
let i_display = format!("{:#}", trait_.print(cx));
|
|
||||||
let out = Escape(&i_display);
|
|
||||||
let prefix = match it.inner_impl().polarity {
|
|
||||||
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
|
|
||||||
ty::ImplPolarity::Negative => "!",
|
|
||||||
};
|
|
||||||
let generated = format!("<a href=\"#{}\">{}{}</a>", encoded, prefix, out);
|
|
||||||
if links.insert(generated.clone()) { Some(generated) } else { None }
|
|
||||||
})
|
|
||||||
.collect::<Vec<String>>();
|
|
||||||
ret.sort();
|
|
||||||
ret
|
|
||||||
};
|
|
||||||
|
|
||||||
let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
|
let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
|
||||||
v.iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_auto());
|
v.iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_auto());
|
||||||
let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) =
|
let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) =
|
||||||
concrete.into_iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_blanket());
|
concrete.into_iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_blanket());
|
||||||
|
|
||||||
let concrete_format = format_impls(concrete, &mut id_map);
|
sidebar_render_assoc_items(cx, out, &mut id_map, concrete, synthetic, blanket_impl);
|
||||||
let synthetic_format = format_impls(synthetic, &mut id_map);
|
|
||||||
let blanket_format = format_impls(blanket_impl, &mut id_map);
|
|
||||||
|
|
||||||
if !concrete_format.is_empty() {
|
|
||||||
print_sidebar_block(
|
|
||||||
out,
|
|
||||||
"trait-implementations",
|
|
||||||
"Trait Implementations",
|
|
||||||
concrete_format.iter(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !synthetic_format.is_empty() {
|
|
||||||
print_sidebar_block(
|
|
||||||
out,
|
|
||||||
"synthetic-implementations",
|
|
||||||
"Auto Trait Implementations",
|
|
||||||
synthetic_format.iter(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !blanket_format.is_empty() {
|
|
||||||
print_sidebar_block(
|
|
||||||
out,
|
|
||||||
"blanket-implementations",
|
|
||||||
"Blanket Implementations",
|
|
||||||
blanket_format.iter(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2344,9 +2355,54 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean
|
||||||
buf.push_str("</section>")
|
buf.push_str("</section>")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the list of implementations for the primitive reference type, filtering out any
|
||||||
|
/// implementations that are on concrete or partially generic types, only keeping implementations
|
||||||
|
/// of the form `impl<T> Trait for &T`.
|
||||||
|
pub(crate) fn get_filtered_impls_for_reference<'a>(
|
||||||
|
shared: &'a Rc<SharedContext<'_>>,
|
||||||
|
it: &clean::Item,
|
||||||
|
) -> (Vec<&'a Impl>, Vec<&'a Impl>, Vec<&'a Impl>) {
|
||||||
|
let def_id = it.item_id.expect_def_id();
|
||||||
|
// If the reference primitive is somehow not defined, exit early.
|
||||||
|
let Some(v) = shared.cache.impls.get(&def_id) else { return (Vec::new(), Vec::new(), Vec::new()) };
|
||||||
|
// Since there is no "direct implementation" on the reference primitive type, we filter out
|
||||||
|
// every implementation which isn't a trait implementation.
|
||||||
|
let traits: Vec<_> = v.iter().filter(|i| i.inner_impl().trait_.is_some()).collect();
|
||||||
|
let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
|
||||||
|
traits.into_iter().partition(|t| t.inner_impl().kind.is_auto());
|
||||||
|
|
||||||
|
let (blanket_impl, concrete): (Vec<&Impl>, _) =
|
||||||
|
concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket());
|
||||||
|
// Now we keep only references over full generic types.
|
||||||
|
let concrete: Vec<_> = concrete
|
||||||
|
.into_iter()
|
||||||
|
.filter(|t| match t.inner_impl().for_ {
|
||||||
|
clean::Type::BorrowedRef { ref type_, .. } => type_.is_full_generic(),
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
(concrete, synthetic, blanket_impl)
|
||||||
|
}
|
||||||
|
|
||||||
fn sidebar_primitive(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) {
|
fn sidebar_primitive(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) {
|
||||||
let mut sidebar = Buffer::new();
|
let mut sidebar = Buffer::new();
|
||||||
sidebar_assoc_items(cx, &mut sidebar, it);
|
|
||||||
|
if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) {
|
||||||
|
sidebar_assoc_items(cx, &mut sidebar, it);
|
||||||
|
} else {
|
||||||
|
let shared = Rc::clone(&cx.shared);
|
||||||
|
let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&shared, it);
|
||||||
|
|
||||||
|
sidebar_render_assoc_items(
|
||||||
|
cx,
|
||||||
|
&mut sidebar,
|
||||||
|
&mut IdMap::new(),
|
||||||
|
concrete,
|
||||||
|
synthetic,
|
||||||
|
blanket_impl,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if !sidebar.is_empty() {
|
if !sidebar.is_empty() {
|
||||||
write!(buf, "<section>{}</section>", sidebar.into_inner());
|
write!(buf, "<section>{}</section>", sidebar.into_inner());
|
||||||
|
|
|
@ -16,10 +16,10 @@ use std::fmt;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_section,
|
collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference,
|
||||||
notable_traits_decl, render_assoc_item, render_assoc_items, render_attributes_in_code,
|
item_ty_to_section, notable_traits_decl, render_all_impls, render_assoc_item,
|
||||||
render_attributes_in_pre, render_impl, render_rightside, render_stability_since_raw,
|
render_assoc_items, render_attributes_in_code, render_attributes_in_pre, render_impl,
|
||||||
AssocItemLink, Context, ImplRenderingParameters,
|
render_rightside, render_stability_since_raw, AssocItemLink, Context, ImplRenderingParameters,
|
||||||
};
|
};
|
||||||
use crate::clean;
|
use crate::clean;
|
||||||
use crate::config::ModuleSorting;
|
use crate::config::ModuleSorting;
|
||||||
|
@ -1371,8 +1371,18 @@ fn item_proc_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, m: &c
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_primitive(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
|
fn item_primitive(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
|
||||||
|
let def_id = it.item_id.expect_def_id();
|
||||||
document(w, cx, it, None, HeadingOffset::H2);
|
document(w, cx, it, None, HeadingOffset::H2);
|
||||||
render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
|
if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) {
|
||||||
|
render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
|
||||||
|
} else {
|
||||||
|
// We handle the "reference" primitive type on its own because we only want to list
|
||||||
|
// implementations on generic types.
|
||||||
|
let shared = Rc::clone(&cx.shared);
|
||||||
|
let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&shared, it);
|
||||||
|
|
||||||
|
render_all_impls(w, cx, it, &concrete, &synthetic, &blanket_impl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &clean::Constant) {
|
fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &clean::Constant) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue