use rustc_middle::ty;
use rustc_middle::ty::TyCtxt;
use rustc_span::{
- symbol::{kw, sym, Symbol},
+ symbol::{sym, Symbol},
BytePos, FileName, RealFileName,
};
use serde::ser::SerializeSeq;
/// A type used for the search index.
#[derive(Debug)]
pub(crate) struct RenderType {
- name: Option<String>,
- generics: Option<Vec<TypeWithKind>>,
+ id: Option<RenderTypeId>,
+ generics: Option<Vec<RenderType>>,
}
-/// Full type of functions/methods in the search index.
-#[derive(Debug)]
-pub(crate) struct IndexItemFunctionType {
- inputs: Vec<TypeWithKind>,
- output: Vec<TypeWithKind>,
-}
-
-impl Serialize for IndexItemFunctionType {
+impl Serialize for RenderType {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
- // If we couldn't figure out a type, just write `null`.
- let has_missing = self.inputs.iter().chain(self.output.iter()).any(|i| i.ty.name.is_none());
- if has_missing {
- serializer.serialize_none()
- } else {
+ let id = match &self.id {
+ // 0 is a sentinel, everything else is one-indexed
+ None => 0,
+ Some(RenderTypeId::Index(idx)) => idx + 1,
+ _ => panic!("must convert render types to indexes before serializing"),
+ };
+ if let Some(generics) = &self.generics {
let mut seq = serializer.serialize_seq(None)?;
- seq.serialize_element(&self.inputs)?;
- match self.output.as_slice() {
- [] => {}
- [one] => seq.serialize_element(one)?,
- all => seq.serialize_element(all)?,
- }
+ seq.serialize_element(&id)?;
+ seq.serialize_element(generics)?;
seq.end()
+ } else {
+ id.serialize(serializer)
}
}
}
-#[derive(Debug)]
-pub(crate) struct TypeWithKind {
- ty: RenderType,
- kind: ItemType,
+#[derive(Clone, Debug)]
+pub(crate) enum RenderTypeId {
+ DefId(DefId),
+ Primitive(clean::PrimitiveType),
+ Index(usize),
}
-impl From<(RenderType, ItemType)> for TypeWithKind {
- fn from(x: (RenderType, ItemType)) -> TypeWithKind {
- TypeWithKind { ty: x.0, kind: x.1 }
- }
+/// Full type of functions/methods in the search index.
+#[derive(Debug)]
+pub(crate) struct IndexItemFunctionType {
+ inputs: Vec<RenderType>,
+ output: Vec<RenderType>,
}
-impl Serialize for TypeWithKind {
+impl Serialize for IndexItemFunctionType {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
- let mut seq = serializer.serialize_seq(None)?;
- seq.serialize_element(&self.ty.name)?;
- seq.serialize_element(&self.kind)?;
- if let Some(generics) = &self.ty.generics {
- seq.serialize_element(generics)?;
+ // If we couldn't figure out a type, just write `0`.
+ let has_missing = self
+ .inputs
+ .iter()
+ .chain(self.output.iter())
+ .any(|i| i.id.is_none() && i.generics.is_none());
+ if has_missing {
+ 0.serialize(serializer)
+ } else {
+ let mut seq = serializer.serialize_seq(None)?;
+ match &self.inputs[..] {
+ [one] if one.generics.is_none() => seq.serialize_element(one)?,
+ _ => seq.serialize_element(&self.inputs)?,
+ }
+ match &self.output[..] {
+ [] => {}
+ [one] if one.generics.is_none() => seq.serialize_element(one)?,
+ _ => seq.serialize_element(&self.output)?,
+ }
+ seq.end()
}
- seq.end()
}
}
&[],
ImplRenderingParameters {
show_def_docs: true,
- is_on_foreign_type: false,
show_default_items: true,
show_non_assoc_items: true,
toggle_open_by_default,
&[],
ImplRenderingParameters {
show_def_docs: true,
- is_on_foreign_type: false,
show_default_items: true,
show_non_assoc_items: true,
toggle_open_by_default: true,
#[derive(Clone, Copy, Debug)]
struct ImplRenderingParameters {
show_def_docs: bool,
- is_on_foreign_type: bool,
show_default_items: bool,
/// Whether or not to show methods.
show_non_assoc_items: bool,
parent,
rendering_params.show_def_docs,
use_absolute,
- rendering_params.is_on_foreign_type,
aliases,
);
if toggled {
containing_item: &clean::Item,
show_def_docs: bool,
use_absolute: Option<bool>,
- is_on_foreign_type: bool,
// This argument is used to reference same type with different paths to avoid duplication
// in documentation pages for trait with automatic implementations like "Send" and "Sync".
aliases: &[String],
) {
- let id = cx.derive_id(match i.inner_impl().trait_ {
- Some(ref t) => {
- if is_on_foreign_type {
- get_id_for_impl_on_foreign_type(&i.inner_impl().for_, t, cx)
- } else {
- format!("impl-{}", small_url_encode(format!("{:#}", t.print(cx))))
- }
- }
- None => "impl".to_string(),
- });
+ let id =
+ cx.derive_id(get_id_for_impl(&i.inner_impl().for_, i.inner_impl().trait_.as_ref(), cx));
let aliases = if aliases.is_empty() {
String::new()
} else {
}
fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
- let parentlen = cx.current.len() - if it.is_mod() { 1 } else { 0 };
-
if it.is_struct()
|| it.is_trait()
|| it.is_primitive()
write!(buffer, "<h2 class=\"location\"><a href=\"index.html\">In {}</a></h2>", path);
}
- // Sidebar refers to the enclosing module, not this module.
- let relpath = if it.is_mod() && parentlen != 0 { "./" } else { "" };
- write!(
- buffer,
- "<div id=\"sidebar-vars\" data-name=\"{name}\" data-ty=\"{ty}\" data-relpath=\"{path}\">\
- </div>",
- name = it.name.unwrap_or(kw::Empty),
- ty = it.type_(),
- path = relpath
- );
- write!(
- buffer,
- "<script defer src=\"{}sidebar-items{}.js\"></script>",
- relpath, cx.shared.resource_suffix
- );
// Closes sidebar-elems div.
buffer.write_str("</div>");
}
let mut ret = impls
.iter()
.filter_map(|it| {
- if let Some(ref i) = it.inner_impl().trait_ {
- let i_display = format!("{:#}", i.print(cx));
- let out = Escape(&i_display);
- let encoded =
- id_map.derive(small_url_encode(format!("impl-{:#}", i.print(cx))));
- 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 }
- } else {
- None
- }
+ 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();
}
}
-fn get_id_for_impl_on_foreign_type(
- for_: &clean::Type,
- trait_: &clean::Path,
- cx: &Context<'_>,
-) -> String {
- small_url_encode(format!("impl-{:#}-for-{:#}", trait_.print(cx), for_.print(cx)))
+fn get_id_for_impl(for_: &clean::Type, trait_: Option<&clean::Path>, cx: &Context<'_>) -> String {
+ match trait_ {
+ Some(t) => small_url_encode(format!("impl-{:#}-for-{:#}", t.print(cx), for_.print(cx))),
+ None => small_url_encode(format!("impl-{:#}", for_.print(cx))),
+ }
}
fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String, String)> {
i.trait_.as_ref().map(|trait_| {
// Alternative format produces no URLs,
// so this parameter does nothing.
- (
- format!("{:#}", i.for_.print(cx)),
- get_id_for_impl_on_foreign_type(&i.for_, trait_, cx),
- )
+ (format!("{:#}", i.for_.print(cx)), get_id_for_impl(&i.for_, Some(trait_), cx))
})
}
_ => None,
ItemType::ProcAttribute => ItemSection::AttributeMacros,
ItemType::ProcDerive => ItemSection::DeriveMacros,
ItemType::TraitAlias => ItemSection::TraitAliases,
- ItemType::Generic => unreachable!(),
}
}