]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | //! This module contains the "cleaned" pieces of the AST, and the functions | |
12 | //! that clean them. | |
13 | ||
1a4d82fc JJ |
14 | pub use self::Type::*; |
15 | pub use self::PrimitiveType::*; | |
16 | pub use self::TypeKind::*; | |
1a4d82fc JJ |
17 | pub use self::VariantKind::*; |
18 | pub use self::Mutability::*; | |
85aaf69f | 19 | pub use self::Import::*; |
1a4d82fc JJ |
20 | pub use self::ItemEnum::*; |
21 | pub use self::Attribute::*; | |
22 | pub use self::TyParamBound::*; | |
23 | pub use self::SelfTy::*; | |
24 | pub use self::FunctionRetTy::*; | |
1a4d82fc JJ |
25 | |
26 | use syntax; | |
7453a54e | 27 | use syntax::abi::Abi; |
1a4d82fc | 28 | use syntax::ast; |
b039eaaf SL |
29 | use syntax::attr; |
30 | use syntax::attr::{AttributeMethods, AttrMetaMethods}; | |
85aaf69f | 31 | use syntax::codemap; |
1a4d82fc JJ |
32 | use syntax::codemap::{DUMMY_SP, Pos, Spanned}; |
33 | use syntax::parse::token::{self, InternedString, special_idents}; | |
34 | use syntax::ptr::P; | |
35 | ||
36 | use rustc_trans::back::link; | |
92a42be0 | 37 | use rustc::middle::cstore::{self, CrateStore}; |
54a0048b SL |
38 | use rustc::hir::def::Def; |
39 | use rustc::hir::def_id::{DefId, DefIndex}; | |
40 | use rustc::ty::subst::{self, ParamSpace, VecPerParamSpace}; | |
41 | use rustc::ty; | |
1a4d82fc | 42 | use rustc::middle::stability; |
1a4d82fc | 43 | |
54a0048b | 44 | use rustc::hir; |
e9174d1e | 45 | |
54a0048b | 46 | use std::collections::{HashMap, HashSet}; |
9346a6ac | 47 | use std::path::PathBuf; |
1a4d82fc JJ |
48 | use std::rc::Rc; |
49 | use std::u32; | |
7453a54e | 50 | use std::env::current_dir; |
1a4d82fc JJ |
51 | |
52 | use core::DocContext; | |
53 | use doctree; | |
54 | use visit_ast; | |
54a0048b | 55 | use html::item_type::ItemType; |
1a4d82fc JJ |
56 | |
57 | mod inline; | |
9346a6ac | 58 | mod simplify; |
1a4d82fc JJ |
59 | |
60 | // extract the stability index for a node from tcx, if possible | |
e9174d1e | 61 | fn get_stability(cx: &DocContext, def_id: DefId) -> Option<Stability> { |
9cc50fc6 SL |
62 | cx.tcx_opt().and_then(|tcx| stability::lookup_stability(tcx, def_id)).clean(cx) |
63 | } | |
64 | ||
65 | fn get_deprecation(cx: &DocContext, def_id: DefId) -> Option<Deprecation> { | |
66 | cx.tcx_opt().and_then(|tcx| stability::lookup_deprecation(tcx, def_id)).clean(cx) | |
1a4d82fc JJ |
67 | } |
68 | ||
69 | pub trait Clean<T> { | |
70 | fn clean(&self, cx: &DocContext) -> T; | |
71 | } | |
72 | ||
c34b1796 | 73 | impl<T: Clean<U>, U> Clean<Vec<U>> for [T] { |
1a4d82fc JJ |
74 | fn clean(&self, cx: &DocContext) -> Vec<U> { |
75 | self.iter().map(|x| x.clean(cx)).collect() | |
76 | } | |
77 | } | |
78 | ||
79 | impl<T: Clean<U>, U> Clean<VecPerParamSpace<U>> for VecPerParamSpace<T> { | |
80 | fn clean(&self, cx: &DocContext) -> VecPerParamSpace<U> { | |
81 | self.map(|x| x.clean(cx)) | |
82 | } | |
83 | } | |
84 | ||
85 | impl<T: Clean<U>, U> Clean<U> for P<T> { | |
86 | fn clean(&self, cx: &DocContext) -> U { | |
87 | (**self).clean(cx) | |
88 | } | |
89 | } | |
90 | ||
91 | impl<T: Clean<U>, U> Clean<U> for Rc<T> { | |
92 | fn clean(&self, cx: &DocContext) -> U { | |
93 | (**self).clean(cx) | |
94 | } | |
95 | } | |
96 | ||
97 | impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> { | |
98 | fn clean(&self, cx: &DocContext) -> Option<U> { | |
54a0048b | 99 | self.as_ref().map(|v| v.clean(cx)) |
1a4d82fc JJ |
100 | } |
101 | } | |
102 | ||
85aaf69f SL |
103 | impl<T, U> Clean<U> for ty::Binder<T> where T: Clean<U> { |
104 | fn clean(&self, cx: &DocContext) -> U { | |
105 | self.0.clean(cx) | |
106 | } | |
107 | } | |
108 | ||
9cc50fc6 | 109 | impl<T: Clean<U>, U> Clean<Vec<U>> for P<[T]> { |
1a4d82fc JJ |
110 | fn clean(&self, cx: &DocContext) -> Vec<U> { |
111 | self.iter().map(|x| x.clean(cx)).collect() | |
112 | } | |
113 | } | |
114 | ||
85aaf69f | 115 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
116 | pub struct Crate { |
117 | pub name: String, | |
c34b1796 | 118 | pub src: PathBuf, |
1a4d82fc JJ |
119 | pub module: Option<Item>, |
120 | pub externs: Vec<(ast::CrateNum, ExternalCrate)>, | |
121 | pub primitives: Vec<PrimitiveType>, | |
e9174d1e | 122 | pub external_traits: HashMap<DefId, Trait>, |
1a4d82fc JJ |
123 | } |
124 | ||
92a42be0 SL |
125 | struct CrateNum(ast::CrateNum); |
126 | ||
1a4d82fc JJ |
127 | impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> { |
128 | fn clean(&self, cx: &DocContext) -> Crate { | |
85aaf69f SL |
129 | use rustc::session::config::Input; |
130 | ||
d9579d0f AL |
131 | if let Some(t) = cx.tcx_opt() { |
132 | cx.deref_trait_did.set(t.lang_items.deref_trait()); | |
133 | } | |
134 | ||
1a4d82fc | 135 | let mut externs = Vec::new(); |
92a42be0 SL |
136 | for cnum in cx.sess().cstore.crates() { |
137 | externs.push((cnum, CrateNum(cnum).clean(cx))); | |
138 | } | |
1a4d82fc JJ |
139 | externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b)); |
140 | ||
141 | // Figure out the name of this crate | |
85aaf69f | 142 | let input = &cx.input; |
b039eaaf | 143 | let name = link::find_crate_name(None, &self.attrs, input); |
1a4d82fc JJ |
144 | |
145 | // Clean the crate, translating the entire libsyntax AST to one that is | |
146 | // understood by rustdoc. | |
147 | let mut module = self.module.clean(cx); | |
148 | ||
149 | // Collect all inner modules which are tagged as implementations of | |
150 | // primitives. | |
151 | // | |
152 | // Note that this loop only searches the top-level items of the crate, | |
153 | // and this is intentional. If we were to search the entire crate for an | |
b039eaaf | 154 | // item tagged with `#[doc(primitive)]` then we would also have to |
1a4d82fc JJ |
155 | // search the entirety of external modules for items tagged |
156 | // `#[doc(primitive)]`, which is a pretty inefficient process (decoding | |
157 | // all that metadata unconditionally). | |
158 | // | |
159 | // In order to keep the metadata load under control, the | |
160 | // `#[doc(primitive)]` feature is explicitly designed to only allow the | |
161 | // primitive tags to show up as the top level items in a crate. | |
162 | // | |
163 | // Also note that this does not attempt to deal with modules tagged | |
164 | // duplicately for the same primitive. This is handled later on when | |
165 | // rendering by delegating everything to a hash map. | |
166 | let mut primitives = Vec::new(); | |
167 | { | |
168 | let m = match module.inner { | |
169 | ModuleItem(ref mut m) => m, | |
170 | _ => unreachable!(), | |
171 | }; | |
172 | let mut tmp = Vec::new(); | |
85aaf69f | 173 | for child in &mut m.items { |
54a0048b SL |
174 | if !child.is_mod() { |
175 | continue; | |
1a4d82fc | 176 | } |
85aaf69f | 177 | let prim = match PrimitiveType::find(&child.attrs) { |
1a4d82fc JJ |
178 | Some(prim) => prim, |
179 | None => continue, | |
180 | }; | |
181 | primitives.push(prim); | |
182 | tmp.push(Item { | |
183 | source: Span::empty(), | |
184 | name: Some(prim.to_url_str().to_string()), | |
185 | attrs: child.attrs.clone(), | |
e9174d1e | 186 | visibility: Some(hir::Public), |
1a4d82fc | 187 | stability: None, |
9cc50fc6 | 188 | deprecation: None, |
b039eaaf | 189 | def_id: DefId::local(prim.to_def_index()), |
1a4d82fc JJ |
190 | inner: PrimitiveItem(prim), |
191 | }); | |
192 | } | |
62682a34 | 193 | m.items.extend(tmp); |
1a4d82fc JJ |
194 | } |
195 | ||
85aaf69f | 196 | let src = match cx.input { |
7453a54e SL |
197 | Input::File(ref path) => { |
198 | if path.is_absolute() { | |
199 | path.clone() | |
200 | } else { | |
201 | current_dir().unwrap().join(path) | |
202 | } | |
203 | }, | |
54a0048b | 204 | Input::Str { ref name, .. } => PathBuf::from(name.clone()), |
85aaf69f SL |
205 | }; |
206 | ||
1a4d82fc JJ |
207 | Crate { |
208 | name: name.to_string(), | |
85aaf69f | 209 | src: src, |
1a4d82fc JJ |
210 | module: Some(module), |
211 | externs: externs, | |
212 | primitives: primitives, | |
9346a6ac AL |
213 | external_traits: cx.external_traits.borrow_mut().take() |
214 | .unwrap_or(HashMap::new()), | |
1a4d82fc JJ |
215 | } |
216 | } | |
217 | } | |
218 | ||
85aaf69f | 219 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
220 | pub struct ExternalCrate { |
221 | pub name: String, | |
222 | pub attrs: Vec<Attribute>, | |
223 | pub primitives: Vec<PrimitiveType>, | |
224 | } | |
225 | ||
92a42be0 | 226 | impl Clean<ExternalCrate> for CrateNum { |
1a4d82fc JJ |
227 | fn clean(&self, cx: &DocContext) -> ExternalCrate { |
228 | let mut primitives = Vec::new(); | |
229 | cx.tcx_opt().map(|tcx| { | |
92a42be0 SL |
230 | for item in tcx.sess.cstore.crate_top_level_items(self.0) { |
231 | let did = match item.def { | |
7453a54e | 232 | cstore::DlDef(Def::Mod(did)) => did, |
92a42be0 | 233 | _ => continue |
1a4d82fc JJ |
234 | }; |
235 | let attrs = inline::load_attrs(cx, tcx, did); | |
85aaf69f | 236 | PrimitiveType::find(&attrs).map(|prim| primitives.push(prim)); |
92a42be0 | 237 | } |
1a4d82fc JJ |
238 | }); |
239 | ExternalCrate { | |
54a0048b | 240 | name: (&cx.sess().cstore.crate_name(self.0)[..]).to_owned(), |
92a42be0 | 241 | attrs: cx.sess().cstore.crate_attrs(self.0).clean(cx), |
1a4d82fc JJ |
242 | primitives: primitives, |
243 | } | |
244 | } | |
245 | } | |
246 | ||
247 | /// Anything with a source location and set of attributes and, optionally, a | |
248 | /// name. That is, anything that can be documented. This doesn't correspond | |
249 | /// directly to the AST's concept of an item; it's a strict superset. | |
85aaf69f | 250 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
251 | pub struct Item { |
252 | /// Stringified span | |
253 | pub source: Span, | |
254 | /// Not everything has a name. E.g., impls | |
255 | pub name: Option<String>, | |
54a0048b | 256 | pub attrs: Vec<Attribute>, |
1a4d82fc JJ |
257 | pub inner: ItemEnum, |
258 | pub visibility: Option<Visibility>, | |
e9174d1e | 259 | pub def_id: DefId, |
1a4d82fc | 260 | pub stability: Option<Stability>, |
9cc50fc6 | 261 | pub deprecation: Option<Deprecation>, |
1a4d82fc JJ |
262 | } |
263 | ||
264 | impl Item { | |
1a4d82fc JJ |
265 | /// Finds the `doc` attribute as a NameValue and returns the corresponding |
266 | /// value found. | |
267 | pub fn doc_value<'a>(&'a self) -> Option<&'a str> { | |
54a0048b | 268 | self.attrs.value("doc") |
1a4d82fc | 269 | } |
54a0048b SL |
270 | pub fn is_crate(&self) -> bool { |
271 | match self.inner { | |
272 | StrippedItem(box ModuleItem(Module { is_crate: true, ..})) | | |
273 | ModuleItem(Module { is_crate: true, ..}) => true, | |
274 | _ => false, | |
1a4d82fc | 275 | } |
1a4d82fc | 276 | } |
1a4d82fc | 277 | pub fn is_mod(&self) -> bool { |
54a0048b | 278 | ItemType::from_item(self) == ItemType::Module |
1a4d82fc JJ |
279 | } |
280 | pub fn is_trait(&self) -> bool { | |
54a0048b | 281 | ItemType::from_item(self) == ItemType::Trait |
1a4d82fc JJ |
282 | } |
283 | pub fn is_struct(&self) -> bool { | |
54a0048b | 284 | ItemType::from_item(self) == ItemType::Struct |
1a4d82fc JJ |
285 | } |
286 | pub fn is_enum(&self) -> bool { | |
54a0048b | 287 | ItemType::from_item(self) == ItemType::Module |
1a4d82fc JJ |
288 | } |
289 | pub fn is_fn(&self) -> bool { | |
54a0048b SL |
290 | ItemType::from_item(self) == ItemType::Function |
291 | } | |
292 | pub fn is_associated_type(&self) -> bool { | |
293 | ItemType::from_item(self) == ItemType::AssociatedType | |
294 | } | |
295 | pub fn is_associated_const(&self) -> bool { | |
296 | ItemType::from_item(self) == ItemType::AssociatedConst | |
297 | } | |
298 | pub fn is_method(&self) -> bool { | |
299 | ItemType::from_item(self) == ItemType::Method | |
300 | } | |
301 | pub fn is_ty_method(&self) -> bool { | |
302 | ItemType::from_item(self) == ItemType::TyMethod | |
303 | } | |
304 | pub fn is_stripped(&self) -> bool { | |
305 | match self.inner { StrippedItem(..) => true, _ => false } | |
306 | } | |
307 | pub fn has_stripped_fields(&self) -> Option<bool> { | |
308 | match self.inner { | |
309 | StructItem(ref _struct) => Some(_struct.fields_stripped), | |
310 | VariantItem(Variant { kind: StructVariant(ref vstruct)} ) => { | |
311 | Some(vstruct.fields_stripped) | |
312 | }, | |
313 | _ => None, | |
314 | } | |
1a4d82fc | 315 | } |
d9579d0f AL |
316 | |
317 | pub fn stability_class(&self) -> String { | |
54a0048b SL |
318 | self.stability.as_ref().map(|ref s| { |
319 | let mut base = match s.level { | |
320 | stability::Unstable => "unstable".to_string(), | |
321 | stability::Stable => String::new(), | |
322 | }; | |
323 | if !s.deprecated_since.is_empty() { | |
324 | base.push_str(" deprecated"); | |
d9579d0f | 325 | } |
54a0048b SL |
326 | base |
327 | }).unwrap_or(String::new()) | |
d9579d0f | 328 | } |
7453a54e SL |
329 | |
330 | pub fn stable_since(&self) -> Option<&str> { | |
54a0048b | 331 | self.stability.as_ref().map(|s| &s.since[..]) |
7453a54e | 332 | } |
1a4d82fc JJ |
333 | } |
334 | ||
85aaf69f | 335 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc | 336 | pub enum ItemEnum { |
85aaf69f SL |
337 | ExternCrateItem(String, Option<String>), |
338 | ImportItem(Import), | |
1a4d82fc JJ |
339 | StructItem(Struct), |
340 | EnumItem(Enum), | |
341 | FunctionItem(Function), | |
342 | ModuleItem(Module), | |
62682a34 | 343 | TypedefItem(Typedef, bool /* is associated type */), |
1a4d82fc JJ |
344 | StaticItem(Static), |
345 | ConstantItem(Constant), | |
346 | TraitItem(Trait), | |
347 | ImplItem(Impl), | |
1a4d82fc JJ |
348 | /// A method signature only. Used for required methods in traits (ie, |
349 | /// non-default-methods). | |
350 | TyMethodItem(TyMethod), | |
351 | /// A method with a body. | |
352 | MethodItem(Method), | |
54a0048b | 353 | StructFieldItem(Type), |
1a4d82fc JJ |
354 | VariantItem(Variant), |
355 | /// `fn`s from an extern block | |
356 | ForeignFunctionItem(Function), | |
357 | /// `static`s from an extern block | |
358 | ForeignStaticItem(Static), | |
359 | MacroItem(Macro), | |
360 | PrimitiveItem(PrimitiveType), | |
d9579d0f | 361 | AssociatedConstItem(Type, Option<String>), |
c34b1796 AL |
362 | AssociatedTypeItem(Vec<TyParamBound>, Option<Type>), |
363 | DefaultImplItem(DefaultImpl), | |
54a0048b SL |
364 | /// An item that has been stripped by a rustdoc pass |
365 | StrippedItem(Box<ItemEnum>), | |
1a4d82fc JJ |
366 | } |
367 | ||
85aaf69f | 368 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
369 | pub struct Module { |
370 | pub items: Vec<Item>, | |
371 | pub is_crate: bool, | |
372 | } | |
373 | ||
374 | impl Clean<Item> for doctree::Module { | |
375 | fn clean(&self, cx: &DocContext) -> Item { | |
376 | let name = if self.name.is_some() { | |
377 | self.name.unwrap().clean(cx) | |
378 | } else { | |
379 | "".to_string() | |
380 | }; | |
85aaf69f SL |
381 | |
382 | let mut items: Vec<Item> = vec![]; | |
383 | items.extend(self.extern_crates.iter().map(|x| x.clean(cx))); | |
62682a34 | 384 | items.extend(self.imports.iter().flat_map(|x| x.clean(cx))); |
85aaf69f SL |
385 | items.extend(self.structs.iter().map(|x| x.clean(cx))); |
386 | items.extend(self.enums.iter().map(|x| x.clean(cx))); | |
387 | items.extend(self.fns.iter().map(|x| x.clean(cx))); | |
62682a34 | 388 | items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx))); |
85aaf69f SL |
389 | items.extend(self.mods.iter().map(|x| x.clean(cx))); |
390 | items.extend(self.typedefs.iter().map(|x| x.clean(cx))); | |
391 | items.extend(self.statics.iter().map(|x| x.clean(cx))); | |
392 | items.extend(self.constants.iter().map(|x| x.clean(cx))); | |
393 | items.extend(self.traits.iter().map(|x| x.clean(cx))); | |
62682a34 | 394 | items.extend(self.impls.iter().flat_map(|x| x.clean(cx))); |
85aaf69f | 395 | items.extend(self.macros.iter().map(|x| x.clean(cx))); |
c34b1796 | 396 | items.extend(self.def_traits.iter().map(|x| x.clean(cx))); |
1a4d82fc JJ |
397 | |
398 | // determine if we should display the inner contents or | |
399 | // the outer `mod` item for the source code. | |
400 | let whence = { | |
401 | let cm = cx.sess().codemap(); | |
402 | let outer = cm.lookup_char_pos(self.where_outer.lo); | |
403 | let inner = cm.lookup_char_pos(self.where_inner.lo); | |
404 | if outer.file.start_pos == inner.file.start_pos { | |
405 | // mod foo { ... } | |
406 | self.where_outer | |
407 | } else { | |
408 | // mod foo; (and a separate FileMap for the contents) | |
409 | self.where_inner | |
410 | } | |
411 | }; | |
412 | ||
413 | Item { | |
414 | name: Some(name), | |
415 | attrs: self.attrs.clean(cx), | |
416 | source: whence.clean(cx), | |
417 | visibility: self.vis.clean(cx), | |
418 | stability: self.stab.clean(cx), | |
9cc50fc6 | 419 | deprecation: self.depr.clean(cx), |
b039eaaf | 420 | def_id: cx.map.local_def_id(self.id), |
1a4d82fc JJ |
421 | inner: ModuleItem(Module { |
422 | is_crate: self.is_crate, | |
85aaf69f | 423 | items: items |
1a4d82fc JJ |
424 | }) |
425 | } | |
426 | } | |
427 | } | |
428 | ||
54a0048b SL |
429 | pub trait Attributes { |
430 | fn has_word(&self, &str) -> bool; | |
431 | fn value<'a>(&'a self, &str) -> Option<&'a str>; | |
432 | fn list<'a>(&'a self, &str) -> &'a [Attribute]; | |
433 | } | |
434 | ||
435 | impl Attributes for [Attribute] { | |
436 | /// Returns whether the attribute list contains a specific `Word` | |
437 | fn has_word(&self, word: &str) -> bool { | |
438 | for attr in self { | |
439 | if let Word(ref w) = *attr { | |
440 | if word == *w { | |
441 | return true; | |
442 | } | |
443 | } | |
444 | } | |
445 | false | |
446 | } | |
447 | ||
448 | /// Finds an attribute as NameValue and returns the corresponding value found. | |
449 | fn value<'a>(&'a self, name: &str) -> Option<&'a str> { | |
450 | for attr in self { | |
451 | if let NameValue(ref x, ref v) = *attr { | |
452 | if name == *x { | |
453 | return Some(v); | |
454 | } | |
455 | } | |
456 | } | |
457 | None | |
458 | } | |
459 | ||
460 | /// Finds an attribute as List and returns the list of attributes nested inside. | |
461 | fn list<'a>(&'a self, name: &str) -> &'a [Attribute] { | |
462 | for attr in self { | |
463 | if let List(ref x, ref list) = *attr { | |
464 | if name == *x { | |
465 | return &list[..]; | |
466 | } | |
467 | } | |
468 | } | |
469 | &[] | |
470 | } | |
471 | } | |
472 | ||
85aaf69f | 473 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
474 | pub enum Attribute { |
475 | Word(String), | |
54a0048b | 476 | List(String, Vec<Attribute>), |
1a4d82fc JJ |
477 | NameValue(String, String) |
478 | } | |
479 | ||
b039eaaf | 480 | impl Clean<Attribute> for ast::MetaItem { |
1a4d82fc JJ |
481 | fn clean(&self, cx: &DocContext) -> Attribute { |
482 | match self.node { | |
7453a54e SL |
483 | ast::MetaItemKind::Word(ref s) => Word(s.to_string()), |
484 | ast::MetaItemKind::List(ref s, ref l) => { | |
85aaf69f | 485 | List(s.to_string(), l.clean(cx)) |
1a4d82fc | 486 | } |
7453a54e | 487 | ast::MetaItemKind::NameValue(ref s, ref v) => { |
85aaf69f | 488 | NameValue(s.to_string(), lit_to_string(v)) |
1a4d82fc JJ |
489 | } |
490 | } | |
491 | } | |
492 | } | |
493 | ||
b039eaaf | 494 | impl Clean<Attribute> for ast::Attribute { |
1a4d82fc JJ |
495 | fn clean(&self, cx: &DocContext) -> Attribute { |
496 | self.with_desugared_doc(|a| a.node.value.clean(cx)) | |
497 | } | |
498 | } | |
499 | ||
500 | // This is a rough approximation that gets us what we want. | |
501 | impl attr::AttrMetaMethods for Attribute { | |
502 | fn name(&self) -> InternedString { | |
503 | match *self { | |
504 | Word(ref n) | List(ref n, _) | NameValue(ref n, _) => { | |
85aaf69f | 505 | token::intern_and_get_ident(n) |
1a4d82fc JJ |
506 | } |
507 | } | |
508 | } | |
509 | ||
510 | fn value_str(&self) -> Option<InternedString> { | |
511 | match *self { | |
512 | NameValue(_, ref v) => { | |
85aaf69f | 513 | Some(token::intern_and_get_ident(v)) |
1a4d82fc JJ |
514 | } |
515 | _ => None, | |
516 | } | |
517 | } | |
b039eaaf | 518 | fn meta_item_list<'a>(&'a self) -> Option<&'a [P<ast::MetaItem>]> { None } |
85aaf69f | 519 | fn span(&self) -> codemap::Span { unimplemented!() } |
1a4d82fc | 520 | } |
1a4d82fc | 521 | |
85aaf69f | 522 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
523 | pub struct TyParam { |
524 | pub name: String, | |
e9174d1e | 525 | pub did: DefId, |
1a4d82fc JJ |
526 | pub bounds: Vec<TyParamBound>, |
527 | pub default: Option<Type>, | |
528 | } | |
529 | ||
e9174d1e | 530 | impl Clean<TyParam> for hir::TyParam { |
1a4d82fc JJ |
531 | fn clean(&self, cx: &DocContext) -> TyParam { |
532 | TyParam { | |
b039eaaf SL |
533 | name: self.name.clean(cx), |
534 | did: cx.map.local_def_id(self.id), | |
1a4d82fc JJ |
535 | bounds: self.bounds.clean(cx), |
536 | default: self.default.clean(cx), | |
537 | } | |
538 | } | |
539 | } | |
540 | ||
541 | impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> { | |
542 | fn clean(&self, cx: &DocContext) -> TyParam { | |
543 | cx.external_typarams.borrow_mut().as_mut().unwrap() | |
544 | .insert(self.def_id, self.name.clean(cx)); | |
1a4d82fc JJ |
545 | TyParam { |
546 | name: self.name.clean(cx), | |
547 | did: self.def_id, | |
c34b1796 | 548 | bounds: vec![], // these are filled in from the where-clauses |
1a4d82fc JJ |
549 | default: self.default.clean(cx), |
550 | } | |
551 | } | |
552 | } | |
553 | ||
85aaf69f | 554 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
555 | pub enum TyParamBound { |
556 | RegionBound(Lifetime), | |
e9174d1e | 557 | TraitBound(PolyTrait, hir::TraitBoundModifier) |
1a4d82fc JJ |
558 | } |
559 | ||
9346a6ac AL |
560 | impl TyParamBound { |
561 | fn maybe_sized(cx: &DocContext) -> TyParamBound { | |
54a0048b | 562 | use rustc::hir::TraitBoundModifier as TBM; |
62682a34 | 563 | let mut sized_bound = ty::BoundSized.clean(cx); |
9346a6ac AL |
564 | if let TyParamBound::TraitBound(_, ref mut tbm) = sized_bound { |
565 | *tbm = TBM::Maybe | |
566 | }; | |
567 | sized_bound | |
568 | } | |
569 | ||
570 | fn is_sized_bound(&self, cx: &DocContext) -> bool { | |
54a0048b | 571 | use rustc::hir::TraitBoundModifier as TBM; |
9346a6ac | 572 | if let Some(tcx) = cx.tcx_opt() { |
54a0048b SL |
573 | if let TyParamBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self { |
574 | if trait_.def_id() == tcx.lang_items.sized_trait() { | |
575 | return true; | |
9346a6ac AL |
576 | } |
577 | } | |
578 | } | |
579 | false | |
580 | } | |
581 | } | |
582 | ||
e9174d1e | 583 | impl Clean<TyParamBound> for hir::TyParamBound { |
1a4d82fc JJ |
584 | fn clean(&self, cx: &DocContext) -> TyParamBound { |
585 | match *self { | |
e9174d1e SL |
586 | hir::RegionTyParamBound(lt) => RegionBound(lt.clean(cx)), |
587 | hir::TraitTyParamBound(ref t, modifier) => TraitBound(t.clean(cx), modifier), | |
1a4d82fc JJ |
588 | } |
589 | } | |
590 | } | |
591 | ||
85aaf69f SL |
592 | impl<'tcx> Clean<(Vec<TyParamBound>, Vec<TypeBinding>)> for ty::ExistentialBounds<'tcx> { |
593 | fn clean(&self, cx: &DocContext) -> (Vec<TyParamBound>, Vec<TypeBinding>) { | |
594 | let mut tp_bounds = vec![]; | |
595 | self.region_bound.clean(cx).map(|b| tp_bounds.push(RegionBound(b))); | |
596 | for bb in &self.builtin_bounds { | |
597 | tp_bounds.push(bb.clean(cx)); | |
1a4d82fc JJ |
598 | } |
599 | ||
85aaf69f SL |
600 | let mut bindings = vec![]; |
601 | for &ty::Binder(ref pb) in &self.projection_bounds { | |
602 | bindings.push(TypeBinding { | |
603 | name: pb.projection_ty.item_name.clean(cx), | |
604 | ty: pb.ty.clean(cx) | |
605 | }); | |
606 | } | |
1a4d82fc | 607 | |
85aaf69f | 608 | (tp_bounds, bindings) |
1a4d82fc JJ |
609 | } |
610 | } | |
611 | ||
e9174d1e | 612 | fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, |
85aaf69f | 613 | bindings: Vec<TypeBinding>, substs: &subst::Substs) -> PathParameters { |
54a0048b | 614 | let lifetimes = substs.regions.get_slice(subst::TypeSpace) |
1a4d82fc JJ |
615 | .iter() |
616 | .filter_map(|v| v.clean(cx)) | |
617 | .collect(); | |
618 | let types = substs.types.get_slice(subst::TypeSpace).to_vec(); | |
619 | ||
620 | match (trait_did, cx.tcx_opt()) { | |
621 | // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C | |
622 | (Some(did), Some(ref tcx)) if tcx.lang_items.fn_trait_kind(did).is_some() => { | |
85aaf69f | 623 | assert_eq!(types.len(), 1); |
1a4d82fc | 624 | let inputs = match types[0].sty { |
62682a34 | 625 | ty::TyTuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(), |
1a4d82fc JJ |
626 | _ => { |
627 | return PathParameters::AngleBracketed { | |
628 | lifetimes: lifetimes, | |
629 | types: types.clean(cx), | |
85aaf69f | 630 | bindings: bindings |
1a4d82fc JJ |
631 | } |
632 | } | |
633 | }; | |
85aaf69f SL |
634 | let output = None; |
635 | // FIXME(#20299) return type comes from a projection now | |
636 | // match types[1].sty { | |
62682a34 | 637 | // ty::TyTuple(ref v) if v.is_empty() => None, // -> () |
85aaf69f SL |
638 | // _ => Some(types[1].clean(cx)) |
639 | // }; | |
1a4d82fc JJ |
640 | PathParameters::Parenthesized { |
641 | inputs: inputs, | |
642 | output: output | |
643 | } | |
644 | }, | |
645 | (_, _) => { | |
646 | PathParameters::AngleBracketed { | |
647 | lifetimes: lifetimes, | |
648 | types: types.clean(cx), | |
85aaf69f | 649 | bindings: bindings |
1a4d82fc JJ |
650 | } |
651 | } | |
652 | } | |
653 | } | |
654 | ||
655 | // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar | |
656 | // from Fn<(A, B,), C> to Fn(A, B) -> C | |
e9174d1e | 657 | fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>, |
85aaf69f | 658 | bindings: Vec<TypeBinding>, substs: &subst::Substs) -> Path { |
1a4d82fc JJ |
659 | Path { |
660 | global: false, | |
661 | segments: vec![PathSegment { | |
662 | name: name.to_string(), | |
85aaf69f | 663 | params: external_path_params(cx, trait_did, bindings, substs) |
1a4d82fc JJ |
664 | }], |
665 | } | |
666 | } | |
667 | ||
668 | impl Clean<TyParamBound> for ty::BuiltinBound { | |
669 | fn clean(&self, cx: &DocContext) -> TyParamBound { | |
670 | let tcx = match cx.tcx_opt() { | |
671 | Some(tcx) => tcx, | |
672 | None => return RegionBound(Lifetime::statik()) | |
673 | }; | |
674 | let empty = subst::Substs::empty(); | |
675 | let (did, path) = match *self { | |
676 | ty::BoundSend => | |
677 | (tcx.lang_items.send_trait().unwrap(), | |
85aaf69f | 678 | external_path(cx, "Send", None, vec![], &empty)), |
1a4d82fc JJ |
679 | ty::BoundSized => |
680 | (tcx.lang_items.sized_trait().unwrap(), | |
85aaf69f | 681 | external_path(cx, "Sized", None, vec![], &empty)), |
1a4d82fc JJ |
682 | ty::BoundCopy => |
683 | (tcx.lang_items.copy_trait().unwrap(), | |
85aaf69f | 684 | external_path(cx, "Copy", None, vec![], &empty)), |
1a4d82fc JJ |
685 | ty::BoundSync => |
686 | (tcx.lang_items.sync_trait().unwrap(), | |
85aaf69f | 687 | external_path(cx, "Sync", None, vec![], &empty)), |
1a4d82fc | 688 | }; |
92a42be0 | 689 | inline::record_extern_fqn(cx, did, TypeTrait); |
1a4d82fc JJ |
690 | TraitBound(PolyTrait { |
691 | trait_: ResolvedPath { | |
692 | path: path, | |
693 | typarams: None, | |
694 | did: did, | |
62682a34 | 695 | is_generic: false, |
1a4d82fc JJ |
696 | }, |
697 | lifetimes: vec![] | |
e9174d1e | 698 | }, hir::TraitBoundModifier::None) |
1a4d82fc JJ |
699 | } |
700 | } | |
701 | ||
1a4d82fc JJ |
702 | impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> { |
703 | fn clean(&self, cx: &DocContext) -> TyParamBound { | |
704 | let tcx = match cx.tcx_opt() { | |
705 | Some(tcx) => tcx, | |
706 | None => return RegionBound(Lifetime::statik()) | |
707 | }; | |
92a42be0 SL |
708 | inline::record_extern_fqn(cx, self.def_id, TypeTrait); |
709 | let path = external_path(cx, &tcx.item_name(self.def_id).as_str(), | |
85aaf69f | 710 | Some(self.def_id), vec![], self.substs); |
1a4d82fc JJ |
711 | |
712 | debug!("ty::TraitRef\n substs.types(TypeSpace): {:?}\n", | |
713 | self.substs.types.get_slice(ParamSpace::TypeSpace)); | |
714 | ||
715 | // collect any late bound regions | |
716 | let mut late_bounds = vec![]; | |
85aaf69f | 717 | for &ty_s in self.substs.types.get_slice(ParamSpace::TypeSpace) { |
62682a34 | 718 | if let ty::TyTuple(ref ts) = ty_s.sty { |
85aaf69f | 719 | for &ty_s in ts { |
62682a34 SL |
720 | if let ty::TyRef(ref reg, _) = ty_s.sty { |
721 | if let &ty::Region::ReLateBound(_, _) = *reg { | |
1a4d82fc JJ |
722 | debug!(" hit an ReLateBound {:?}", reg); |
723 | if let Some(lt) = reg.clean(cx) { | |
54a0048b | 724 | late_bounds.push(lt); |
1a4d82fc JJ |
725 | } |
726 | } | |
727 | } | |
728 | } | |
729 | } | |
730 | } | |
731 | ||
54a0048b SL |
732 | TraitBound( |
733 | PolyTrait { | |
734 | trait_: ResolvedPath { | |
735 | path: path, | |
736 | typarams: None, | |
737 | did: self.def_id, | |
738 | is_generic: false, | |
739 | }, | |
740 | lifetimes: late_bounds, | |
62682a34 | 741 | }, |
54a0048b SL |
742 | hir::TraitBoundModifier::None |
743 | ) | |
1a4d82fc JJ |
744 | } |
745 | } | |
746 | ||
1a4d82fc JJ |
747 | impl<'tcx> Clean<Option<Vec<TyParamBound>>> for subst::Substs<'tcx> { |
748 | fn clean(&self, cx: &DocContext) -> Option<Vec<TyParamBound>> { | |
749 | let mut v = Vec::new(); | |
54a0048b | 750 | v.extend(self.regions.iter().filter_map(|r| r.clean(cx)).map(RegionBound)); |
1a4d82fc JJ |
751 | v.extend(self.types.iter().map(|t| TraitBound(PolyTrait { |
752 | trait_: t.clean(cx), | |
753 | lifetimes: vec![] | |
e9174d1e | 754 | }, hir::TraitBoundModifier::None))); |
9346a6ac | 755 | if !v.is_empty() {Some(v)} else {None} |
1a4d82fc JJ |
756 | } |
757 | } | |
758 | ||
85aaf69f | 759 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
760 | pub struct Lifetime(String); |
761 | ||
762 | impl Lifetime { | |
763 | pub fn get_ref<'a>(&'a self) -> &'a str { | |
764 | let Lifetime(ref s) = *self; | |
85aaf69f | 765 | let s: &'a str = s; |
1a4d82fc JJ |
766 | return s; |
767 | } | |
768 | ||
769 | pub fn statik() -> Lifetime { | |
770 | Lifetime("'static".to_string()) | |
771 | } | |
772 | } | |
773 | ||
e9174d1e | 774 | impl Clean<Lifetime> for hir::Lifetime { |
1a4d82fc | 775 | fn clean(&self, _: &DocContext) -> Lifetime { |
c1a9b12d | 776 | Lifetime(self.name.to_string()) |
1a4d82fc JJ |
777 | } |
778 | } | |
779 | ||
e9174d1e | 780 | impl Clean<Lifetime> for hir::LifetimeDef { |
1a4d82fc | 781 | fn clean(&self, _: &DocContext) -> Lifetime { |
c1a9b12d | 782 | Lifetime(self.lifetime.name.to_string()) |
1a4d82fc JJ |
783 | } |
784 | } | |
785 | ||
786 | impl Clean<Lifetime> for ty::RegionParameterDef { | |
787 | fn clean(&self, _: &DocContext) -> Lifetime { | |
c1a9b12d | 788 | Lifetime(self.name.to_string()) |
1a4d82fc JJ |
789 | } |
790 | } | |
791 | ||
792 | impl Clean<Option<Lifetime>> for ty::Region { | |
793 | fn clean(&self, cx: &DocContext) -> Option<Lifetime> { | |
794 | match *self { | |
795 | ty::ReStatic => Some(Lifetime::statik()), | |
54a0048b | 796 | ty::ReLateBound(_, ty::BrNamed(_, name)) => Some(Lifetime(name.to_string())), |
9346a6ac | 797 | ty::ReEarlyBound(ref data) => Some(Lifetime(data.name.clean(cx))), |
1a4d82fc JJ |
798 | |
799 | ty::ReLateBound(..) | | |
800 | ty::ReFree(..) | | |
801 | ty::ReScope(..) | | |
e9174d1e SL |
802 | ty::ReVar(..) | |
803 | ty::ReSkolemized(..) | | |
92a42be0 | 804 | ty::ReEmpty => None |
1a4d82fc JJ |
805 | } |
806 | } | |
807 | } | |
808 | ||
85aaf69f | 809 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
810 | pub enum WherePredicate { |
811 | BoundPredicate { ty: Type, bounds: Vec<TyParamBound> }, | |
812 | RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>}, | |
85aaf69f | 813 | EqPredicate { lhs: Type, rhs: Type } |
1a4d82fc JJ |
814 | } |
815 | ||
e9174d1e | 816 | impl Clean<WherePredicate> for hir::WherePredicate { |
1a4d82fc JJ |
817 | fn clean(&self, cx: &DocContext) -> WherePredicate { |
818 | match *self { | |
e9174d1e | 819 | hir::WherePredicate::BoundPredicate(ref wbp) => { |
1a4d82fc JJ |
820 | WherePredicate::BoundPredicate { |
821 | ty: wbp.bounded_ty.clean(cx), | |
822 | bounds: wbp.bounds.clean(cx) | |
823 | } | |
824 | } | |
825 | ||
e9174d1e | 826 | hir::WherePredicate::RegionPredicate(ref wrp) => { |
1a4d82fc JJ |
827 | WherePredicate::RegionPredicate { |
828 | lifetime: wrp.lifetime.clean(cx), | |
829 | bounds: wrp.bounds.clean(cx) | |
830 | } | |
831 | } | |
832 | ||
e9174d1e | 833 | hir::WherePredicate::EqPredicate(_) => { |
85aaf69f | 834 | unimplemented!() // FIXME(#20041) |
1a4d82fc JJ |
835 | } |
836 | } | |
837 | } | |
838 | } | |
839 | ||
85aaf69f SL |
840 | impl<'a> Clean<WherePredicate> for ty::Predicate<'a> { |
841 | fn clean(&self, cx: &DocContext) -> WherePredicate { | |
54a0048b | 842 | use rustc::ty::Predicate; |
85aaf69f SL |
843 | |
844 | match *self { | |
845 | Predicate::Trait(ref pred) => pred.clean(cx), | |
846 | Predicate::Equate(ref pred) => pred.clean(cx), | |
847 | Predicate::RegionOutlives(ref pred) => pred.clean(cx), | |
848 | Predicate::TypeOutlives(ref pred) => pred.clean(cx), | |
e9174d1e SL |
849 | Predicate::Projection(ref pred) => pred.clean(cx), |
850 | Predicate::WellFormed(_) => panic!("not user writable"), | |
851 | Predicate::ObjectSafe(_) => panic!("not user writable"), | |
85aaf69f SL |
852 | } |
853 | } | |
854 | } | |
855 | ||
856 | impl<'a> Clean<WherePredicate> for ty::TraitPredicate<'a> { | |
857 | fn clean(&self, cx: &DocContext) -> WherePredicate { | |
858 | WherePredicate::BoundPredicate { | |
859 | ty: self.trait_ref.substs.self_ty().clean(cx).unwrap(), | |
860 | bounds: vec![self.trait_ref.clean(cx)] | |
861 | } | |
862 | } | |
863 | } | |
864 | ||
865 | impl<'tcx> Clean<WherePredicate> for ty::EquatePredicate<'tcx> { | |
866 | fn clean(&self, cx: &DocContext) -> WherePredicate { | |
867 | let ty::EquatePredicate(ref lhs, ref rhs) = *self; | |
868 | WherePredicate::EqPredicate { | |
869 | lhs: lhs.clean(cx), | |
870 | rhs: rhs.clean(cx) | |
871 | } | |
872 | } | |
873 | } | |
874 | ||
875 | impl Clean<WherePredicate> for ty::OutlivesPredicate<ty::Region, ty::Region> { | |
876 | fn clean(&self, cx: &DocContext) -> WherePredicate { | |
877 | let ty::OutlivesPredicate(ref a, ref b) = *self; | |
878 | WherePredicate::RegionPredicate { | |
879 | lifetime: a.clean(cx).unwrap(), | |
880 | bounds: vec![b.clean(cx).unwrap()] | |
881 | } | |
882 | } | |
883 | } | |
884 | ||
885 | impl<'tcx> Clean<WherePredicate> for ty::OutlivesPredicate<ty::Ty<'tcx>, ty::Region> { | |
886 | fn clean(&self, cx: &DocContext) -> WherePredicate { | |
887 | let ty::OutlivesPredicate(ref ty, ref lt) = *self; | |
888 | ||
889 | WherePredicate::BoundPredicate { | |
890 | ty: ty.clean(cx), | |
891 | bounds: vec![TyParamBound::RegionBound(lt.clean(cx).unwrap())] | |
892 | } | |
893 | } | |
894 | } | |
895 | ||
896 | impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> { | |
897 | fn clean(&self, cx: &DocContext) -> WherePredicate { | |
898 | WherePredicate::EqPredicate { | |
899 | lhs: self.projection_ty.clean(cx), | |
900 | rhs: self.ty.clean(cx) | |
901 | } | |
902 | } | |
903 | } | |
904 | ||
905 | impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> { | |
906 | fn clean(&self, cx: &DocContext) -> Type { | |
907 | let trait_ = match self.trait_ref.clean(cx) { | |
908 | TyParamBound::TraitBound(t, _) => t.trait_, | |
9346a6ac AL |
909 | TyParamBound::RegionBound(_) => { |
910 | panic!("cleaning a trait got a region") | |
911 | } | |
85aaf69f SL |
912 | }; |
913 | Type::QPath { | |
914 | name: self.item_name.clean(cx), | |
915 | self_type: box self.trait_ref.self_ty().clean(cx), | |
916 | trait_: box trait_ | |
917 | } | |
918 | } | |
919 | } | |
920 | ||
d9579d0f | 921 | // maybe use a Generic enum and use Vec<Generic>? |
85aaf69f | 922 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
923 | pub struct Generics { |
924 | pub lifetimes: Vec<Lifetime>, | |
925 | pub type_params: Vec<TyParam>, | |
926 | pub where_predicates: Vec<WherePredicate> | |
927 | } | |
928 | ||
e9174d1e | 929 | impl Clean<Generics> for hir::Generics { |
1a4d82fc JJ |
930 | fn clean(&self, cx: &DocContext) -> Generics { |
931 | Generics { | |
932 | lifetimes: self.lifetimes.clean(cx), | |
933 | type_params: self.ty_params.clean(cx), | |
934 | where_predicates: self.where_clause.predicates.clean(cx) | |
935 | } | |
936 | } | |
937 | } | |
938 | ||
85aaf69f SL |
939 | impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>, |
940 | &'a ty::GenericPredicates<'tcx>, | |
941 | subst::ParamSpace) { | |
1a4d82fc | 942 | fn clean(&self, cx: &DocContext) -> Generics { |
85aaf69f SL |
943 | use self::WherePredicate as WP; |
944 | ||
85aaf69f SL |
945 | let (gens, preds, space) = *self; |
946 | ||
9346a6ac AL |
947 | // Bounds in the type_params and lifetimes fields are repeated in the |
948 | // predicates field (see rustc_typeck::collect::ty_generics), so remove | |
949 | // them. | |
85aaf69f | 950 | let stripped_typarams = gens.types.get_slice(space).iter().map(|tp| { |
c34b1796 | 951 | tp.clean(cx) |
85aaf69f SL |
952 | }).collect::<Vec<_>>(); |
953 | let stripped_lifetimes = gens.regions.get_slice(space).iter().map(|rp| { | |
954 | let mut srp = rp.clone(); | |
955 | srp.bounds = Vec::new(); | |
956 | srp.clean(cx) | |
957 | }).collect::<Vec<_>>(); | |
958 | ||
9346a6ac AL |
959 | let mut where_predicates = preds.predicates.get_slice(space) |
960 | .to_vec().clean(cx); | |
85aaf69f | 961 | |
9346a6ac AL |
962 | // Type parameters and have a Sized bound by default unless removed with |
963 | // ?Sized. Scan through the predicates and mark any type parameter with | |
964 | // a Sized bound, removing the bounds as we find them. | |
965 | // | |
966 | // Note that associated types also have a sized bound by default, but we | |
d9579d0f | 967 | // don't actually know the set of associated types right here so that's |
9346a6ac | 968 | // handled in cleaning associated types |
85aaf69f | 969 | let mut sized_params = HashSet::new(); |
9346a6ac AL |
970 | where_predicates.retain(|pred| { |
971 | match *pred { | |
972 | WP::BoundPredicate { ty: Generic(ref g), ref bounds } => { | |
973 | if bounds.iter().any(|b| b.is_sized_bound(cx)) { | |
974 | sized_params.insert(g.clone()); | |
975 | false | |
976 | } else { | |
977 | true | |
978 | } | |
85aaf69f | 979 | } |
9346a6ac | 980 | _ => true, |
85aaf69f | 981 | } |
9346a6ac | 982 | }); |
85aaf69f | 983 | |
9346a6ac AL |
984 | // Run through the type parameters again and insert a ?Sized |
985 | // unbound for any we didn't find to be Sized. | |
85aaf69f SL |
986 | for tp in &stripped_typarams { |
987 | if !sized_params.contains(&tp.name) { | |
85aaf69f SL |
988 | where_predicates.push(WP::BoundPredicate { |
989 | ty: Type::Generic(tp.name.clone()), | |
9346a6ac | 990 | bounds: vec![TyParamBound::maybe_sized(cx)], |
85aaf69f SL |
991 | }) |
992 | } | |
993 | } | |
994 | ||
995 | // It would be nice to collect all of the bounds on a type and recombine | |
996 | // them if possible, to avoid e.g. `where T: Foo, T: Bar, T: Sized, T: 'a` | |
997 | // and instead see `where T: Foo + Bar + Sized + 'a` | |
998 | ||
1a4d82fc | 999 | Generics { |
9346a6ac | 1000 | type_params: simplify::ty_params(stripped_typarams), |
85aaf69f | 1001 | lifetimes: stripped_lifetimes, |
9346a6ac | 1002 | where_predicates: simplify::where_clauses(cx, where_predicates), |
1a4d82fc JJ |
1003 | } |
1004 | } | |
1005 | } | |
1006 | ||
85aaf69f | 1007 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
1008 | pub struct Method { |
1009 | pub generics: Generics, | |
1010 | pub self_: SelfTy, | |
e9174d1e SL |
1011 | pub unsafety: hir::Unsafety, |
1012 | pub constness: hir::Constness, | |
1a4d82fc | 1013 | pub decl: FnDecl, |
7453a54e | 1014 | pub abi: Abi, |
1a4d82fc JJ |
1015 | } |
1016 | ||
e9174d1e | 1017 | impl Clean<Method> for hir::MethodSig { |
c34b1796 AL |
1018 | fn clean(&self, cx: &DocContext) -> Method { |
1019 | let all_inputs = &self.decl.inputs; | |
1020 | let inputs = match self.explicit_self.node { | |
e9174d1e | 1021 | hir::SelfStatic => &**all_inputs, |
1a4d82fc JJ |
1022 | _ => &all_inputs[1..] |
1023 | }; | |
1024 | let decl = FnDecl { | |
1025 | inputs: Arguments { | |
c34b1796 | 1026 | values: inputs.clean(cx), |
1a4d82fc | 1027 | }, |
c34b1796 | 1028 | output: self.decl.output.clean(cx), |
e9174d1e | 1029 | variadic: false, |
1a4d82fc JJ |
1030 | attrs: Vec::new() |
1031 | }; | |
c34b1796 AL |
1032 | Method { |
1033 | generics: self.generics.clean(cx), | |
1034 | self_: self.explicit_self.node.clean(cx), | |
62682a34 SL |
1035 | unsafety: self.unsafety, |
1036 | constness: self.constness, | |
c34b1796 AL |
1037 | decl: decl, |
1038 | abi: self.abi | |
1a4d82fc JJ |
1039 | } |
1040 | } | |
1041 | } | |
1042 | ||
85aaf69f | 1043 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc | 1044 | pub struct TyMethod { |
e9174d1e | 1045 | pub unsafety: hir::Unsafety, |
1a4d82fc JJ |
1046 | pub decl: FnDecl, |
1047 | pub generics: Generics, | |
1048 | pub self_: SelfTy, | |
7453a54e | 1049 | pub abi: Abi, |
1a4d82fc JJ |
1050 | } |
1051 | ||
e9174d1e | 1052 | impl Clean<TyMethod> for hir::MethodSig { |
c34b1796 | 1053 | fn clean(&self, cx: &DocContext) -> TyMethod { |
1a4d82fc | 1054 | let inputs = match self.explicit_self.node { |
e9174d1e | 1055 | hir::SelfStatic => &*self.decl.inputs, |
1a4d82fc JJ |
1056 | _ => &self.decl.inputs[1..] |
1057 | }; | |
1058 | let decl = FnDecl { | |
1059 | inputs: Arguments { | |
c34b1796 | 1060 | values: inputs.clean(cx), |
1a4d82fc JJ |
1061 | }, |
1062 | output: self.decl.output.clean(cx), | |
e9174d1e | 1063 | variadic: false, |
1a4d82fc JJ |
1064 | attrs: Vec::new() |
1065 | }; | |
c34b1796 AL |
1066 | TyMethod { |
1067 | unsafety: self.unsafety.clone(), | |
1068 | decl: decl, | |
1069 | self_: self.explicit_self.node.clean(cx), | |
1070 | generics: self.generics.clean(cx), | |
1071 | abi: self.abi | |
1a4d82fc JJ |
1072 | } |
1073 | } | |
1074 | } | |
1075 | ||
85aaf69f | 1076 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
1077 | pub enum SelfTy { |
1078 | SelfStatic, | |
1079 | SelfValue, | |
1080 | SelfBorrowed(Option<Lifetime>, Mutability), | |
1081 | SelfExplicit(Type), | |
1082 | } | |
1083 | ||
e9174d1e | 1084 | impl Clean<SelfTy> for hir::ExplicitSelf_ { |
1a4d82fc JJ |
1085 | fn clean(&self, cx: &DocContext) -> SelfTy { |
1086 | match *self { | |
e9174d1e SL |
1087 | hir::SelfStatic => SelfStatic, |
1088 | hir::SelfValue(_) => SelfValue, | |
1089 | hir::SelfRegion(ref lt, ref mt, _) => { | |
1a4d82fc JJ |
1090 | SelfBorrowed(lt.clean(cx), mt.clean(cx)) |
1091 | } | |
e9174d1e | 1092 | hir::SelfExplicit(ref typ, _) => SelfExplicit(typ.clean(cx)), |
1a4d82fc JJ |
1093 | } |
1094 | } | |
1095 | } | |
1096 | ||
85aaf69f | 1097 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
1098 | pub struct Function { |
1099 | pub decl: FnDecl, | |
1100 | pub generics: Generics, | |
e9174d1e SL |
1101 | pub unsafety: hir::Unsafety, |
1102 | pub constness: hir::Constness, | |
7453a54e | 1103 | pub abi: Abi, |
1a4d82fc JJ |
1104 | } |
1105 | ||
1106 | impl Clean<Item> for doctree::Function { | |
1107 | fn clean(&self, cx: &DocContext) -> Item { | |
1108 | Item { | |
1109 | name: Some(self.name.clean(cx)), | |
1110 | attrs: self.attrs.clean(cx), | |
1111 | source: self.whence.clean(cx), | |
1112 | visibility: self.vis.clean(cx), | |
1113 | stability: self.stab.clean(cx), | |
9cc50fc6 | 1114 | deprecation: self.depr.clean(cx), |
b039eaaf | 1115 | def_id: cx.map.local_def_id(self.id), |
1a4d82fc JJ |
1116 | inner: FunctionItem(Function { |
1117 | decl: self.decl.clean(cx), | |
1118 | generics: self.generics.clean(cx), | |
1119 | unsafety: self.unsafety, | |
62682a34 | 1120 | constness: self.constness, |
9346a6ac | 1121 | abi: self.abi, |
1a4d82fc JJ |
1122 | }), |
1123 | } | |
1124 | } | |
1125 | } | |
1126 | ||
85aaf69f | 1127 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
1128 | pub struct FnDecl { |
1129 | pub inputs: Arguments, | |
1130 | pub output: FunctionRetTy, | |
e9174d1e | 1131 | pub variadic: bool, |
1a4d82fc JJ |
1132 | pub attrs: Vec<Attribute>, |
1133 | } | |
1134 | ||
85aaf69f | 1135 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
1136 | pub struct Arguments { |
1137 | pub values: Vec<Argument>, | |
1138 | } | |
1139 | ||
e9174d1e | 1140 | impl Clean<FnDecl> for hir::FnDecl { |
1a4d82fc JJ |
1141 | fn clean(&self, cx: &DocContext) -> FnDecl { |
1142 | FnDecl { | |
1143 | inputs: Arguments { | |
1144 | values: self.inputs.clean(cx), | |
1145 | }, | |
1146 | output: self.output.clean(cx), | |
e9174d1e | 1147 | variadic: self.variadic, |
1a4d82fc JJ |
1148 | attrs: Vec::new() |
1149 | } | |
1150 | } | |
1151 | } | |
1152 | ||
1153 | impl<'tcx> Clean<Type> for ty::FnOutput<'tcx> { | |
1154 | fn clean(&self, cx: &DocContext) -> Type { | |
1155 | match *self { | |
1156 | ty::FnConverging(ty) => ty.clean(cx), | |
1157 | ty::FnDiverging => Bottom | |
1158 | } | |
1159 | } | |
1160 | } | |
1161 | ||
e9174d1e | 1162 | impl<'a, 'tcx> Clean<FnDecl> for (DefId, &'a ty::PolyFnSig<'tcx>) { |
1a4d82fc JJ |
1163 | fn clean(&self, cx: &DocContext) -> FnDecl { |
1164 | let (did, sig) = *self; | |
54a0048b | 1165 | let mut names = if cx.map.as_local_node_id(did).is_some() { |
b039eaaf | 1166 | vec![].into_iter() |
1a4d82fc | 1167 | } else { |
92a42be0 | 1168 | cx.tcx().sess.cstore.method_arg_names(did).into_iter() |
1a4d82fc | 1169 | }.peekable(); |
54a0048b | 1170 | if let Some("self") = names.peek().map(|s| &s[..]) { |
1a4d82fc JJ |
1171 | let _ = names.next(); |
1172 | } | |
1173 | FnDecl { | |
1174 | output: Return(sig.0.output.clean(cx)), | |
1175 | attrs: Vec::new(), | |
e9174d1e | 1176 | variadic: sig.0.variadic, |
1a4d82fc JJ |
1177 | inputs: Arguments { |
1178 | values: sig.0.inputs.iter().map(|t| { | |
1179 | Argument { | |
1180 | type_: t.clean(cx), | |
1181 | id: 0, | |
1182 | name: names.next().unwrap_or("".to_string()), | |
1183 | } | |
1184 | }).collect(), | |
1185 | }, | |
1186 | } | |
1187 | } | |
1188 | } | |
1189 | ||
85aaf69f | 1190 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
1191 | pub struct Argument { |
1192 | pub type_: Type, | |
1193 | pub name: String, | |
1194 | pub id: ast::NodeId, | |
1195 | } | |
1196 | ||
e9174d1e | 1197 | impl Clean<Argument> for hir::Arg { |
1a4d82fc JJ |
1198 | fn clean(&self, cx: &DocContext) -> Argument { |
1199 | Argument { | |
1200 | name: name_from_pat(&*self.pat), | |
1201 | type_: (self.ty.clean(cx)), | |
1202 | id: self.id | |
1203 | } | |
1204 | } | |
1205 | } | |
1206 | ||
85aaf69f | 1207 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
1208 | pub enum FunctionRetTy { |
1209 | Return(Type), | |
85aaf69f | 1210 | DefaultReturn, |
1a4d82fc JJ |
1211 | NoReturn |
1212 | } | |
1213 | ||
e9174d1e | 1214 | impl Clean<FunctionRetTy> for hir::FunctionRetTy { |
1a4d82fc JJ |
1215 | fn clean(&self, cx: &DocContext) -> FunctionRetTy { |
1216 | match *self { | |
e9174d1e SL |
1217 | hir::Return(ref typ) => Return(typ.clean(cx)), |
1218 | hir::DefaultReturn(..) => DefaultReturn, | |
1219 | hir::NoReturn(..) => NoReturn | |
1a4d82fc JJ |
1220 | } |
1221 | } | |
1222 | } | |
1223 | ||
85aaf69f | 1224 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc | 1225 | pub struct Trait { |
e9174d1e | 1226 | pub unsafety: hir::Unsafety, |
c34b1796 | 1227 | pub items: Vec<Item>, |
1a4d82fc JJ |
1228 | pub generics: Generics, |
1229 | pub bounds: Vec<TyParamBound>, | |
1230 | } | |
1231 | ||
1232 | impl Clean<Item> for doctree::Trait { | |
1233 | fn clean(&self, cx: &DocContext) -> Item { | |
1234 | Item { | |
1235 | name: Some(self.name.clean(cx)), | |
1236 | attrs: self.attrs.clean(cx), | |
1237 | source: self.whence.clean(cx), | |
b039eaaf | 1238 | def_id: cx.map.local_def_id(self.id), |
1a4d82fc JJ |
1239 | visibility: self.vis.clean(cx), |
1240 | stability: self.stab.clean(cx), | |
9cc50fc6 | 1241 | deprecation: self.depr.clean(cx), |
1a4d82fc JJ |
1242 | inner: TraitItem(Trait { |
1243 | unsafety: self.unsafety, | |
1244 | items: self.items.clean(cx), | |
1245 | generics: self.generics.clean(cx), | |
1246 | bounds: self.bounds.clean(cx), | |
1247 | }), | |
1248 | } | |
1249 | } | |
1250 | } | |
1251 | ||
e9174d1e | 1252 | impl Clean<Type> for hir::TraitRef { |
1a4d82fc JJ |
1253 | fn clean(&self, cx: &DocContext) -> Type { |
1254 | resolve_type(cx, self.path.clean(cx), self.ref_id) | |
1255 | } | |
1256 | } | |
1257 | ||
e9174d1e | 1258 | impl Clean<PolyTrait> for hir::PolyTraitRef { |
1a4d82fc JJ |
1259 | fn clean(&self, cx: &DocContext) -> PolyTrait { |
1260 | PolyTrait { | |
1261 | trait_: self.trait_ref.clean(cx), | |
1262 | lifetimes: self.bound_lifetimes.clean(cx) | |
1263 | } | |
1264 | } | |
1265 | } | |
1266 | ||
e9174d1e | 1267 | impl Clean<Item> for hir::TraitItem { |
c34b1796 AL |
1268 | fn clean(&self, cx: &DocContext) -> Item { |
1269 | let inner = match self.node { | |
e9174d1e | 1270 | hir::ConstTraitItem(ref ty, ref default) => { |
d9579d0f AL |
1271 | AssociatedConstItem(ty.clean(cx), |
1272 | default.as_ref().map(|expr| | |
1273 | expr.span.to_src(cx))) | |
1274 | } | |
e9174d1e | 1275 | hir::MethodTraitItem(ref sig, Some(_)) => { |
c34b1796 AL |
1276 | MethodItem(sig.clean(cx)) |
1277 | } | |
e9174d1e | 1278 | hir::MethodTraitItem(ref sig, None) => { |
c34b1796 AL |
1279 | TyMethodItem(sig.clean(cx)) |
1280 | } | |
e9174d1e | 1281 | hir::TypeTraitItem(ref bounds, ref default) => { |
c34b1796 AL |
1282 | AssociatedTypeItem(bounds.clean(cx), default.clean(cx)) |
1283 | } | |
1284 | }; | |
1285 | Item { | |
b039eaaf | 1286 | name: Some(self.name.clean(cx)), |
c34b1796 AL |
1287 | attrs: self.attrs.clean(cx), |
1288 | source: self.span.clean(cx), | |
b039eaaf | 1289 | def_id: cx.map.local_def_id(self.id), |
c34b1796 | 1290 | visibility: None, |
b039eaaf | 1291 | stability: get_stability(cx, cx.map.local_def_id(self.id)), |
9cc50fc6 | 1292 | deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)), |
c34b1796 | 1293 | inner: inner |
1a4d82fc JJ |
1294 | } |
1295 | } | |
1296 | } | |
1297 | ||
e9174d1e | 1298 | impl Clean<Item> for hir::ImplItem { |
c34b1796 AL |
1299 | fn clean(&self, cx: &DocContext) -> Item { |
1300 | let inner = match self.node { | |
92a42be0 | 1301 | hir::ImplItemKind::Const(ref ty, ref expr) => { |
7453a54e SL |
1302 | AssociatedConstItem(ty.clean(cx), |
1303 | Some(expr.span.to_src(cx))) | |
d9579d0f | 1304 | } |
92a42be0 | 1305 | hir::ImplItemKind::Method(ref sig, _) => { |
c34b1796 AL |
1306 | MethodItem(sig.clean(cx)) |
1307 | } | |
92a42be0 | 1308 | hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef { |
c34b1796 AL |
1309 | type_: ty.clean(cx), |
1310 | generics: Generics { | |
1311 | lifetimes: Vec::new(), | |
1312 | type_params: Vec::new(), | |
1313 | where_predicates: Vec::new() | |
1314 | }, | |
62682a34 | 1315 | }, true), |
c34b1796 AL |
1316 | }; |
1317 | Item { | |
b039eaaf | 1318 | name: Some(self.name.clean(cx)), |
c34b1796 AL |
1319 | source: self.span.clean(cx), |
1320 | attrs: self.attrs.clean(cx), | |
b039eaaf | 1321 | def_id: cx.map.local_def_id(self.id), |
c34b1796 | 1322 | visibility: self.vis.clean(cx), |
b039eaaf | 1323 | stability: get_stability(cx, cx.map.local_def_id(self.id)), |
9cc50fc6 | 1324 | deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)), |
c34b1796 | 1325 | inner: inner |
1a4d82fc JJ |
1326 | } |
1327 | } | |
1328 | } | |
1329 | ||
1330 | impl<'tcx> Clean<Item> for ty::Method<'tcx> { | |
1331 | fn clean(&self, cx: &DocContext) -> Item { | |
1332 | let (self_, sig) = match self.explicit_self { | |
9cc50fc6 SL |
1333 | ty::ExplicitSelfCategory::Static => (hir::SelfStatic.clean(cx), |
1334 | self.fty.sig.clone()), | |
1a4d82fc JJ |
1335 | s => { |
1336 | let sig = ty::Binder(ty::FnSig { | |
1337 | inputs: self.fty.sig.0.inputs[1..].to_vec(), | |
1338 | ..self.fty.sig.0.clone() | |
1339 | }); | |
1340 | let s = match s { | |
9cc50fc6 SL |
1341 | ty::ExplicitSelfCategory::ByValue => SelfValue, |
1342 | ty::ExplicitSelfCategory::ByReference(..) => { | |
1a4d82fc | 1343 | match self.fty.sig.0.inputs[0].sty { |
62682a34 | 1344 | ty::TyRef(r, mt) => { |
1a4d82fc JJ |
1345 | SelfBorrowed(r.clean(cx), mt.mutbl.clean(cx)) |
1346 | } | |
1347 | _ => unreachable!(), | |
1348 | } | |
1349 | } | |
9cc50fc6 | 1350 | ty::ExplicitSelfCategory::ByBox => { |
1a4d82fc JJ |
1351 | SelfExplicit(self.fty.sig.0.inputs[0].clean(cx)) |
1352 | } | |
9cc50fc6 | 1353 | ty::ExplicitSelfCategory::Static => unreachable!(), |
1a4d82fc JJ |
1354 | }; |
1355 | (s, sig) | |
1356 | } | |
1357 | }; | |
1358 | ||
9346a6ac AL |
1359 | let generics = (&self.generics, &self.predicates, |
1360 | subst::FnSpace).clean(cx); | |
1361 | let decl = (self.def_id, &sig).clean(cx); | |
1362 | let provided = match self.container { | |
1363 | ty::ImplContainer(..) => false, | |
1364 | ty::TraitContainer(did) => { | |
c1a9b12d | 1365 | cx.tcx().provided_trait_methods(did).iter().any(|m| { |
9346a6ac AL |
1366 | m.def_id == self.def_id |
1367 | }) | |
1368 | } | |
1369 | }; | |
1370 | let inner = if provided { | |
1371 | MethodItem(Method { | |
1372 | unsafety: self.fty.unsafety, | |
1373 | generics: generics, | |
1374 | self_: self_, | |
1375 | decl: decl, | |
62682a34 SL |
1376 | abi: self.fty.abi, |
1377 | ||
1378 | // trait methods canot (currently, at least) be const | |
e9174d1e | 1379 | constness: hir::Constness::NotConst, |
9346a6ac AL |
1380 | }) |
1381 | } else { | |
1382 | TyMethodItem(TyMethod { | |
1383 | unsafety: self.fty.unsafety, | |
1384 | generics: generics, | |
1385 | self_: self_, | |
1386 | decl: decl, | |
62682a34 | 1387 | abi: self.fty.abi, |
9346a6ac AL |
1388 | }) |
1389 | }; | |
1390 | ||
1a4d82fc JJ |
1391 | Item { |
1392 | name: Some(self.name.clean(cx)), | |
e9174d1e | 1393 | visibility: Some(hir::Inherited), |
1a4d82fc | 1394 | stability: get_stability(cx, self.def_id), |
9cc50fc6 | 1395 | deprecation: get_deprecation(cx, self.def_id), |
1a4d82fc JJ |
1396 | def_id: self.def_id, |
1397 | attrs: inline::load_attrs(cx, cx.tcx(), self.def_id), | |
1398 | source: Span::empty(), | |
9346a6ac | 1399 | inner: inner, |
1a4d82fc JJ |
1400 | } |
1401 | } | |
1402 | } | |
1403 | ||
1404 | impl<'tcx> Clean<Item> for ty::ImplOrTraitItem<'tcx> { | |
1405 | fn clean(&self, cx: &DocContext) -> Item { | |
1406 | match *self { | |
d9579d0f | 1407 | ty::ConstTraitItem(ref cti) => cti.clean(cx), |
1a4d82fc JJ |
1408 | ty::MethodTraitItem(ref mti) => mti.clean(cx), |
1409 | ty::TypeTraitItem(ref tti) => tti.clean(cx), | |
1410 | } | |
1411 | } | |
1412 | } | |
1413 | ||
1414 | /// A trait reference, which may have higher ranked lifetimes. | |
85aaf69f | 1415 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
1416 | pub struct PolyTrait { |
1417 | pub trait_: Type, | |
1418 | pub lifetimes: Vec<Lifetime> | |
1419 | } | |
1420 | ||
1421 | /// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original | |
54a0048b | 1422 | /// type out of the AST/TyCtxt given one of these, if more information is needed. Most importantly |
1a4d82fc | 1423 | /// it does not preserve mutability or boxes. |
85aaf69f | 1424 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc | 1425 | pub enum Type { |
e9174d1e | 1426 | /// structs/enums/traits (most that'd be an hir::TyPath) |
1a4d82fc JJ |
1427 | ResolvedPath { |
1428 | path: Path, | |
1429 | typarams: Option<Vec<TyParamBound>>, | |
e9174d1e | 1430 | did: DefId, |
62682a34 SL |
1431 | /// true if is a `T::Name` path for associated types |
1432 | is_generic: bool, | |
1a4d82fc | 1433 | }, |
1a4d82fc JJ |
1434 | /// For parameterized types, so the consumer of the JSON don't go |
1435 | /// looking for types which don't exist anywhere. | |
1436 | Generic(String), | |
c34b1796 AL |
1437 | /// Primitives are the fixed-size numeric types (plus int/usize/float), char, |
1438 | /// arrays, slices, and tuples. | |
1a4d82fc | 1439 | Primitive(PrimitiveType), |
1a4d82fc JJ |
1440 | /// extern "ABI" fn |
1441 | BareFunction(Box<BareFunctionDecl>), | |
1442 | Tuple(Vec<Type>), | |
1443 | Vector(Box<Type>), | |
1444 | FixedVector(Box<Type>, String), | |
1445 | /// aka TyBot | |
1446 | Bottom, | |
1447 | Unique(Box<Type>), | |
1448 | RawPointer(Mutability, Box<Type>), | |
1449 | BorrowedRef { | |
1450 | lifetime: Option<Lifetime>, | |
1451 | mutability: Mutability, | |
1452 | type_: Box<Type>, | |
1453 | }, | |
1454 | ||
1455 | // <Type as Trait>::Name | |
1456 | QPath { | |
1457 | name: String, | |
1458 | self_type: Box<Type>, | |
1459 | trait_: Box<Type> | |
1460 | }, | |
1461 | ||
1462 | // _ | |
1463 | Infer, | |
1464 | ||
1465 | // for<'a> Foo(&'a) | |
1466 | PolyTraitRef(Vec<TyParamBound>), | |
1467 | } | |
1468 | ||
85aaf69f | 1469 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)] |
1a4d82fc JJ |
1470 | pub enum PrimitiveType { |
1471 | Isize, I8, I16, I32, I64, | |
1472 | Usize, U8, U16, U32, U64, | |
1473 | F32, F64, | |
1474 | Char, | |
1475 | Bool, | |
1476 | Str, | |
1477 | Slice, | |
c34b1796 | 1478 | Array, |
1a4d82fc | 1479 | PrimitiveTuple, |
9346a6ac | 1480 | PrimitiveRawPointer, |
1a4d82fc JJ |
1481 | } |
1482 | ||
85aaf69f | 1483 | #[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)] |
1a4d82fc JJ |
1484 | pub enum TypeKind { |
1485 | TypeEnum, | |
1486 | TypeFunction, | |
1487 | TypeModule, | |
1488 | TypeConst, | |
1489 | TypeStatic, | |
1490 | TypeStruct, | |
1491 | TypeTrait, | |
1492 | TypeVariant, | |
1493 | TypeTypedef, | |
1494 | } | |
1495 | ||
54a0048b SL |
1496 | pub trait GetDefId { |
1497 | fn def_id(&self) -> Option<DefId>; | |
1498 | } | |
1499 | ||
1500 | impl<T: GetDefId> GetDefId for Option<T> { | |
1501 | fn def_id(&self) -> Option<DefId> { | |
1502 | self.as_ref().and_then(|d| d.def_id()) | |
1503 | } | |
1504 | } | |
1505 | ||
9346a6ac AL |
1506 | impl Type { |
1507 | pub fn primitive_type(&self) -> Option<PrimitiveType> { | |
1508 | match *self { | |
1509 | Primitive(p) | BorrowedRef { type_: box Primitive(p), ..} => Some(p), | |
1510 | Vector(..) | BorrowedRef{ type_: box Vector(..), .. } => Some(Slice), | |
1511 | FixedVector(..) | BorrowedRef { type_: box FixedVector(..), .. } => { | |
1512 | Some(Array) | |
1513 | } | |
1514 | Tuple(..) => Some(PrimitiveTuple), | |
1515 | RawPointer(..) => Some(PrimitiveRawPointer), | |
1516 | _ => None, | |
1517 | } | |
1518 | } | |
1519 | } | |
1520 | ||
54a0048b SL |
1521 | impl GetDefId for Type { |
1522 | fn def_id(&self) -> Option<DefId> { | |
1523 | match *self { | |
1524 | ResolvedPath { did, .. } => Some(did), | |
1525 | _ => None, | |
1526 | } | |
1527 | } | |
1528 | } | |
1529 | ||
1a4d82fc JJ |
1530 | impl PrimitiveType { |
1531 | fn from_str(s: &str) -> Option<PrimitiveType> { | |
85aaf69f | 1532 | match s { |
c34b1796 | 1533 | "isize" => Some(Isize), |
1a4d82fc JJ |
1534 | "i8" => Some(I8), |
1535 | "i16" => Some(I16), | |
1536 | "i32" => Some(I32), | |
1537 | "i64" => Some(I64), | |
c34b1796 | 1538 | "usize" => Some(Usize), |
1a4d82fc JJ |
1539 | "u8" => Some(U8), |
1540 | "u16" => Some(U16), | |
1541 | "u32" => Some(U32), | |
1542 | "u64" => Some(U64), | |
1543 | "bool" => Some(Bool), | |
1544 | "char" => Some(Char), | |
1545 | "str" => Some(Str), | |
1546 | "f32" => Some(F32), | |
1547 | "f64" => Some(F64), | |
c34b1796 | 1548 | "array" => Some(Array), |
1a4d82fc JJ |
1549 | "slice" => Some(Slice), |
1550 | "tuple" => Some(PrimitiveTuple), | |
9346a6ac | 1551 | "pointer" => Some(PrimitiveRawPointer), |
1a4d82fc JJ |
1552 | _ => None, |
1553 | } | |
1554 | } | |
1555 | ||
1556 | fn find(attrs: &[Attribute]) -> Option<PrimitiveType> { | |
54a0048b SL |
1557 | for attr in attrs.list("doc") { |
1558 | if let NameValue(ref k, ref v) = *attr { | |
1559 | if "primitive" == *k { | |
1560 | if let ret@Some(..) = PrimitiveType::from_str(v) { | |
1561 | return ret; | |
1562 | } | |
1a4d82fc JJ |
1563 | } |
1564 | } | |
1565 | } | |
54a0048b | 1566 | None |
1a4d82fc JJ |
1567 | } |
1568 | ||
1569 | pub fn to_string(&self) -> &'static str { | |
1570 | match *self { | |
1571 | Isize => "isize", | |
1572 | I8 => "i8", | |
1573 | I16 => "i16", | |
1574 | I32 => "i32", | |
1575 | I64 => "i64", | |
1576 | Usize => "usize", | |
1577 | U8 => "u8", | |
1578 | U16 => "u16", | |
1579 | U32 => "u32", | |
1580 | U64 => "u64", | |
1581 | F32 => "f32", | |
1582 | F64 => "f64", | |
1583 | Str => "str", | |
1584 | Bool => "bool", | |
1585 | Char => "char", | |
c34b1796 | 1586 | Array => "array", |
1a4d82fc JJ |
1587 | Slice => "slice", |
1588 | PrimitiveTuple => "tuple", | |
9346a6ac | 1589 | PrimitiveRawPointer => "pointer", |
1a4d82fc JJ |
1590 | } |
1591 | } | |
1592 | ||
1593 | pub fn to_url_str(&self) -> &'static str { | |
1594 | self.to_string() | |
1595 | } | |
1596 | ||
1597 | /// Creates a rustdoc-specific node id for primitive types. | |
1598 | /// | |
1599 | /// These node ids are generally never used by the AST itself. | |
b039eaaf SL |
1600 | pub fn to_def_index(&self) -> DefIndex { |
1601 | let x = u32::MAX - 1 - (*self as u32); | |
1602 | DefIndex::new(x as usize) | |
1a4d82fc JJ |
1603 | } |
1604 | } | |
1605 | ||
e9174d1e | 1606 | impl Clean<Type> for hir::Ty { |
1a4d82fc | 1607 | fn clean(&self, cx: &DocContext) -> Type { |
54a0048b | 1608 | use rustc::hir::*; |
1a4d82fc JJ |
1609 | match self.node { |
1610 | TyPtr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)), | |
1611 | TyRptr(ref l, ref m) => | |
1612 | BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx), | |
1613 | type_: box m.ty.clean(cx)}, | |
1614 | TyVec(ref ty) => Vector(box ty.clean(cx)), | |
1615 | TyFixedLengthVec(ref ty, ref e) => FixedVector(box ty.clean(cx), | |
1616 | e.span.to_src(cx)), | |
1617 | TyTup(ref tys) => Tuple(tys.clean(cx)), | |
c34b1796 AL |
1618 | TyPath(None, ref p) => { |
1619 | resolve_type(cx, p.clean(cx), self.id) | |
1620 | } | |
1621 | TyPath(Some(ref qself), ref p) => { | |
9cc50fc6 SL |
1622 | let mut segments: Vec<_> = p.segments.clone().into(); |
1623 | segments.pop(); | |
1624 | let trait_path = hir::Path { | |
1625 | span: p.span, | |
1626 | global: p.global, | |
1627 | segments: segments.into(), | |
1628 | }; | |
c34b1796 | 1629 | Type::QPath { |
b039eaaf | 1630 | name: p.segments.last().unwrap().identifier.name.clean(cx), |
c34b1796 AL |
1631 | self_type: box qself.ty.clean(cx), |
1632 | trait_: box resolve_type(cx, trait_path.clean(cx), self.id) | |
1633 | } | |
1a4d82fc JJ |
1634 | } |
1635 | TyObjectSum(ref lhs, ref bounds) => { | |
1636 | let lhs_ty = lhs.clean(cx); | |
1637 | match lhs_ty { | |
62682a34 SL |
1638 | ResolvedPath { path, typarams: None, did, is_generic } => { |
1639 | ResolvedPath { | |
1640 | path: path, | |
1641 | typarams: Some(bounds.clean(cx)), | |
1642 | did: did, | |
1643 | is_generic: is_generic, | |
1644 | } | |
1a4d82fc JJ |
1645 | } |
1646 | _ => { | |
1647 | lhs_ty // shouldn't happen | |
1648 | } | |
1649 | } | |
1650 | } | |
1651 | TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)), | |
54a0048b SL |
1652 | TyPolyTraitRef(ref bounds) => PolyTraitRef(bounds.clean(cx)), |
1653 | TyInfer => Infer, | |
1654 | TyTypeof(..) => panic!("Unimplemented type {:?}", self.node), | |
1a4d82fc JJ |
1655 | } |
1656 | } | |
1657 | } | |
1658 | ||
1659 | impl<'tcx> Clean<Type> for ty::Ty<'tcx> { | |
1660 | fn clean(&self, cx: &DocContext) -> Type { | |
1661 | match self.sty { | |
62682a34 SL |
1662 | ty::TyBool => Primitive(Bool), |
1663 | ty::TyChar => Primitive(Char), | |
7453a54e SL |
1664 | ty::TyInt(ast::IntTy::Is) => Primitive(Isize), |
1665 | ty::TyInt(ast::IntTy::I8) => Primitive(I8), | |
1666 | ty::TyInt(ast::IntTy::I16) => Primitive(I16), | |
1667 | ty::TyInt(ast::IntTy::I32) => Primitive(I32), | |
1668 | ty::TyInt(ast::IntTy::I64) => Primitive(I64), | |
1669 | ty::TyUint(ast::UintTy::Us) => Primitive(Usize), | |
1670 | ty::TyUint(ast::UintTy::U8) => Primitive(U8), | |
1671 | ty::TyUint(ast::UintTy::U16) => Primitive(U16), | |
1672 | ty::TyUint(ast::UintTy::U32) => Primitive(U32), | |
1673 | ty::TyUint(ast::UintTy::U64) => Primitive(U64), | |
1674 | ty::TyFloat(ast::FloatTy::F32) => Primitive(F32), | |
1675 | ty::TyFloat(ast::FloatTy::F64) => Primitive(F64), | |
62682a34 SL |
1676 | ty::TyStr => Primitive(Str), |
1677 | ty::TyBox(t) => { | |
1a4d82fc JJ |
1678 | let box_did = cx.tcx_opt().and_then(|tcx| { |
1679 | tcx.lang_items.owned_box() | |
1680 | }); | |
1681 | lang_struct(cx, box_did, t, "Box", Unique) | |
1682 | } | |
62682a34 SL |
1683 | ty::TySlice(ty) => Vector(box ty.clean(cx)), |
1684 | ty::TyArray(ty, i) => FixedVector(box ty.clean(cx), | |
1685 | format!("{}", i)), | |
1686 | ty::TyRawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)), | |
1687 | ty::TyRef(r, mt) => BorrowedRef { | |
1a4d82fc JJ |
1688 | lifetime: r.clean(cx), |
1689 | mutability: mt.mutbl.clean(cx), | |
1690 | type_: box mt.ty.clean(cx), | |
1691 | }, | |
54a0048b SL |
1692 | ty::TyFnDef(_, _, ref fty) | |
1693 | ty::TyFnPtr(ref fty) => BareFunction(box BareFunctionDecl { | |
1a4d82fc JJ |
1694 | unsafety: fty.unsafety, |
1695 | generics: Generics { | |
1696 | lifetimes: Vec::new(), | |
1697 | type_params: Vec::new(), | |
1698 | where_predicates: Vec::new() | |
1699 | }, | |
b039eaaf | 1700 | decl: (cx.map.local_def_id(0), &fty.sig).clean(cx), |
1a4d82fc JJ |
1701 | abi: fty.abi.to_string(), |
1702 | }), | |
e9174d1e SL |
1703 | ty::TyStruct(def, substs) | |
1704 | ty::TyEnum(def, substs) => { | |
1705 | let did = def.did; | |
1a4d82fc | 1706 | let kind = match self.sty { |
62682a34 | 1707 | ty::TyStruct(..) => TypeStruct, |
1a4d82fc JJ |
1708 | _ => TypeEnum, |
1709 | }; | |
92a42be0 SL |
1710 | inline::record_extern_fqn(cx, did, kind); |
1711 | let path = external_path(cx, &cx.tcx().item_name(did).as_str(), | |
85aaf69f | 1712 | None, vec![], substs); |
1a4d82fc JJ |
1713 | ResolvedPath { |
1714 | path: path, | |
1715 | typarams: None, | |
1716 | did: did, | |
62682a34 | 1717 | is_generic: false, |
1a4d82fc JJ |
1718 | } |
1719 | } | |
62682a34 | 1720 | ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => { |
1a4d82fc | 1721 | let did = principal.def_id(); |
92a42be0 | 1722 | inline::record_extern_fqn(cx, did, TypeTrait); |
85aaf69f | 1723 | let (typarams, bindings) = bounds.clean(cx); |
92a42be0 | 1724 | let path = external_path(cx, &cx.tcx().item_name(did).as_str(), |
85aaf69f | 1725 | Some(did), bindings, principal.substs()); |
1a4d82fc JJ |
1726 | ResolvedPath { |
1727 | path: path, | |
85aaf69f | 1728 | typarams: Some(typarams), |
1a4d82fc | 1729 | did: did, |
62682a34 | 1730 | is_generic: false, |
1a4d82fc JJ |
1731 | } |
1732 | } | |
62682a34 | 1733 | ty::TyTuple(ref t) => Tuple(t.clean(cx)), |
1a4d82fc | 1734 | |
62682a34 | 1735 | ty::TyProjection(ref data) => data.clean(cx), |
1a4d82fc | 1736 | |
c1a9b12d | 1737 | ty::TyParam(ref p) => Generic(p.name.to_string()), |
1a4d82fc | 1738 | |
62682a34 | 1739 | ty::TyClosure(..) => Tuple(vec![]), // FIXME(pcwalton) |
1a4d82fc | 1740 | |
62682a34 SL |
1741 | ty::TyInfer(..) => panic!("TyInfer"), |
1742 | ty::TyError => panic!("TyError"), | |
1a4d82fc JJ |
1743 | } |
1744 | } | |
1745 | } | |
1746 | ||
e9174d1e | 1747 | impl Clean<Item> for hir::StructField { |
1a4d82fc | 1748 | fn clean(&self, cx: &DocContext) -> Item { |
1a4d82fc | 1749 | Item { |
54a0048b SL |
1750 | name: Some(self.name).clean(cx), |
1751 | attrs: self.attrs.clean(cx), | |
1a4d82fc | 1752 | source: self.span.clean(cx), |
54a0048b SL |
1753 | visibility: self.vis.clean(cx), |
1754 | stability: get_stability(cx, cx.map.local_def_id(self.id)), | |
1755 | deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)), | |
1756 | def_id: cx.map.local_def_id(self.id), | |
1757 | inner: StructFieldItem(self.ty.clean(cx)), | |
1a4d82fc JJ |
1758 | } |
1759 | } | |
1760 | } | |
1761 | ||
e9174d1e | 1762 | impl<'tcx> Clean<Item> for ty::FieldDefData<'tcx, 'static> { |
1a4d82fc | 1763 | fn clean(&self, cx: &DocContext) -> Item { |
92a42be0 | 1764 | // FIXME: possible O(n^2)-ness! Not my fault. |
54a0048b | 1765 | let attr_map = cx.tcx().sess.cstore.crate_struct_field_attrs(self.did.krate); |
1a4d82fc | 1766 | Item { |
54a0048b SL |
1767 | name: Some(self.name).clean(cx), |
1768 | attrs: attr_map.get(&self.did).unwrap_or(&Vec::new()).clean(cx), | |
1a4d82fc | 1769 | source: Span::empty(), |
54a0048b | 1770 | visibility: self.vis.clean(cx), |
e9174d1e | 1771 | stability: get_stability(cx, self.did), |
9cc50fc6 | 1772 | deprecation: get_deprecation(cx, self.did), |
e9174d1e | 1773 | def_id: self.did, |
54a0048b | 1774 | inner: StructFieldItem(self.unsubst_ty().clean(cx)), |
1a4d82fc JJ |
1775 | } |
1776 | } | |
1777 | } | |
1778 | ||
e9174d1e | 1779 | pub type Visibility = hir::Visibility; |
1a4d82fc | 1780 | |
e9174d1e | 1781 | impl Clean<Option<Visibility>> for hir::Visibility { |
1a4d82fc | 1782 | fn clean(&self, _: &DocContext) -> Option<Visibility> { |
54a0048b SL |
1783 | Some(self.clone()) |
1784 | } | |
1785 | } | |
1786 | ||
1787 | impl Clean<Option<Visibility>> for ty::Visibility { | |
1788 | fn clean(&self, _: &DocContext) -> Option<Visibility> { | |
1789 | Some(if *self == ty::Visibility::Public { hir::Public } else { hir::Inherited }) | |
1a4d82fc JJ |
1790 | } |
1791 | } | |
1792 | ||
85aaf69f | 1793 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
1794 | pub struct Struct { |
1795 | pub struct_type: doctree::StructType, | |
1796 | pub generics: Generics, | |
1797 | pub fields: Vec<Item>, | |
1798 | pub fields_stripped: bool, | |
1799 | } | |
1800 | ||
1801 | impl Clean<Item> for doctree::Struct { | |
1802 | fn clean(&self, cx: &DocContext) -> Item { | |
1803 | Item { | |
1804 | name: Some(self.name.clean(cx)), | |
1805 | attrs: self.attrs.clean(cx), | |
1806 | source: self.whence.clean(cx), | |
b039eaaf | 1807 | def_id: cx.map.local_def_id(self.id), |
1a4d82fc JJ |
1808 | visibility: self.vis.clean(cx), |
1809 | stability: self.stab.clean(cx), | |
9cc50fc6 | 1810 | deprecation: self.depr.clean(cx), |
1a4d82fc JJ |
1811 | inner: StructItem(Struct { |
1812 | struct_type: self.struct_type, | |
1813 | generics: self.generics.clean(cx), | |
1814 | fields: self.fields.clean(cx), | |
1815 | fields_stripped: false, | |
1816 | }), | |
1817 | } | |
1818 | } | |
1819 | } | |
1820 | ||
1821 | /// This is a more limited form of the standard Struct, different in that | |
1822 | /// it lacks the things most items have (name, id, parameterization). Found | |
1823 | /// only as a variant in an enum. | |
85aaf69f | 1824 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
1825 | pub struct VariantStruct { |
1826 | pub struct_type: doctree::StructType, | |
1827 | pub fields: Vec<Item>, | |
1828 | pub fields_stripped: bool, | |
1829 | } | |
1830 | ||
54a0048b | 1831 | impl Clean<VariantStruct> for ::rustc::hir::VariantData { |
1a4d82fc JJ |
1832 | fn clean(&self, cx: &DocContext) -> VariantStruct { |
1833 | VariantStruct { | |
1834 | struct_type: doctree::struct_type_from_def(self), | |
b039eaaf | 1835 | fields: self.fields().iter().map(|x| x.clean(cx)).collect(), |
1a4d82fc JJ |
1836 | fields_stripped: false, |
1837 | } | |
1838 | } | |
1839 | } | |
1840 | ||
85aaf69f | 1841 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
1842 | pub struct Enum { |
1843 | pub variants: Vec<Item>, | |
1844 | pub generics: Generics, | |
1845 | pub variants_stripped: bool, | |
1846 | } | |
1847 | ||
1848 | impl Clean<Item> for doctree::Enum { | |
1849 | fn clean(&self, cx: &DocContext) -> Item { | |
1850 | Item { | |
1851 | name: Some(self.name.clean(cx)), | |
1852 | attrs: self.attrs.clean(cx), | |
1853 | source: self.whence.clean(cx), | |
b039eaaf | 1854 | def_id: cx.map.local_def_id(self.id), |
1a4d82fc JJ |
1855 | visibility: self.vis.clean(cx), |
1856 | stability: self.stab.clean(cx), | |
9cc50fc6 | 1857 | deprecation: self.depr.clean(cx), |
1a4d82fc JJ |
1858 | inner: EnumItem(Enum { |
1859 | variants: self.variants.clean(cx), | |
1860 | generics: self.generics.clean(cx), | |
1861 | variants_stripped: false, | |
1862 | }), | |
1863 | } | |
1864 | } | |
1865 | } | |
1866 | ||
85aaf69f | 1867 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
1868 | pub struct Variant { |
1869 | pub kind: VariantKind, | |
1870 | } | |
1871 | ||
1872 | impl Clean<Item> for doctree::Variant { | |
1873 | fn clean(&self, cx: &DocContext) -> Item { | |
1874 | Item { | |
1875 | name: Some(self.name.clean(cx)), | |
1876 | attrs: self.attrs.clean(cx), | |
1877 | source: self.whence.clean(cx), | |
b039eaaf | 1878 | visibility: None, |
1a4d82fc | 1879 | stability: self.stab.clean(cx), |
9cc50fc6 | 1880 | deprecation: self.depr.clean(cx), |
b039eaaf | 1881 | def_id: cx.map.local_def_id(self.def.id()), |
1a4d82fc | 1882 | inner: VariantItem(Variant { |
b039eaaf | 1883 | kind: struct_def_to_variant_kind(&self.def, cx), |
1a4d82fc JJ |
1884 | }), |
1885 | } | |
1886 | } | |
1887 | } | |
1888 | ||
e9174d1e | 1889 | impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> { |
1a4d82fc | 1890 | fn clean(&self, cx: &DocContext) -> Item { |
e9174d1e SL |
1891 | let kind = match self.kind() { |
1892 | ty::VariantKind::Unit => CLikeVariant, | |
1893 | ty::VariantKind::Tuple => { | |
1894 | TupleVariant( | |
1895 | self.fields.iter().map(|f| f.unsubst_ty().clean(cx)).collect() | |
1896 | ) | |
1a4d82fc | 1897 | } |
b039eaaf | 1898 | ty::VariantKind::Struct => { |
1a4d82fc JJ |
1899 | StructVariant(VariantStruct { |
1900 | struct_type: doctree::Plain, | |
1901 | fields_stripped: false, | |
e9174d1e | 1902 | fields: self.fields.iter().map(|field| { |
1a4d82fc JJ |
1903 | Item { |
1904 | source: Span::empty(), | |
e9174d1e | 1905 | name: Some(field.name.clean(cx)), |
54a0048b SL |
1906 | attrs: cx.tcx().get_attrs(field.did).clean(cx), |
1907 | visibility: field.vis.clean(cx), | |
1908 | def_id: field.did, | |
1909 | stability: get_stability(cx, field.did), | |
1910 | deprecation: get_deprecation(cx, field.did), | |
1911 | inner: StructFieldItem(field.unsubst_ty().clean(cx)) | |
1a4d82fc JJ |
1912 | } |
1913 | }).collect() | |
1914 | }) | |
1915 | } | |
1916 | }; | |
1917 | Item { | |
1918 | name: Some(self.name.clean(cx)), | |
e9174d1e | 1919 | attrs: inline::load_attrs(cx, cx.tcx(), self.did), |
1a4d82fc | 1920 | source: Span::empty(), |
54a0048b | 1921 | visibility: Some(hir::Inherited), |
e9174d1e | 1922 | def_id: self.did, |
1a4d82fc | 1923 | inner: VariantItem(Variant { kind: kind }), |
e9174d1e | 1924 | stability: get_stability(cx, self.did), |
9cc50fc6 | 1925 | deprecation: get_deprecation(cx, self.did), |
1a4d82fc JJ |
1926 | } |
1927 | } | |
1928 | } | |
1929 | ||
85aaf69f | 1930 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
1931 | pub enum VariantKind { |
1932 | CLikeVariant, | |
1933 | TupleVariant(Vec<Type>), | |
1934 | StructVariant(VariantStruct), | |
1935 | } | |
1936 | ||
b039eaaf SL |
1937 | fn struct_def_to_variant_kind(struct_def: &hir::VariantData, cx: &DocContext) -> VariantKind { |
1938 | if struct_def.is_struct() { | |
1939 | StructVariant(struct_def.clean(cx)) | |
1940 | } else if struct_def.is_unit() { | |
1941 | CLikeVariant | |
1942 | } else { | |
54a0048b | 1943 | TupleVariant(struct_def.fields().iter().map(|x| x.ty.clean(cx)).collect()) |
1a4d82fc JJ |
1944 | } |
1945 | } | |
1946 | ||
85aaf69f | 1947 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
1948 | pub struct Span { |
1949 | pub filename: String, | |
c34b1796 AL |
1950 | pub loline: usize, |
1951 | pub locol: usize, | |
1952 | pub hiline: usize, | |
1953 | pub hicol: usize, | |
1a4d82fc JJ |
1954 | } |
1955 | ||
1956 | impl Span { | |
1957 | fn empty() -> Span { | |
1958 | Span { | |
1959 | filename: "".to_string(), | |
1960 | loline: 0, locol: 0, | |
1961 | hiline: 0, hicol: 0, | |
1962 | } | |
1963 | } | |
1964 | } | |
1965 | ||
1966 | impl Clean<Span> for syntax::codemap::Span { | |
1967 | fn clean(&self, cx: &DocContext) -> Span { | |
c1a9b12d SL |
1968 | if *self == DUMMY_SP { |
1969 | return Span::empty(); | |
1970 | } | |
1971 | ||
1a4d82fc JJ |
1972 | let cm = cx.sess().codemap(); |
1973 | let filename = cm.span_to_filename(*self); | |
1974 | let lo = cm.lookup_char_pos(self.lo); | |
1975 | let hi = cm.lookup_char_pos(self.hi); | |
1976 | Span { | |
1977 | filename: filename.to_string(), | |
1978 | loline: lo.line, | |
85aaf69f | 1979 | locol: lo.col.to_usize(), |
1a4d82fc | 1980 | hiline: hi.line, |
85aaf69f | 1981 | hicol: hi.col.to_usize(), |
1a4d82fc JJ |
1982 | } |
1983 | } | |
1984 | } | |
1985 | ||
85aaf69f | 1986 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
1987 | pub struct Path { |
1988 | pub global: bool, | |
1989 | pub segments: Vec<PathSegment>, | |
1990 | } | |
1991 | ||
9346a6ac AL |
1992 | impl Path { |
1993 | pub fn singleton(name: String) -> Path { | |
1994 | Path { | |
1995 | global: false, | |
1996 | segments: vec![PathSegment { | |
1997 | name: name, | |
1998 | params: PathParameters::AngleBracketed { | |
1999 | lifetimes: Vec::new(), | |
2000 | types: Vec::new(), | |
2001 | bindings: Vec::new() | |
2002 | } | |
2003 | }] | |
2004 | } | |
2005 | } | |
2006 | } | |
2007 | ||
e9174d1e | 2008 | impl Clean<Path> for hir::Path { |
1a4d82fc JJ |
2009 | fn clean(&self, cx: &DocContext) -> Path { |
2010 | Path { | |
2011 | global: self.global, | |
2012 | segments: self.segments.clean(cx), | |
2013 | } | |
2014 | } | |
2015 | } | |
2016 | ||
85aaf69f | 2017 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
2018 | pub enum PathParameters { |
2019 | AngleBracketed { | |
2020 | lifetimes: Vec<Lifetime>, | |
2021 | types: Vec<Type>, | |
2022 | bindings: Vec<TypeBinding> | |
2023 | }, | |
2024 | Parenthesized { | |
2025 | inputs: Vec<Type>, | |
2026 | output: Option<Type> | |
2027 | } | |
2028 | } | |
2029 | ||
e9174d1e | 2030 | impl Clean<PathParameters> for hir::PathParameters { |
1a4d82fc JJ |
2031 | fn clean(&self, cx: &DocContext) -> PathParameters { |
2032 | match *self { | |
e9174d1e | 2033 | hir::AngleBracketedParameters(ref data) => { |
1a4d82fc JJ |
2034 | PathParameters::AngleBracketed { |
2035 | lifetimes: data.lifetimes.clean(cx), | |
2036 | types: data.types.clean(cx), | |
2037 | bindings: data.bindings.clean(cx) | |
2038 | } | |
2039 | } | |
2040 | ||
e9174d1e | 2041 | hir::ParenthesizedParameters(ref data) => { |
1a4d82fc JJ |
2042 | PathParameters::Parenthesized { |
2043 | inputs: data.inputs.clean(cx), | |
2044 | output: data.output.clean(cx) | |
2045 | } | |
2046 | } | |
2047 | } | |
2048 | } | |
2049 | } | |
2050 | ||
85aaf69f | 2051 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
2052 | pub struct PathSegment { |
2053 | pub name: String, | |
2054 | pub params: PathParameters | |
2055 | } | |
2056 | ||
e9174d1e | 2057 | impl Clean<PathSegment> for hir::PathSegment { |
1a4d82fc JJ |
2058 | fn clean(&self, cx: &DocContext) -> PathSegment { |
2059 | PathSegment { | |
b039eaaf | 2060 | name: self.identifier.name.clean(cx), |
1a4d82fc JJ |
2061 | params: self.parameters.clean(cx) |
2062 | } | |
2063 | } | |
2064 | } | |
2065 | ||
e9174d1e | 2066 | fn path_to_string(p: &hir::Path) -> String { |
1a4d82fc JJ |
2067 | let mut s = String::new(); |
2068 | let mut first = true; | |
c1a9b12d | 2069 | for i in p.segments.iter().map(|x| x.identifier.name.as_str()) { |
1a4d82fc JJ |
2070 | if !first || p.global { |
2071 | s.push_str("::"); | |
2072 | } else { | |
2073 | first = false; | |
2074 | } | |
85aaf69f | 2075 | s.push_str(&i); |
1a4d82fc JJ |
2076 | } |
2077 | s | |
2078 | } | |
2079 | ||
1a4d82fc JJ |
2080 | impl Clean<String> for ast::Name { |
2081 | fn clean(&self, _: &DocContext) -> String { | |
c1a9b12d | 2082 | self.to_string() |
1a4d82fc JJ |
2083 | } |
2084 | } | |
2085 | ||
85aaf69f | 2086 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
2087 | pub struct Typedef { |
2088 | pub type_: Type, | |
2089 | pub generics: Generics, | |
2090 | } | |
2091 | ||
2092 | impl Clean<Item> for doctree::Typedef { | |
2093 | fn clean(&self, cx: &DocContext) -> Item { | |
2094 | Item { | |
2095 | name: Some(self.name.clean(cx)), | |
2096 | attrs: self.attrs.clean(cx), | |
2097 | source: self.whence.clean(cx), | |
b039eaaf | 2098 | def_id: cx.map.local_def_id(self.id.clone()), |
1a4d82fc JJ |
2099 | visibility: self.vis.clean(cx), |
2100 | stability: self.stab.clean(cx), | |
9cc50fc6 | 2101 | deprecation: self.depr.clean(cx), |
1a4d82fc JJ |
2102 | inner: TypedefItem(Typedef { |
2103 | type_: self.ty.clean(cx), | |
2104 | generics: self.gen.clean(cx), | |
62682a34 | 2105 | }, false), |
1a4d82fc JJ |
2106 | } |
2107 | } | |
2108 | } | |
2109 | ||
85aaf69f | 2110 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc | 2111 | pub struct BareFunctionDecl { |
e9174d1e | 2112 | pub unsafety: hir::Unsafety, |
1a4d82fc JJ |
2113 | pub generics: Generics, |
2114 | pub decl: FnDecl, | |
2115 | pub abi: String, | |
2116 | } | |
2117 | ||
e9174d1e | 2118 | impl Clean<BareFunctionDecl> for hir::BareFnTy { |
1a4d82fc JJ |
2119 | fn clean(&self, cx: &DocContext) -> BareFunctionDecl { |
2120 | BareFunctionDecl { | |
2121 | unsafety: self.unsafety, | |
2122 | generics: Generics { | |
2123 | lifetimes: self.lifetimes.clean(cx), | |
2124 | type_params: Vec::new(), | |
2125 | where_predicates: Vec::new() | |
2126 | }, | |
2127 | decl: self.decl.clean(cx), | |
2128 | abi: self.abi.to_string(), | |
2129 | } | |
2130 | } | |
2131 | } | |
2132 | ||
85aaf69f | 2133 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
2134 | pub struct Static { |
2135 | pub type_: Type, | |
2136 | pub mutability: Mutability, | |
2137 | /// It's useful to have the value of a static documented, but I have no | |
2138 | /// desire to represent expressions (that'd basically be all of the AST, | |
2139 | /// which is huge!). So, have a string. | |
2140 | pub expr: String, | |
2141 | } | |
2142 | ||
2143 | impl Clean<Item> for doctree::Static { | |
2144 | fn clean(&self, cx: &DocContext) -> Item { | |
2145 | debug!("cleaning static {}: {:?}", self.name.clean(cx), self); | |
2146 | Item { | |
2147 | name: Some(self.name.clean(cx)), | |
2148 | attrs: self.attrs.clean(cx), | |
2149 | source: self.whence.clean(cx), | |
b039eaaf | 2150 | def_id: cx.map.local_def_id(self.id), |
1a4d82fc JJ |
2151 | visibility: self.vis.clean(cx), |
2152 | stability: self.stab.clean(cx), | |
9cc50fc6 | 2153 | deprecation: self.depr.clean(cx), |
1a4d82fc JJ |
2154 | inner: StaticItem(Static { |
2155 | type_: self.type_.clean(cx), | |
2156 | mutability: self.mutability.clean(cx), | |
2157 | expr: self.expr.span.to_src(cx), | |
2158 | }), | |
2159 | } | |
2160 | } | |
2161 | } | |
2162 | ||
85aaf69f | 2163 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
2164 | pub struct Constant { |
2165 | pub type_: Type, | |
2166 | pub expr: String, | |
2167 | } | |
2168 | ||
2169 | impl Clean<Item> for doctree::Constant { | |
2170 | fn clean(&self, cx: &DocContext) -> Item { | |
2171 | Item { | |
2172 | name: Some(self.name.clean(cx)), | |
2173 | attrs: self.attrs.clean(cx), | |
2174 | source: self.whence.clean(cx), | |
b039eaaf | 2175 | def_id: cx.map.local_def_id(self.id), |
1a4d82fc JJ |
2176 | visibility: self.vis.clean(cx), |
2177 | stability: self.stab.clean(cx), | |
9cc50fc6 | 2178 | deprecation: self.depr.clean(cx), |
1a4d82fc JJ |
2179 | inner: ConstantItem(Constant { |
2180 | type_: self.type_.clean(cx), | |
2181 | expr: self.expr.span.to_src(cx), | |
2182 | }), | |
2183 | } | |
2184 | } | |
2185 | } | |
2186 | ||
85aaf69f | 2187 | #[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Copy)] |
1a4d82fc JJ |
2188 | pub enum Mutability { |
2189 | Mutable, | |
2190 | Immutable, | |
2191 | } | |
2192 | ||
e9174d1e | 2193 | impl Clean<Mutability> for hir::Mutability { |
1a4d82fc JJ |
2194 | fn clean(&self, _: &DocContext) -> Mutability { |
2195 | match self { | |
e9174d1e SL |
2196 | &hir::MutMutable => Mutable, |
2197 | &hir::MutImmutable => Immutable, | |
1a4d82fc JJ |
2198 | } |
2199 | } | |
2200 | } | |
2201 | ||
85aaf69f SL |
2202 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Copy, Debug)] |
2203 | pub enum ImplPolarity { | |
2204 | Positive, | |
2205 | Negative, | |
2206 | } | |
2207 | ||
e9174d1e | 2208 | impl Clean<ImplPolarity> for hir::ImplPolarity { |
85aaf69f SL |
2209 | fn clean(&self, _: &DocContext) -> ImplPolarity { |
2210 | match self { | |
e9174d1e SL |
2211 | &hir::ImplPolarity::Positive => ImplPolarity::Positive, |
2212 | &hir::ImplPolarity::Negative => ImplPolarity::Negative, | |
85aaf69f SL |
2213 | } |
2214 | } | |
2215 | } | |
2216 | ||
2217 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] | |
1a4d82fc | 2218 | pub struct Impl { |
e9174d1e | 2219 | pub unsafety: hir::Unsafety, |
1a4d82fc | 2220 | pub generics: Generics, |
54a0048b | 2221 | pub provided_trait_methods: HashSet<String>, |
1a4d82fc JJ |
2222 | pub trait_: Option<Type>, |
2223 | pub for_: Type, | |
2224 | pub items: Vec<Item>, | |
2225 | pub derived: bool, | |
85aaf69f | 2226 | pub polarity: Option<ImplPolarity>, |
1a4d82fc JJ |
2227 | } |
2228 | ||
2229 | fn detect_derived<M: AttrMetaMethods>(attrs: &[M]) -> bool { | |
2230 | attr::contains_name(attrs, "automatically_derived") | |
2231 | } | |
2232 | ||
d9579d0f AL |
2233 | impl Clean<Vec<Item>> for doctree::Impl { |
2234 | fn clean(&self, cx: &DocContext) -> Vec<Item> { | |
2235 | let mut ret = Vec::new(); | |
2236 | let trait_ = self.trait_.clean(cx); | |
2237 | let items = self.items.clean(cx); | |
2238 | ||
2239 | // If this impl block is an implementation of the Deref trait, then we | |
2240 | // need to try inlining the target's inherent impl blocks as well. | |
54a0048b SL |
2241 | if trait_.def_id() == cx.deref_trait_did.get() { |
2242 | build_deref_target_impls(cx, &items, &mut ret); | |
d9579d0f AL |
2243 | } |
2244 | ||
54a0048b SL |
2245 | let provided = trait_.def_id().and_then(|did| { |
2246 | cx.tcx_opt().map(|tcx| { | |
2247 | tcx.provided_trait_methods(did) | |
2248 | .into_iter() | |
2249 | .map(|meth| meth.name.to_string()) | |
2250 | .collect() | |
2251 | }) | |
2252 | }).unwrap_or(HashSet::new()); | |
2253 | ||
d9579d0f | 2254 | ret.push(Item { |
1a4d82fc JJ |
2255 | name: None, |
2256 | attrs: self.attrs.clean(cx), | |
2257 | source: self.whence.clean(cx), | |
b039eaaf | 2258 | def_id: cx.map.local_def_id(self.id), |
1a4d82fc JJ |
2259 | visibility: self.vis.clean(cx), |
2260 | stability: self.stab.clean(cx), | |
9cc50fc6 | 2261 | deprecation: self.depr.clean(cx), |
1a4d82fc | 2262 | inner: ImplItem(Impl { |
c34b1796 | 2263 | unsafety: self.unsafety, |
1a4d82fc | 2264 | generics: self.generics.clean(cx), |
54a0048b | 2265 | provided_trait_methods: provided, |
d9579d0f | 2266 | trait_: trait_, |
1a4d82fc | 2267 | for_: self.for_.clean(cx), |
d9579d0f | 2268 | items: items, |
85aaf69f SL |
2269 | derived: detect_derived(&self.attrs), |
2270 | polarity: Some(self.polarity.clean(cx)), | |
1a4d82fc | 2271 | }), |
d9579d0f | 2272 | }); |
54a0048b | 2273 | ret |
d9579d0f AL |
2274 | } |
2275 | } | |
2276 | ||
2277 | fn build_deref_target_impls(cx: &DocContext, | |
2278 | items: &[Item], | |
2279 | ret: &mut Vec<Item>) { | |
2280 | let tcx = match cx.tcx_opt() { | |
2281 | Some(t) => t, | |
2282 | None => return, | |
2283 | }; | |
2284 | ||
2285 | for item in items { | |
2286 | let target = match item.inner { | |
62682a34 | 2287 | TypedefItem(ref t, true) => &t.type_, |
d9579d0f AL |
2288 | _ => continue, |
2289 | }; | |
2290 | let primitive = match *target { | |
e9174d1e | 2291 | ResolvedPath { did, .. } if did.is_local() => continue, |
d9579d0f AL |
2292 | ResolvedPath { did, .. } => { |
2293 | ret.extend(inline::build_impls(cx, tcx, did)); | |
2294 | continue | |
2295 | } | |
2296 | _ => match target.primitive_type() { | |
2297 | Some(prim) => prim, | |
2298 | None => continue, | |
2299 | } | |
2300 | }; | |
2301 | let did = match primitive { | |
2302 | Isize => tcx.lang_items.isize_impl(), | |
2303 | I8 => tcx.lang_items.i8_impl(), | |
2304 | I16 => tcx.lang_items.i16_impl(), | |
2305 | I32 => tcx.lang_items.i32_impl(), | |
2306 | I64 => tcx.lang_items.i64_impl(), | |
2307 | Usize => tcx.lang_items.usize_impl(), | |
2308 | U8 => tcx.lang_items.u8_impl(), | |
2309 | U16 => tcx.lang_items.u16_impl(), | |
2310 | U32 => tcx.lang_items.u32_impl(), | |
2311 | U64 => tcx.lang_items.u64_impl(), | |
2312 | F32 => tcx.lang_items.f32_impl(), | |
2313 | F64 => tcx.lang_items.f64_impl(), | |
2314 | Char => tcx.lang_items.char_impl(), | |
2315 | Bool => None, | |
2316 | Str => tcx.lang_items.str_impl(), | |
2317 | Slice => tcx.lang_items.slice_impl(), | |
2318 | Array => tcx.lang_items.slice_impl(), | |
2319 | PrimitiveTuple => None, | |
2320 | PrimitiveRawPointer => tcx.lang_items.const_ptr_impl(), | |
2321 | }; | |
2322 | if let Some(did) = did { | |
e9174d1e | 2323 | if !did.is_local() { |
d9579d0f AL |
2324 | inline::build_impl(cx, tcx, did, ret); |
2325 | } | |
1a4d82fc JJ |
2326 | } |
2327 | } | |
2328 | } | |
2329 | ||
c34b1796 AL |
2330 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
2331 | pub struct DefaultImpl { | |
e9174d1e | 2332 | pub unsafety: hir::Unsafety, |
c34b1796 AL |
2333 | pub trait_: Type, |
2334 | } | |
2335 | ||
2336 | impl Clean<Item> for doctree::DefaultImpl { | |
2337 | fn clean(&self, cx: &DocContext) -> Item { | |
2338 | Item { | |
2339 | name: None, | |
2340 | attrs: self.attrs.clean(cx), | |
2341 | source: self.whence.clean(cx), | |
b039eaaf | 2342 | def_id: cx.map.local_def_id(self.id), |
e9174d1e | 2343 | visibility: Some(hir::Public), |
c34b1796 | 2344 | stability: None, |
9cc50fc6 | 2345 | deprecation: None, |
c34b1796 AL |
2346 | inner: DefaultImplItem(DefaultImpl { |
2347 | unsafety: self.unsafety, | |
2348 | trait_: self.trait_.clean(cx), | |
2349 | }), | |
2350 | } | |
2351 | } | |
2352 | } | |
2353 | ||
85aaf69f SL |
2354 | impl Clean<Item> for doctree::ExternCrate { |
2355 | fn clean(&self, cx: &DocContext) -> Item { | |
2356 | Item { | |
2357 | name: None, | |
2358 | attrs: self.attrs.clean(cx), | |
2359 | source: self.whence.clean(cx), | |
b039eaaf | 2360 | def_id: cx.map.local_def_id(0), |
85aaf69f SL |
2361 | visibility: self.vis.clean(cx), |
2362 | stability: None, | |
9cc50fc6 | 2363 | deprecation: None, |
85aaf69f SL |
2364 | inner: ExternCrateItem(self.name.clean(cx), self.path.clone()) |
2365 | } | |
2366 | } | |
1a4d82fc JJ |
2367 | } |
2368 | ||
85aaf69f | 2369 | impl Clean<Vec<Item>> for doctree::Import { |
1a4d82fc JJ |
2370 | fn clean(&self, cx: &DocContext) -> Vec<Item> { |
2371 | // We consider inlining the documentation of `pub use` statements, but we | |
2372 | // forcefully don't inline if this is not public or if the | |
2373 | // #[doc(no_inline)] attribute is present. | |
e9174d1e | 2374 | let denied = self.vis != hir::Public || self.attrs.iter().any(|a| { |
c34b1796 | 2375 | &a.name()[..] == "doc" && match a.meta_item_list() { |
1a4d82fc JJ |
2376 | Some(l) => attr::contains_name(l, "no_inline"), |
2377 | None => false, | |
2378 | } | |
2379 | }); | |
85aaf69f | 2380 | let (mut ret, inner) = match self.node { |
e9174d1e | 2381 | hir::ViewPathGlob(ref p) => { |
85aaf69f | 2382 | (vec![], GlobImport(resolve_use_source(cx, p.clean(cx), self.id))) |
1a4d82fc | 2383 | } |
e9174d1e | 2384 | hir::ViewPathList(ref p, ref list) => { |
85aaf69f SL |
2385 | // Attempt to inline all reexported items, but be sure |
2386 | // to keep any non-inlineable reexports so they can be | |
2387 | // listed in the documentation. | |
2388 | let mut ret = vec![]; | |
2389 | let remaining = if !denied { | |
2390 | let mut remaining = vec![]; | |
2391 | for path in list { | |
e9174d1e | 2392 | match inline::try_inline(cx, path.node.id(), path.node.rename()) { |
85aaf69f | 2393 | Some(items) => { |
62682a34 | 2394 | ret.extend(items); |
85aaf69f SL |
2395 | } |
2396 | None => { | |
2397 | remaining.push(path.clean(cx)); | |
1a4d82fc | 2398 | } |
1a4d82fc JJ |
2399 | } |
2400 | } | |
85aaf69f SL |
2401 | remaining |
2402 | } else { | |
2403 | list.clean(cx) | |
1a4d82fc | 2404 | }; |
85aaf69f SL |
2405 | if remaining.is_empty() { |
2406 | return ret; | |
2407 | } | |
2408 | (ret, ImportList(resolve_use_source(cx, p.clean(cx), self.id), | |
2409 | remaining)) | |
1a4d82fc | 2410 | } |
b039eaaf | 2411 | hir::ViewPathSimple(name, ref p) => { |
85aaf69f | 2412 | if !denied { |
54a0048b SL |
2413 | if let Some(items) = inline::try_inline(cx, self.id, Some(name)) { |
2414 | return items; | |
85aaf69f SL |
2415 | } |
2416 | } | |
b039eaaf | 2417 | (vec![], SimpleImport(name.clean(cx), |
85aaf69f | 2418 | resolve_use_source(cx, p.clean(cx), self.id))) |
1a4d82fc | 2419 | } |
85aaf69f SL |
2420 | }; |
2421 | ret.push(Item { | |
2422 | name: None, | |
2423 | attrs: self.attrs.clean(cx), | |
2424 | source: self.whence.clean(cx), | |
b039eaaf | 2425 | def_id: cx.map.local_def_id(0), |
85aaf69f SL |
2426 | visibility: self.vis.clean(cx), |
2427 | stability: None, | |
9cc50fc6 | 2428 | deprecation: None, |
85aaf69f SL |
2429 | inner: ImportItem(inner) |
2430 | }); | |
2431 | ret | |
1a4d82fc JJ |
2432 | } |
2433 | } | |
2434 | ||
85aaf69f SL |
2435 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
2436 | pub enum Import { | |
1a4d82fc JJ |
2437 | // use source as str; |
2438 | SimpleImport(String, ImportSource), | |
2439 | // use source::*; | |
2440 | GlobImport(ImportSource), | |
2441 | // use source::{a, b, c}; | |
2442 | ImportList(ImportSource, Vec<ViewListIdent>), | |
2443 | } | |
2444 | ||
85aaf69f | 2445 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
2446 | pub struct ImportSource { |
2447 | pub path: Path, | |
e9174d1e | 2448 | pub did: Option<DefId>, |
1a4d82fc JJ |
2449 | } |
2450 | ||
85aaf69f | 2451 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
2452 | pub struct ViewListIdent { |
2453 | pub name: String, | |
e9174d1e SL |
2454 | pub rename: Option<String>, |
2455 | pub source: Option<DefId>, | |
1a4d82fc JJ |
2456 | } |
2457 | ||
e9174d1e | 2458 | impl Clean<ViewListIdent> for hir::PathListItem { |
1a4d82fc JJ |
2459 | fn clean(&self, cx: &DocContext) -> ViewListIdent { |
2460 | match self.node { | |
e9174d1e | 2461 | hir::PathListIdent { id, name, rename } => ViewListIdent { |
1a4d82fc | 2462 | name: name.clean(cx), |
e9174d1e | 2463 | rename: rename.map(|r| r.clean(cx)), |
1a4d82fc JJ |
2464 | source: resolve_def(cx, id) |
2465 | }, | |
e9174d1e | 2466 | hir::PathListMod { id, rename } => ViewListIdent { |
85aaf69f | 2467 | name: "self".to_string(), |
e9174d1e | 2468 | rename: rename.map(|r| r.clean(cx)), |
1a4d82fc JJ |
2469 | source: resolve_def(cx, id) |
2470 | } | |
2471 | } | |
2472 | } | |
2473 | } | |
2474 | ||
e9174d1e | 2475 | impl Clean<Vec<Item>> for hir::ForeignMod { |
1a4d82fc | 2476 | fn clean(&self, cx: &DocContext) -> Vec<Item> { |
9346a6ac AL |
2477 | let mut items = self.items.clean(cx); |
2478 | for item in &mut items { | |
54a0048b SL |
2479 | if let ForeignFunctionItem(ref mut f) = item.inner { |
2480 | f.abi = self.abi; | |
9346a6ac AL |
2481 | } |
2482 | } | |
2483 | items | |
1a4d82fc JJ |
2484 | } |
2485 | } | |
2486 | ||
e9174d1e | 2487 | impl Clean<Item> for hir::ForeignItem { |
1a4d82fc JJ |
2488 | fn clean(&self, cx: &DocContext) -> Item { |
2489 | let inner = match self.node { | |
e9174d1e | 2490 | hir::ForeignItemFn(ref decl, ref generics) => { |
1a4d82fc JJ |
2491 | ForeignFunctionItem(Function { |
2492 | decl: decl.clean(cx), | |
2493 | generics: generics.clean(cx), | |
e9174d1e | 2494 | unsafety: hir::Unsafety::Unsafe, |
7453a54e | 2495 | abi: Abi::Rust, |
e9174d1e | 2496 | constness: hir::Constness::NotConst, |
1a4d82fc JJ |
2497 | }) |
2498 | } | |
e9174d1e | 2499 | hir::ForeignItemStatic(ref ty, mutbl) => { |
1a4d82fc JJ |
2500 | ForeignStaticItem(Static { |
2501 | type_: ty.clean(cx), | |
2502 | mutability: if mutbl {Mutable} else {Immutable}, | |
2503 | expr: "".to_string(), | |
2504 | }) | |
2505 | } | |
2506 | }; | |
2507 | Item { | |
b039eaaf | 2508 | name: Some(self.name.clean(cx)), |
1a4d82fc JJ |
2509 | attrs: self.attrs.clean(cx), |
2510 | source: self.span.clean(cx), | |
b039eaaf | 2511 | def_id: cx.map.local_def_id(self.id), |
1a4d82fc | 2512 | visibility: self.vis.clean(cx), |
b039eaaf | 2513 | stability: get_stability(cx, cx.map.local_def_id(self.id)), |
9cc50fc6 | 2514 | deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)), |
1a4d82fc JJ |
2515 | inner: inner, |
2516 | } | |
2517 | } | |
2518 | } | |
2519 | ||
2520 | // Utilities | |
2521 | ||
2522 | trait ToSource { | |
2523 | fn to_src(&self, cx: &DocContext) -> String; | |
2524 | } | |
2525 | ||
2526 | impl ToSource for syntax::codemap::Span { | |
2527 | fn to_src(&self, cx: &DocContext) -> String { | |
2528 | debug!("converting span {:?} to snippet", self.clean(cx)); | |
2529 | let sn = match cx.sess().codemap().span_to_snippet(*self) { | |
85aaf69f SL |
2530 | Ok(x) => x.to_string(), |
2531 | Err(_) => "".to_string() | |
1a4d82fc JJ |
2532 | }; |
2533 | debug!("got snippet {}", sn); | |
2534 | sn | |
2535 | } | |
2536 | } | |
2537 | ||
b039eaaf | 2538 | fn lit_to_string(lit: &ast::Lit) -> String { |
1a4d82fc | 2539 | match lit.node { |
7453a54e SL |
2540 | ast::LitKind::Str(ref st, _) => st.to_string(), |
2541 | ast::LitKind::ByteStr(ref data) => format!("{:?}", data), | |
2542 | ast::LitKind::Byte(b) => { | |
62682a34 | 2543 | let mut res = String::from("b'"); |
1a4d82fc JJ |
2544 | for c in (b as char).escape_default() { |
2545 | res.push(c); | |
2546 | } | |
2547 | res.push('\''); | |
2548 | res | |
2549 | }, | |
7453a54e SL |
2550 | ast::LitKind::Char(c) => format!("'{}'", c), |
2551 | ast::LitKind::Int(i, _t) => i.to_string(), | |
2552 | ast::LitKind::Float(ref f, _t) => f.to_string(), | |
2553 | ast::LitKind::FloatUnsuffixed(ref f) => f.to_string(), | |
2554 | ast::LitKind::Bool(b) => b.to_string(), | |
1a4d82fc JJ |
2555 | } |
2556 | } | |
2557 | ||
e9174d1e | 2558 | fn name_from_pat(p: &hir::Pat) -> String { |
54a0048b | 2559 | use rustc::hir::*; |
1a4d82fc JJ |
2560 | debug!("Trying to get a name from pattern: {:?}", p); |
2561 | ||
2562 | match p.node { | |
7453a54e SL |
2563 | PatKind::Wild => "_".to_string(), |
2564 | PatKind::Ident(_, ref p, _) => p.node.to_string(), | |
2565 | PatKind::TupleStruct(ref p, _) | PatKind::Path(ref p) => path_to_string(p), | |
2566 | PatKind::QPath(..) => panic!("tried to get argument name from PatKind::QPath, \ | |
d9579d0f | 2567 | which is not allowed in function arguments"), |
7453a54e | 2568 | PatKind::Struct(ref name, ref fields, etc) => { |
1a4d82fc JJ |
2569 | format!("{} {{ {}{} }}", path_to_string(name), |
2570 | fields.iter().map(|&Spanned { node: ref fp, .. }| | |
b039eaaf | 2571 | format!("{}: {}", fp.name, name_from_pat(&*fp.pat))) |
c1a9b12d | 2572 | .collect::<Vec<String>>().join(", "), |
1a4d82fc JJ |
2573 | if etc { ", ..." } else { "" } |
2574 | ) | |
2575 | }, | |
7453a54e | 2576 | PatKind::Tup(ref elts) => format!("({})", elts.iter().map(|p| name_from_pat(&**p)) |
c1a9b12d | 2577 | .collect::<Vec<String>>().join(", ")), |
7453a54e SL |
2578 | PatKind::Box(ref p) => name_from_pat(&**p), |
2579 | PatKind::Ref(ref p, _) => name_from_pat(&**p), | |
2580 | PatKind::Lit(..) => { | |
2581 | warn!("tried to get argument name from PatKind::Lit, \ | |
1a4d82fc JJ |
2582 | which is silly in function arguments"); |
2583 | "()".to_string() | |
2584 | }, | |
7453a54e | 2585 | PatKind::Range(..) => panic!("tried to get argument name from PatKind::Range, \ |
1a4d82fc | 2586 | which is not allowed in function arguments"), |
7453a54e | 2587 | PatKind::Vec(ref begin, ref mid, ref end) => { |
1a4d82fc JJ |
2588 | let begin = begin.iter().map(|p| name_from_pat(&**p)); |
2589 | let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter(); | |
2590 | let end = end.iter().map(|p| name_from_pat(&**p)); | |
c1a9b12d | 2591 | format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", ")) |
1a4d82fc | 2592 | }, |
1a4d82fc JJ |
2593 | } |
2594 | } | |
2595 | ||
2596 | /// Given a Type, resolve it using the def_map | |
2597 | fn resolve_type(cx: &DocContext, | |
2598 | path: Path, | |
2599 | id: ast::NodeId) -> Type { | |
b039eaaf | 2600 | debug!("resolve_type({:?},{:?})", path, id); |
1a4d82fc JJ |
2601 | let tcx = match cx.tcx_opt() { |
2602 | Some(tcx) => tcx, | |
92a42be0 SL |
2603 | // If we're extracting tests, this return value's accuracy is not |
2604 | // important, all we want is a string representation to help people | |
2605 | // figure out what doctests are failing. | |
2606 | None => { | |
2607 | let did = DefId::local(DefIndex::from_u32(0)); | |
2608 | return ResolvedPath { | |
2609 | path: path, | |
2610 | typarams: None, | |
2611 | did: did, | |
2612 | is_generic: false | |
2613 | }; | |
2614 | } | |
1a4d82fc | 2615 | }; |
54a0048b | 2616 | let def = tcx.def_map.borrow().get(&id).expect("unresolved id not in defmap").full_def(); |
b039eaaf SL |
2617 | debug!("resolve_type: def={:?}", def); |
2618 | ||
62682a34 | 2619 | let is_generic = match def { |
7453a54e | 2620 | Def::PrimTy(p) => match p { |
e9174d1e SL |
2621 | hir::TyStr => return Primitive(Str), |
2622 | hir::TyBool => return Primitive(Bool), | |
2623 | hir::TyChar => return Primitive(Char), | |
7453a54e SL |
2624 | hir::TyInt(ast::IntTy::Is) => return Primitive(Isize), |
2625 | hir::TyInt(ast::IntTy::I8) => return Primitive(I8), | |
2626 | hir::TyInt(ast::IntTy::I16) => return Primitive(I16), | |
2627 | hir::TyInt(ast::IntTy::I32) => return Primitive(I32), | |
2628 | hir::TyInt(ast::IntTy::I64) => return Primitive(I64), | |
2629 | hir::TyUint(ast::UintTy::Us) => return Primitive(Usize), | |
2630 | hir::TyUint(ast::UintTy::U8) => return Primitive(U8), | |
2631 | hir::TyUint(ast::UintTy::U16) => return Primitive(U16), | |
2632 | hir::TyUint(ast::UintTy::U32) => return Primitive(U32), | |
2633 | hir::TyUint(ast::UintTy::U64) => return Primitive(U64), | |
2634 | hir::TyFloat(ast::FloatTy::F32) => return Primitive(F32), | |
2635 | hir::TyFloat(ast::FloatTy::F64) => return Primitive(F64), | |
1a4d82fc | 2636 | }, |
7453a54e | 2637 | Def::SelfTy(..) if path.segments.len() == 1 => { |
c1a9b12d | 2638 | return Generic(special_idents::type_self.name.to_string()); |
c34b1796 | 2639 | } |
7453a54e | 2640 | Def::SelfTy(..) | Def::TyParam(..) => true, |
62682a34 | 2641 | _ => false, |
1a4d82fc JJ |
2642 | }; |
2643 | let did = register_def(&*cx, def); | |
62682a34 | 2644 | ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic } |
1a4d82fc JJ |
2645 | } |
2646 | ||
7453a54e | 2647 | fn register_def(cx: &DocContext, def: Def) -> DefId { |
b039eaaf SL |
2648 | debug!("register_def({:?})", def); |
2649 | ||
1a4d82fc | 2650 | let (did, kind) = match def { |
7453a54e SL |
2651 | Def::Fn(i) => (i, TypeFunction), |
2652 | Def::TyAlias(i) => (i, TypeTypedef), | |
2653 | Def::Enum(i) => (i, TypeEnum), | |
2654 | Def::Trait(i) => (i, TypeTrait), | |
2655 | Def::Struct(i) => (i, TypeStruct), | |
2656 | Def::Mod(i) => (i, TypeModule), | |
2657 | Def::Static(i, _) => (i, TypeStatic), | |
2658 | Def::Variant(i, _) => (i, TypeEnum), | |
2659 | Def::SelfTy(Some(def_id), _) => (def_id, TypeTrait), | |
2660 | Def::SelfTy(_, Some((impl_id, _))) => return cx.map.local_def_id(impl_id), | |
1a4d82fc JJ |
2661 | _ => return def.def_id() |
2662 | }; | |
e9174d1e | 2663 | if did.is_local() { return did } |
1a4d82fc JJ |
2664 | let tcx = match cx.tcx_opt() { |
2665 | Some(tcx) => tcx, | |
2666 | None => return did | |
2667 | }; | |
2668 | inline::record_extern_fqn(cx, did, kind); | |
2669 | if let TypeTrait = kind { | |
2670 | let t = inline::build_external_trait(cx, tcx, did); | |
2671 | cx.external_traits.borrow_mut().as_mut().unwrap().insert(did, t); | |
2672 | } | |
54a0048b | 2673 | did |
1a4d82fc JJ |
2674 | } |
2675 | ||
2676 | fn resolve_use_source(cx: &DocContext, path: Path, id: ast::NodeId) -> ImportSource { | |
2677 | ImportSource { | |
2678 | path: path, | |
2679 | did: resolve_def(cx, id), | |
2680 | } | |
2681 | } | |
2682 | ||
e9174d1e | 2683 | fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option<DefId> { |
1a4d82fc | 2684 | cx.tcx_opt().and_then(|tcx| { |
c34b1796 | 2685 | tcx.def_map.borrow().get(&id).map(|d| register_def(cx, d.full_def())) |
1a4d82fc JJ |
2686 | }) |
2687 | } | |
2688 | ||
85aaf69f | 2689 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
2690 | pub struct Macro { |
2691 | pub source: String, | |
d9579d0f | 2692 | pub imported_from: Option<String>, |
1a4d82fc JJ |
2693 | } |
2694 | ||
2695 | impl Clean<Item> for doctree::Macro { | |
2696 | fn clean(&self, cx: &DocContext) -> Item { | |
92a42be0 | 2697 | let name = format!("{}!", self.name.clean(cx)); |
1a4d82fc | 2698 | Item { |
92a42be0 | 2699 | name: Some(name.clone()), |
1a4d82fc JJ |
2700 | attrs: self.attrs.clean(cx), |
2701 | source: self.whence.clean(cx), | |
e9174d1e | 2702 | visibility: hir::Public.clean(cx), |
1a4d82fc | 2703 | stability: self.stab.clean(cx), |
9cc50fc6 | 2704 | deprecation: self.depr.clean(cx), |
b039eaaf | 2705 | def_id: cx.map.local_def_id(self.id), |
1a4d82fc | 2706 | inner: MacroItem(Macro { |
92a42be0 SL |
2707 | source: format!("macro_rules! {} {{\n{}}}", |
2708 | name.trim_right_matches('!'), self.matchers.iter().map(|span| | |
2709 | format!(" {} => {{ ... }};\n", span.to_src(cx))).collect::<String>()), | |
d9579d0f | 2710 | imported_from: self.imported_from.clean(cx), |
1a4d82fc JJ |
2711 | }), |
2712 | } | |
2713 | } | |
2714 | } | |
2715 | ||
85aaf69f | 2716 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc | 2717 | pub struct Stability { |
b039eaaf | 2718 | pub level: stability::StabilityLevel, |
85aaf69f SL |
2719 | pub feature: String, |
2720 | pub since: String, | |
2721 | pub deprecated_since: String, | |
e9174d1e SL |
2722 | pub reason: String, |
2723 | pub issue: Option<u32> | |
1a4d82fc JJ |
2724 | } |
2725 | ||
9cc50fc6 SL |
2726 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
2727 | pub struct Deprecation { | |
2728 | pub since: String, | |
2729 | pub note: String, | |
2730 | } | |
2731 | ||
1a4d82fc JJ |
2732 | impl Clean<Stability> for attr::Stability { |
2733 | fn clean(&self, _: &DocContext) -> Stability { | |
2734 | Stability { | |
b039eaaf | 2735 | level: stability::StabilityLevel::from_attr_level(&self.level), |
85aaf69f | 2736 | feature: self.feature.to_string(), |
b039eaaf SL |
2737 | since: match self.level { |
2738 | attr::Stable {ref since} => since.to_string(), | |
2739 | _ => "".to_string(), | |
2740 | }, | |
9cc50fc6 SL |
2741 | deprecated_since: match self.rustc_depr { |
2742 | Some(attr::RustcDeprecation {ref since, ..}) => since.to_string(), | |
b039eaaf SL |
2743 | _=> "".to_string(), |
2744 | }, | |
2745 | reason: { | |
54a0048b SL |
2746 | match (&self.rustc_depr, &self.level) { |
2747 | (&Some(ref depr), _) => depr.reason.to_string(), | |
2748 | (&None, &attr::Unstable {reason: Some(ref reason), ..}) => reason.to_string(), | |
2749 | _ => "".to_string(), | |
b039eaaf SL |
2750 | } |
2751 | }, | |
2752 | issue: match self.level { | |
2753 | attr::Unstable {issue, ..} => Some(issue), | |
2754 | _ => None, | |
2755 | } | |
1a4d82fc JJ |
2756 | } |
2757 | } | |
2758 | } | |
2759 | ||
62682a34 | 2760 | impl<'a> Clean<Stability> for &'a attr::Stability { |
b039eaaf SL |
2761 | fn clean(&self, dc: &DocContext) -> Stability { |
2762 | (**self).clean(dc) | |
62682a34 SL |
2763 | } |
2764 | } | |
2765 | ||
9cc50fc6 SL |
2766 | impl Clean<Deprecation> for attr::Deprecation { |
2767 | fn clean(&self, _: &DocContext) -> Deprecation { | |
2768 | Deprecation { | |
2769 | since: self.since.as_ref().map_or("".to_string(), |s| s.to_string()), | |
2770 | note: self.note.as_ref().map_or("".to_string(), |s| s.to_string()), | |
2771 | } | |
2772 | } | |
2773 | } | |
2774 | ||
d9579d0f AL |
2775 | impl<'tcx> Clean<Item> for ty::AssociatedConst<'tcx> { |
2776 | fn clean(&self, cx: &DocContext) -> Item { | |
2777 | Item { | |
2778 | source: DUMMY_SP.clean(cx), | |
2779 | name: Some(self.name.clean(cx)), | |
2780 | attrs: Vec::new(), | |
2781 | inner: AssociatedConstItem(self.ty.clean(cx), None), | |
2782 | visibility: None, | |
2783 | def_id: self.def_id, | |
2784 | stability: None, | |
9cc50fc6 | 2785 | deprecation: None, |
d9579d0f AL |
2786 | } |
2787 | } | |
2788 | } | |
2789 | ||
62682a34 | 2790 | impl<'tcx> Clean<Item> for ty::AssociatedType<'tcx> { |
1a4d82fc | 2791 | fn clean(&self, cx: &DocContext) -> Item { |
9346a6ac | 2792 | let my_name = self.name.clean(cx); |
62682a34 SL |
2793 | |
2794 | let mut bounds = if let ty::TraitContainer(did) = self.container { | |
2795 | // When loading a cross-crate associated type, the bounds for this type | |
2796 | // are actually located on the trait/impl itself, so we need to load | |
2797 | // all of the generics from there and then look for bounds that are | |
2798 | // applied to this associated type in question. | |
c1a9b12d SL |
2799 | let def = cx.tcx().lookup_trait_def(did); |
2800 | let predicates = cx.tcx().lookup_predicates(did); | |
62682a34 SL |
2801 | let generics = (&def.generics, &predicates, subst::TypeSpace).clean(cx); |
2802 | generics.where_predicates.iter().filter_map(|pred| { | |
2803 | let (name, self_type, trait_, bounds) = match *pred { | |
2804 | WherePredicate::BoundPredicate { | |
2805 | ty: QPath { ref name, ref self_type, ref trait_ }, | |
2806 | ref bounds | |
2807 | } => (name, self_type, trait_, bounds), | |
2808 | _ => return None, | |
2809 | }; | |
2810 | if *name != my_name { return None } | |
2811 | match **trait_ { | |
2812 | ResolvedPath { did, .. } if did == self.container.id() => {} | |
2813 | _ => return None, | |
2814 | } | |
2815 | match **self_type { | |
2816 | Generic(ref s) if *s == "Self" => {} | |
2817 | _ => return None, | |
2818 | } | |
2819 | Some(bounds) | |
2820 | }).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>() | |
2821 | } else { | |
2822 | vec![] | |
2823 | }; | |
9346a6ac AL |
2824 | |
2825 | // Our Sized/?Sized bound didn't get handled when creating the generics | |
2826 | // because we didn't actually get our whole set of bounds until just now | |
2827 | // (some of them may have come from the trait). If we do have a sized | |
2828 | // bound, we remove it, and if we don't then we add the `?Sized` bound | |
2829 | // at the end. | |
2830 | match bounds.iter().position(|b| b.is_sized_bound(cx)) { | |
2831 | Some(i) => { bounds.remove(i); } | |
2832 | None => bounds.push(TyParamBound::maybe_sized(cx)), | |
2833 | } | |
2834 | ||
1a4d82fc JJ |
2835 | Item { |
2836 | source: DUMMY_SP.clean(cx), | |
2837 | name: Some(self.name.clean(cx)), | |
9346a6ac | 2838 | attrs: inline::load_attrs(cx, cx.tcx(), self.def_id), |
62682a34 | 2839 | inner: AssociatedTypeItem(bounds, self.ty.clean(cx)), |
9346a6ac | 2840 | visibility: self.vis.clean(cx), |
1a4d82fc | 2841 | def_id: self.def_id, |
9cc50fc6 SL |
2842 | stability: stability::lookup_stability(cx.tcx(), self.def_id).clean(cx), |
2843 | deprecation: stability::lookup_deprecation(cx.tcx(), self.def_id).clean(cx), | |
1a4d82fc JJ |
2844 | } |
2845 | } | |
2846 | } | |
2847 | ||
9346a6ac AL |
2848 | impl<'a> Clean<Typedef> for (ty::TypeScheme<'a>, ty::GenericPredicates<'a>, |
2849 | ParamSpace) { | |
85aaf69f SL |
2850 | fn clean(&self, cx: &DocContext) -> Typedef { |
2851 | let (ref ty_scheme, ref predicates, ps) = *self; | |
2852 | Typedef { | |
2853 | type_: ty_scheme.ty.clean(cx), | |
2854 | generics: (&ty_scheme.generics, predicates, ps).clean(cx) | |
2855 | } | |
2856 | } | |
2857 | } | |
2858 | ||
e9174d1e | 2859 | fn lang_struct(cx: &DocContext, did: Option<DefId>, |
1a4d82fc JJ |
2860 | t: ty::Ty, name: &str, |
2861 | fallback: fn(Box<Type>) -> Type) -> Type { | |
2862 | let did = match did { | |
2863 | Some(did) => did, | |
2864 | None => return fallback(box t.clean(cx)), | |
2865 | }; | |
92a42be0 | 2866 | inline::record_extern_fqn(cx, did, TypeStruct); |
1a4d82fc JJ |
2867 | ResolvedPath { |
2868 | typarams: None, | |
2869 | did: did, | |
2870 | path: Path { | |
2871 | global: false, | |
2872 | segments: vec![PathSegment { | |
2873 | name: name.to_string(), | |
2874 | params: PathParameters::AngleBracketed { | |
2875 | lifetimes: vec![], | |
2876 | types: vec![t.clean(cx)], | |
2877 | bindings: vec![] | |
2878 | } | |
2879 | }], | |
2880 | }, | |
62682a34 | 2881 | is_generic: false, |
1a4d82fc JJ |
2882 | } |
2883 | } | |
2884 | ||
2885 | /// An equality constraint on an associated type, e.g. `A=Bar` in `Foo<A=Bar>` | |
85aaf69f | 2886 | #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Debug)] |
1a4d82fc JJ |
2887 | pub struct TypeBinding { |
2888 | pub name: String, | |
2889 | pub ty: Type | |
2890 | } | |
2891 | ||
e9174d1e | 2892 | impl Clean<TypeBinding> for hir::TypeBinding { |
1a4d82fc JJ |
2893 | fn clean(&self, cx: &DocContext) -> TypeBinding { |
2894 | TypeBinding { | |
b039eaaf | 2895 | name: self.name.clean(cx), |
1a4d82fc JJ |
2896 | ty: self.ty.clean(cx) |
2897 | } | |
2898 | } | |
2899 | } |