Skip to content

Commit ac77084

Browse files
committed
rustdoc-search: add support for associated types
1 parent 64fa0c3 commit ac77084

File tree

14 files changed

+979
-93
lines changed

14 files changed

+979
-93
lines changed

src/librustdoc/clean/types.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1632,6 +1632,13 @@ impl Type {
16321632
}
16331633
}
16341634

1635+
pub(crate) fn bindings(&self) -> Option<&[TypeBinding]> {
1636+
match self {
1637+
Type::Path { path, .. } => path.bindings(),
1638+
_ => None,
1639+
}
1640+
}
1641+
16351642
pub(crate) fn is_full_generic(&self) -> bool {
16361643
matches!(self, Type::Generic(_))
16371644
}
@@ -2207,6 +2214,39 @@ impl GenericArgs {
22072214
GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
22082215
}
22092216
}
2217+
pub(crate) fn bindings<'a>(&'a self) -> Box<dyn Iterator<Item = TypeBinding> + 'a> {
2218+
match self {
2219+
&GenericArgs::AngleBracketed { ref bindings, .. } => Box::new(bindings.iter().cloned()),
2220+
&GenericArgs::Parenthesized { ref output, .. } => Box::new(
2221+
output
2222+
.as_ref()
2223+
.map(|ty| TypeBinding {
2224+
assoc: PathSegment {
2225+
name: sym::Output,
2226+
args: GenericArgs::AngleBracketed {
2227+
args: Vec::new().into_boxed_slice(),
2228+
bindings: ThinVec::new(),
2229+
},
2230+
},
2231+
kind: TypeBindingKind::Equality { term: Term::Type((**ty).clone()) },
2232+
})
2233+
.into_iter(),
2234+
),
2235+
}
2236+
}
2237+
}
2238+
2239+
impl<'a> IntoIterator for &'a GenericArgs {
2240+
type IntoIter = Box<dyn Iterator<Item = GenericArg> + 'a>;
2241+
type Item = GenericArg;
2242+
fn into_iter(self) -> Self::IntoIter {
2243+
match self {
2244+
&GenericArgs::AngleBracketed { ref args, .. } => Box::new(args.iter().cloned()),
2245+
&GenericArgs::Parenthesized { ref inputs, .. } => {
2246+
Box::new(inputs.iter().cloned().map(GenericArg::Type))
2247+
}
2248+
}
2249+
}
22102250
}
22112251

22122252
#[derive(Clone, PartialEq, Eq, Debug, Hash)]

src/librustdoc/formats/item_type.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ pub(crate) enum ItemType {
4949
ProcAttribute = 23,
5050
ProcDerive = 24,
5151
TraitAlias = 25,
52+
// This number is reserved for use in JavaScript
53+
// Generic = 26,
5254
}
5355

5456
impl Serialize for ItemType {

src/librustdoc/html/render/mod.rs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ pub(crate) struct IndexItem {
112112
pub(crate) struct RenderType {
113113
id: Option<RenderTypeId>,
114114
generics: Option<Vec<RenderType>>,
115+
bindings: Option<Vec<(RenderTypeId, Vec<RenderType>)>>,
115116
}
116117

117118
impl Serialize for RenderType {
@@ -128,24 +129,47 @@ impl Serialize for RenderType {
128129
Some(RenderTypeId::Index(idx)) => *idx,
129130
_ => panic!("must convert render types to indexes before serializing"),
130131
};
131-
if let Some(generics) = &self.generics {
132+
if self.generics.is_some() || self.bindings.is_some() {
132133
let mut seq = serializer.serialize_seq(None)?;
133134
seq.serialize_element(&id)?;
134-
seq.serialize_element(generics)?;
135+
seq.serialize_element(self.generics.as_ref().map(Vec::as_slice).unwrap_or_default())?;
136+
if self.bindings.is_some() {
137+
seq.serialize_element(
138+
self.bindings.as_ref().map(Vec::as_slice).unwrap_or_default(),
139+
)?;
140+
}
135141
seq.end()
136142
} else {
137143
id.serialize(serializer)
138144
}
139145
}
140146
}
141147

142-
#[derive(Clone, Debug)]
148+
#[derive(Clone, Copy, Debug)]
143149
pub(crate) enum RenderTypeId {
144150
DefId(DefId),
145151
Primitive(clean::PrimitiveType),
152+
AssociatedType(Symbol),
146153
Index(isize),
147154
}
148155

156+
impl Serialize for RenderTypeId {
157+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
158+
where
159+
S: Serializer,
160+
{
161+
let id = match &self {
162+
// 0 is a sentinel, everything else is one-indexed
163+
// concrete type
164+
RenderTypeId::Index(idx) if *idx >= 0 => idx + 1,
165+
// generic type parameter
166+
RenderTypeId::Index(idx) => *idx,
167+
_ => panic!("must convert render types to indexes before serializing"),
168+
};
169+
id.serialize(serializer)
170+
}
171+
}
172+
149173
/// Full type of functions/methods in the search index.
150174
#[derive(Debug)]
151175
pub(crate) struct IndexItemFunctionType {
@@ -170,16 +194,20 @@ impl Serialize for IndexItemFunctionType {
170194
} else {
171195
let mut seq = serializer.serialize_seq(None)?;
172196
match &self.inputs[..] {
173-
[one] if one.generics.is_none() => seq.serialize_element(one)?,
197+
[one] if one.generics.is_none() && one.bindings.is_none() => {
198+
seq.serialize_element(one)?
199+
}
174200
_ => seq.serialize_element(&self.inputs)?,
175201
}
176202
match &self.output[..] {
177203
[] if self.where_clause.is_empty() => {}
178-
[one] if one.generics.is_none() => seq.serialize_element(one)?,
204+
[one] if one.generics.is_none() && one.bindings.is_none() => {
205+
seq.serialize_element(one)?
206+
}
179207
_ => seq.serialize_element(&self.output)?,
180208
}
181209
for constraint in &self.where_clause {
182-
if let [one] = &constraint[..] && one.generics.is_none() {
210+
if let [one] = &constraint[..] && one.generics.is_none() && one.bindings.is_none() {
183211
seq.serialize_element(one)?;
184212
} else {
185213
seq.serialize_element(constraint)?;

0 commit comments

Comments
 (0)