Skip to content

Commit c6b34ce

Browse files
committed
rustdoc-search: add support for associated types
1 parent 4af886f commit c6b34ce

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
@@ -1654,6 +1654,13 @@ impl Type {
16541654
}
16551655
}
16561656

1657+
pub(crate) fn bindings(&self) -> Option<&[TypeBinding]> {
1658+
match self {
1659+
Type::Path { path, .. } => path.bindings(),
1660+
_ => None,
1661+
}
1662+
}
1663+
16571664
pub(crate) fn is_full_generic(&self) -> bool {
16581665
matches!(self, Type::Generic(_))
16591666
}
@@ -2228,6 +2235,39 @@ impl GenericArgs {
22282235
GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
22292236
}
22302237
}
2238+
pub(crate) fn bindings<'a>(&'a self) -> Box<dyn Iterator<Item = TypeBinding> + 'a> {
2239+
match self {
2240+
&GenericArgs::AngleBracketed { ref bindings, .. } => Box::new(bindings.iter().cloned()),
2241+
&GenericArgs::Parenthesized { ref output, .. } => Box::new(
2242+
output
2243+
.as_ref()
2244+
.map(|ty| TypeBinding {
2245+
assoc: PathSegment {
2246+
name: sym::Output,
2247+
args: GenericArgs::AngleBracketed {
2248+
args: Vec::new().into_boxed_slice(),
2249+
bindings: ThinVec::new(),
2250+
},
2251+
},
2252+
kind: TypeBindingKind::Equality { term: Term::Type((**ty).clone()) },
2253+
})
2254+
.into_iter(),
2255+
),
2256+
}
2257+
}
2258+
}
2259+
2260+
impl<'a> IntoIterator for &'a GenericArgs {
2261+
type IntoIter = Box<dyn Iterator<Item = GenericArg> + 'a>;
2262+
type Item = GenericArg;
2263+
fn into_iter(self) -> Self::IntoIter {
2264+
match self {
2265+
&GenericArgs::AngleBracketed { ref args, .. } => Box::new(args.iter().cloned()),
2266+
&GenericArgs::Parenthesized { ref inputs, .. } => {
2267+
Box::new(inputs.iter().cloned().map(GenericArg::Type))
2268+
}
2269+
}
2270+
}
22312271
}
22322272

22332273
#[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
@@ -113,6 +113,7 @@ pub(crate) struct IndexItem {
113113
pub(crate) struct RenderType {
114114
id: Option<RenderTypeId>,
115115
generics: Option<Vec<RenderType>>,
116+
bindings: Option<Vec<(RenderTypeId, Vec<RenderType>)>>,
116117
}
117118

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

143-
#[derive(Clone, Debug)]
149+
#[derive(Clone, Copy, Debug)]
144150
pub(crate) enum RenderTypeId {
145151
DefId(DefId),
146152
Primitive(clean::PrimitiveType),
153+
AssociatedType(Symbol),
147154
Index(isize),
148155
}
149156

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

0 commit comments

Comments
 (0)