]> git.proxmox.com Git - rustc.git/blame - src/librustdoc/clean/mod.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / librustdoc / clean / mod.rs
CommitLineData
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
14pub use self::Type::*;
15pub use self::PrimitiveType::*;
16pub use self::TypeKind::*;
1a4d82fc
JJ
17pub use self::VariantKind::*;
18pub use self::Mutability::*;
85aaf69f 19pub use self::Import::*;
1a4d82fc
JJ
20pub use self::ItemEnum::*;
21pub use self::Attribute::*;
22pub use self::TyParamBound::*;
23pub use self::SelfTy::*;
24pub use self::FunctionRetTy::*;
1a4d82fc
JJ
25
26use syntax;
7453a54e 27use syntax::abi::Abi;
1a4d82fc 28use syntax::ast;
b039eaaf
SL
29use syntax::attr;
30use syntax::attr::{AttributeMethods, AttrMetaMethods};
85aaf69f 31use syntax::codemap;
1a4d82fc
JJ
32use syntax::codemap::{DUMMY_SP, Pos, Spanned};
33use syntax::parse::token::{self, InternedString, special_idents};
34use syntax::ptr::P;
35
36use rustc_trans::back::link;
92a42be0 37use rustc::middle::cstore::{self, CrateStore};
54a0048b
SL
38use rustc::hir::def::Def;
39use rustc::hir::def_id::{DefId, DefIndex};
40use rustc::ty::subst::{self, ParamSpace, VecPerParamSpace};
41use rustc::ty;
1a4d82fc 42use rustc::middle::stability;
1a4d82fc 43
54a0048b 44use rustc::hir;
e9174d1e 45
54a0048b 46use std::collections::{HashMap, HashSet};
9346a6ac 47use std::path::PathBuf;
1a4d82fc
JJ
48use std::rc::Rc;
49use std::u32;
7453a54e 50use std::env::current_dir;
1a4d82fc
JJ
51
52use core::DocContext;
53use doctree;
54use visit_ast;
54a0048b 55use html::item_type::ItemType;
1a4d82fc
JJ
56
57mod inline;
9346a6ac 58mod simplify;
1a4d82fc
JJ
59
60// extract the stability index for a node from tcx, if possible
e9174d1e 61fn 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
65fn 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
69pub trait Clean<T> {
70 fn clean(&self, cx: &DocContext) -> T;
71}
72
c34b1796 73impl<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
79impl<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
85impl<T: Clean<U>, U> Clean<U> for P<T> {
86 fn clean(&self, cx: &DocContext) -> U {
87 (**self).clean(cx)
88 }
89}
90
91impl<T: Clean<U>, U> Clean<U> for Rc<T> {
92 fn clean(&self, cx: &DocContext) -> U {
93 (**self).clean(cx)
94 }
95}
96
97impl<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
103impl<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 109impl<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
116pub 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
125struct CrateNum(ast::CrateNum);
126
1a4d82fc
JJ
127impl<'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
220pub struct ExternalCrate {
221 pub name: String,
222 pub attrs: Vec<Attribute>,
223 pub primitives: Vec<PrimitiveType>,
224}
225
92a42be0 226impl 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
251pub 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
264impl 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 336pub 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
369pub struct Module {
370 pub items: Vec<Item>,
371 pub is_crate: bool,
372}
373
374impl 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
429pub 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
435impl 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
474pub enum Attribute {
475 Word(String),
54a0048b 476 List(String, Vec<Attribute>),
1a4d82fc
JJ
477 NameValue(String, String)
478}
479
b039eaaf 480impl 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 494impl 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.
501impl 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
523pub 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 530impl 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
541impl<'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
555pub enum TyParamBound {
556 RegionBound(Lifetime),
e9174d1e 557 TraitBound(PolyTrait, hir::TraitBoundModifier)
1a4d82fc
JJ
558}
559
9346a6ac
AL
560impl 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 583impl 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
592impl<'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 612fn 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 657fn 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
668impl 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
702impl<'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
747impl<'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
760pub struct Lifetime(String);
761
762impl 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 774impl 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 780impl 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
786impl Clean<Lifetime> for ty::RegionParameterDef {
787 fn clean(&self, _: &DocContext) -> Lifetime {
c1a9b12d 788 Lifetime(self.name.to_string())
1a4d82fc
JJ
789 }
790}
791
792impl 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
810pub 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 816impl 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
840impl<'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
856impl<'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
865impl<'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
875impl 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
885impl<'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
896impl<'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
905impl<'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
923pub struct Generics {
924 pub lifetimes: Vec<Lifetime>,
925 pub type_params: Vec<TyParam>,
926 pub where_predicates: Vec<WherePredicate>
927}
928
e9174d1e 929impl 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
939impl<'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
1008pub 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 1017impl 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 1044pub 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 1052impl 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
1077pub enum SelfTy {
1078 SelfStatic,
1079 SelfValue,
1080 SelfBorrowed(Option<Lifetime>, Mutability),
1081 SelfExplicit(Type),
1082}
1083
e9174d1e 1084impl 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
1098pub 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
1106impl 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
1128pub 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
1136pub struct Arguments {
1137 pub values: Vec<Argument>,
1138}
1139
e9174d1e 1140impl 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
1153impl<'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 1162impl<'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
1191pub struct Argument {
1192 pub type_: Type,
1193 pub name: String,
1194 pub id: ast::NodeId,
1195}
1196
e9174d1e 1197impl 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
1208pub enum FunctionRetTy {
1209 Return(Type),
85aaf69f 1210 DefaultReturn,
1a4d82fc
JJ
1211 NoReturn
1212}
1213
e9174d1e 1214impl 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 1225pub 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
1232impl 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 1252impl 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 1258impl 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 1267impl 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 1298impl 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
1330impl<'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
1404impl<'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
1416pub 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 1425pub 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
1470pub 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
1484pub enum TypeKind {
1485 TypeEnum,
1486 TypeFunction,
1487 TypeModule,
1488 TypeConst,
1489 TypeStatic,
1490 TypeStruct,
1491 TypeTrait,
1492 TypeVariant,
1493 TypeTypedef,
1494}
1495
54a0048b
SL
1496pub trait GetDefId {
1497 fn def_id(&self) -> Option<DefId>;
1498}
1499
1500impl<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
1506impl 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
1521impl 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
1530impl 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 1606impl 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
1659impl<'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 1747impl 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 1762impl<'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 1779pub type Visibility = hir::Visibility;
1a4d82fc 1780
e9174d1e 1781impl Clean<Option<Visibility>> for hir::Visibility {
1a4d82fc 1782 fn clean(&self, _: &DocContext) -> Option<Visibility> {
54a0048b
SL
1783 Some(self.clone())
1784 }
1785}
1786
1787impl 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
1794pub struct Struct {
1795 pub struct_type: doctree::StructType,
1796 pub generics: Generics,
1797 pub fields: Vec<Item>,
1798 pub fields_stripped: bool,
1799}
1800
1801impl 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
1825pub struct VariantStruct {
1826 pub struct_type: doctree::StructType,
1827 pub fields: Vec<Item>,
1828 pub fields_stripped: bool,
1829}
1830
54a0048b 1831impl 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
1842pub struct Enum {
1843 pub variants: Vec<Item>,
1844 pub generics: Generics,
1845 pub variants_stripped: bool,
1846}
1847
1848impl 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
1868pub struct Variant {
1869 pub kind: VariantKind,
1870}
1871
1872impl 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 1889impl<'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
1931pub enum VariantKind {
1932 CLikeVariant,
1933 TupleVariant(Vec<Type>),
1934 StructVariant(VariantStruct),
1935}
1936
b039eaaf
SL
1937fn 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
1948pub 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
1956impl 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
1966impl 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
1987pub struct Path {
1988 pub global: bool,
1989 pub segments: Vec<PathSegment>,
1990}
1991
9346a6ac
AL
1992impl 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 2008impl 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
2018pub 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 2030impl 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
2052pub struct PathSegment {
2053 pub name: String,
2054 pub params: PathParameters
2055}
2056
e9174d1e 2057impl 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 2066fn 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
2080impl 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
2087pub struct Typedef {
2088 pub type_: Type,
2089 pub generics: Generics,
2090}
2091
2092impl 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 2111pub 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 2118impl 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
2134pub 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
2143impl 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
2164pub struct Constant {
2165 pub type_: Type,
2166 pub expr: String,
2167}
2168
2169impl 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
2188pub enum Mutability {
2189 Mutable,
2190 Immutable,
2191}
2192
e9174d1e 2193impl 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)]
2203pub enum ImplPolarity {
2204 Positive,
2205 Negative,
2206}
2207
e9174d1e 2208impl 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 2218pub 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
2229fn detect_derived<M: AttrMetaMethods>(attrs: &[M]) -> bool {
2230 attr::contains_name(attrs, "automatically_derived")
2231}
2232
d9579d0f
AL
2233impl 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
2277fn 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)]
2331pub struct DefaultImpl {
e9174d1e 2332 pub unsafety: hir::Unsafety,
c34b1796
AL
2333 pub trait_: Type,
2334}
2335
2336impl 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
2354impl 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 2369impl 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)]
2436pub 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
2446pub 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
2452pub struct ViewListIdent {
2453 pub name: String,
e9174d1e
SL
2454 pub rename: Option<String>,
2455 pub source: Option<DefId>,
1a4d82fc
JJ
2456}
2457
e9174d1e 2458impl 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 2475impl 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 2487impl 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
2522trait ToSource {
2523 fn to_src(&self, cx: &DocContext) -> String;
2524}
2525
2526impl 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 2538fn 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 2558fn 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
2597fn 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 2647fn 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
2676fn 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 2683fn 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
2690pub struct Macro {
2691 pub source: String,
d9579d0f 2692 pub imported_from: Option<String>,
1a4d82fc
JJ
2693}
2694
2695impl 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 2717pub 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)]
2727pub struct Deprecation {
2728 pub since: String,
2729 pub note: String,
2730}
2731
1a4d82fc
JJ
2732impl 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 2760impl<'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
2766impl 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
2775impl<'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 2790impl<'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
2848impl<'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 2859fn 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
2887pub struct TypeBinding {
2888 pub name: String,
2889 pub ty: Type
2890}
2891
e9174d1e 2892impl 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}