mod.rs 99.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

C
Corey Richardson 已提交
11 12 13
//! This module contains the "cleaned" pieces of the AST, and the functions
//! that clean them.

S
Steven Fackler 已提交
14 15 16 17 18
pub use self::Type::*;
pub use self::PrimitiveType::*;
pub use self::TypeKind::*;
pub use self::VariantKind::*;
pub use self::Mutability::*;
19
pub use self::Import::*;
S
Steven Fackler 已提交
20 21 22 23 24
pub use self::ItemEnum::*;
pub use self::Attribute::*;
pub use self::TyParamBound::*;
pub use self::SelfTy::*;
pub use self::FunctionRetTy::*;
J
Jeffrey Seyfried 已提交
25
pub use self::Visibility::*;
S
Steven Fackler 已提交
26

27
use syntax::abi::Abi;
C
Corey Richardson 已提交
28
use syntax::ast;
29 30
use syntax::attr;
use syntax::attr::{AttributeMethods, AttrMetaMethods};
31
use syntax::codemap::Spanned;
32
use syntax::parse::token::{self, InternedString, keywords};
33
use syntax::ptr::P;
34
use syntax_pos::{self, DUMMY_SP, Pos};
C
Corey Richardson 已提交
35

36
use rustc_trans::back::link;
37
use rustc::middle::cstore;
M
mitaa 已提交
38
use rustc::middle::privacy::AccessLevels;
39
use rustc::middle::resolve_lifetime::DefRegion::*;
40
use rustc::hir::def::Def;
M
mitaa 已提交
41
use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
42
use rustc::hir::fold::Folder;
43
use rustc::hir::print as pprust;
44 45
use rustc::ty::subst::{self, ParamSpace, VecPerParamSpace};
use rustc::ty;
46
use rustc::middle::stability;
47

48
use rustc::hir;
49

50
use std::collections::{HashMap, HashSet};
51
use std::path::PathBuf;
52
use std::rc::Rc;
M
mitaa 已提交
53
use std::sync::Arc;
54
use std::u32;
55
use std::env::current_dir;
M
mitaa 已提交
56
use std::mem;
57

58
use core::DocContext;
C
Corey Richardson 已提交
59 60
use doctree;
use visit_ast;
61
use html::item_type::ItemType;
C
Corey Richardson 已提交
62

63
pub mod inline;
64
mod simplify;
65

66
// extract the stability index for a node from tcx, if possible
N
Niko Matsakis 已提交
67
fn get_stability(cx: &DocContext, def_id: DefId) -> Option<Stability> {
68
    cx.tcx_opt().and_then(|tcx| tcx.lookup_stability(def_id)).clean(cx)
69 70
}

71
fn get_deprecation(cx: &DocContext, def_id: DefId) -> Option<Deprecation> {
72
    cx.tcx_opt().and_then(|tcx| tcx.lookup_deprecation(def_id)).clean(cx)
73 74
}

C
Corey Richardson 已提交
75
pub trait Clean<T> {
76
    fn clean(&self, cx: &DocContext) -> T;
C
Corey Richardson 已提交
77 78
}

79
impl<T: Clean<U>, U> Clean<Vec<U>> for [T] {
80 81
    fn clean(&self, cx: &DocContext) -> Vec<U> {
        self.iter().map(|x| x.clean(cx)).collect()
82 83 84
    }
}

85
impl<T: Clean<U>, U> Clean<VecPerParamSpace<U>> for VecPerParamSpace<T> {
86 87
    fn clean(&self, cx: &DocContext) -> VecPerParamSpace<U> {
        self.map(|x| x.clean(cx))
88 89 90
    }
}

91
impl<T: Clean<U>, U> Clean<U> for P<T> {
92 93
    fn clean(&self, cx: &DocContext) -> U {
        (**self).clean(cx)
C
Corey Richardson 已提交
94 95 96
    }
}

97
impl<T: Clean<U>, U> Clean<U> for Rc<T> {
98 99
    fn clean(&self, cx: &DocContext) -> U {
        (**self).clean(cx)
100 101 102
    }
}

C
Corey Richardson 已提交
103
impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
104
    fn clean(&self, cx: &DocContext) -> Option<U> {
M
mitaa 已提交
105
        self.as_ref().map(|v| v.clean(cx))
C
Corey Richardson 已提交
106 107 108
    }
}

109 110 111 112 113 114
impl<T, U> Clean<U> for ty::Binder<T> where T: Clean<U> {
    fn clean(&self, cx: &DocContext) -> U {
        self.0.clean(cx)
    }
}

115
impl<T: Clean<U>, U> Clean<Vec<U>> for P<[T]> {
116 117
    fn clean(&self, cx: &DocContext) -> Vec<U> {
        self.iter().map(|x| x.clean(cx)).collect()
C
Corey Richardson 已提交
118 119 120
    }
}

M
mitaa 已提交
121
#[derive(Clone, Debug)]
C
Corey Richardson 已提交
122
pub struct Crate {
123
    pub name: String,
A
Alex Crichton 已提交
124
    pub src: PathBuf,
125 126
    pub module: Option<Item>,
    pub externs: Vec<(ast::CrateNum, ExternalCrate)>,
127
    pub primitives: Vec<PrimitiveType>,
M
mitaa 已提交
128 129 130
    pub access_levels: Arc<AccessLevels<DefId>>,
    // These are later on moved into `CACHEKEY`, leaving the map empty.
    // Only here so that they can be filtered through the rustdoc passes.
N
Niko Matsakis 已提交
131
    pub external_traits: HashMap<DefId, Trait>,
C
Corey Richardson 已提交
132 133
}

A
Ariel Ben-Yehuda 已提交
134 135
struct CrateNum(ast::CrateNum);

136 137
impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
    fn clean(&self, cx: &DocContext) -> Crate {
138
        use rustc::session::config::Input;
M
mitaa 已提交
139
        use ::visit_lib::LibEmbargoVisitor;
140

141 142
        if let Some(t) = cx.tcx_opt() {
            cx.deref_trait_did.set(t.lang_items.deref_trait());
M
mitaa 已提交
143
            cx.renderinfo.borrow_mut().deref_trait_did = cx.deref_trait_did.get();
144 145
        }

146
        let mut externs = Vec::new();
A
Ariel Ben-Yehuda 已提交
147 148
        for cnum in cx.sess().cstore.crates() {
            externs.push((cnum, CrateNum(cnum).clean(cx)));
M
mitaa 已提交
149 150 151 152
            if cx.tcx_opt().is_some() {
                // Analyze doc-reachability for extern items
                LibEmbargoVisitor::new(cx).visit_lib(cnum);
            }
A
Ariel Ben-Yehuda 已提交
153
        }
154
        externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
C
Corey Richardson 已提交
155

156
        // Figure out the name of this crate
157
        let input = &cx.input;
158
        let name = link::find_crate_name(None, &self.attrs, input);
159

160
        // Clean the crate, translating the entire libsyntax AST to one that is
161
        // understood by rustdoc.
162
        let mut module = self.module.clean(cx);
163 164 165

        // Collect all inner modules which are tagged as implementations of
        // primitives.
166 167 168
        //
        // Note that this loop only searches the top-level items of the crate,
        // and this is intentional. If we were to search the entire crate for an
169
        // item tagged with `#[doc(primitive)]` then we would also have to
170 171 172 173 174 175 176 177 178 179 180
        // search the entirety of external modules for items tagged
        // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
        // all that metadata unconditionally).
        //
        // In order to keep the metadata load under control, the
        // `#[doc(primitive)]` feature is explicitly designed to only allow the
        // primitive tags to show up as the top level items in a crate.
        //
        // Also note that this does not attempt to deal with modules tagged
        // duplicately for the same primitive. This is handled later on when
        // rendering by delegating everything to a hash map.
181 182 183 184 185 186 187
        let mut primitives = Vec::new();
        {
            let m = match module.inner {
                ModuleItem(ref mut m) => m,
                _ => unreachable!(),
            };
            let mut tmp = Vec::new();
188
            for child in &mut m.items {
M
mitaa 已提交
189 190
                if !child.is_mod() {
                    continue;
191
                }
192
                let prim = match PrimitiveType::find(&child.attrs) {
193 194 195 196
                    Some(prim) => prim,
                    None => continue,
                };
                primitives.push(prim);
197
                tmp.push(Item {
198 199
                    source: Span::empty(),
                    name: Some(prim.to_url_str().to_string()),
200
                    attrs: child.attrs.clone(),
J
Jeffrey Seyfried 已提交
201
                    visibility: Some(Public),
202
                    stability: None,
203
                    deprecation: None,
204
                    def_id: DefId::local(prim.to_def_index()),
205
                    inner: PrimitiveItem(prim),
206
                });
207
            }
208
            m.items.extend(tmp);
209 210
        }

211
        let src = match cx.input {
212 213 214 215 216 217 218
            Input::File(ref path) => {
                if path.is_absolute() {
                    path.clone()
                } else {
                    current_dir().unwrap().join(path)
                }
            },
219
            Input::Str { ref name, .. } => PathBuf::from(name.clone()),
220 221
        };

M
mitaa 已提交
222 223 224
        let mut access_levels = cx.access_levels.borrow_mut();
        let mut external_traits = cx.external_traits.borrow_mut();

C
Corey Richardson 已提交
225
        Crate {
226
            name: name.to_string(),
227
            src: src,
228
            module: Some(module),
229
            externs: externs,
230
            primitives: primitives,
M
mitaa 已提交
231 232
            access_levels: Arc::new(mem::replace(&mut access_levels, Default::default())),
            external_traits: mem::replace(&mut external_traits, Default::default()),
233 234 235 236
        }
    }
}

J
Jorge Aparicio 已提交
237
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
238
pub struct ExternalCrate {
239
    pub name: String,
240
    pub attrs: Vec<Attribute>,
241
    pub primitives: Vec<PrimitiveType>,
242 243
}

A
Ariel Ben-Yehuda 已提交
244
impl Clean<ExternalCrate> for CrateNum {
245
    fn clean(&self, cx: &DocContext) -> ExternalCrate {
246
        let mut primitives = Vec::new();
247
        cx.tcx_opt().map(|tcx| {
A
Ariel Ben-Yehuda 已提交
248 249
            for item in tcx.sess.cstore.crate_top_level_items(self.0) {
                let did = match item.def {
250
                    cstore::DlDef(Def::Mod(did)) => did,
A
Ariel Ben-Yehuda 已提交
251
                    _ => continue
252
                };
253
                let attrs = inline::load_attrs(cx, tcx, did);
254
                PrimitiveType::find(&attrs).map(|prim| primitives.push(prim));
A
Ariel Ben-Yehuda 已提交
255
            }
256
        });
257
        ExternalCrate {
258
            name: (&cx.sess().cstore.crate_name(self.0)[..]).to_owned(),
A
Ariel Ben-Yehuda 已提交
259
            attrs: cx.sess().cstore.crate_attrs(self.0).clean(cx),
260
            primitives: primitives,
C
Corey Richardson 已提交
261 262 263 264 265 266 267
        }
    }
}

/// Anything with a source location and set of attributes and, optionally, a
/// name. That is, anything that can be documented. This doesn't correspond
/// directly to the AST's concept of an item; it's a strict superset.
J
Jorge Aparicio 已提交
268
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
269 270
pub struct Item {
    /// Stringified span
271
    pub source: Span,
C
Corey Richardson 已提交
272
    /// Not everything has a name. E.g., impls
273
    pub name: Option<String>,
M
mitaa 已提交
274
    pub attrs: Vec<Attribute>,
275 276
    pub inner: ItemEnum,
    pub visibility: Option<Visibility>,
N
Niko Matsakis 已提交
277
    pub def_id: DefId,
278
    pub stability: Option<Stability>,
279
    pub deprecation: Option<Deprecation>,
C
Corey Richardson 已提交
280 281
}

282 283 284 285
impl Item {
    /// Finds the `doc` attribute as a NameValue and returns the corresponding
    /// value found.
    pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
M
mitaa 已提交
286
        self.attrs.value("doc")
287
    }
M
mitaa 已提交
288 289
    pub fn is_crate(&self) -> bool {
        match self.inner {
290 291 292
            StrippedItem(box ModuleItem(Module { is_crate: true, ..})) |
            ModuleItem(Module { is_crate: true, ..}) => true,
            _ => false,
M
mitaa 已提交
293 294
        }
    }
295
    pub fn is_mod(&self) -> bool {
296
        ItemType::from_item(self) == ItemType::Module
297 298
    }
    pub fn is_trait(&self) -> bool {
299
        ItemType::from_item(self) == ItemType::Trait
300 301
    }
    pub fn is_struct(&self) -> bool {
302
        ItemType::from_item(self) == ItemType::Struct
303 304
    }
    pub fn is_enum(&self) -> bool {
305
        ItemType::from_item(self) == ItemType::Module
306 307
    }
    pub fn is_fn(&self) -> bool {
308
        ItemType::from_item(self) == ItemType::Function
309
    }
M
mitaa 已提交
310
    pub fn is_associated_type(&self) -> bool {
311
        ItemType::from_item(self) == ItemType::AssociatedType
M
mitaa 已提交
312 313
    }
    pub fn is_associated_const(&self) -> bool {
314
        ItemType::from_item(self) == ItemType::AssociatedConst
M
mitaa 已提交
315 316
    }
    pub fn is_method(&self) -> bool {
317
        ItemType::from_item(self) == ItemType::Method
M
mitaa 已提交
318 319
    }
    pub fn is_ty_method(&self) -> bool {
320 321
        ItemType::from_item(self) == ItemType::TyMethod
    }
322 323 324
    pub fn is_primitive(&self) -> bool {
        ItemType::from_item(self) == ItemType::Primitive
    }
325 326
    pub fn is_stripped(&self) -> bool {
        match self.inner { StrippedItem(..) => true, _ => false }
M
mitaa 已提交
327
    }
328 329 330 331 332 333 334 335 336
    pub fn has_stripped_fields(&self) -> Option<bool> {
        match self.inner {
            StructItem(ref _struct) => Some(_struct.fields_stripped),
            VariantItem(Variant { kind: StructVariant(ref vstruct)} ) => {
                Some(vstruct.fields_stripped)
            },
            _ => None,
        }
    }
337 338

    pub fn stability_class(&self) -> String {
M
mitaa 已提交
339 340 341 342 343 344 345
        self.stability.as_ref().map(|ref s| {
            let mut base = match s.level {
                stability::Unstable => "unstable".to_string(),
                stability::Stable => String::new(),
            };
            if !s.deprecated_since.is_empty() {
                base.push_str(" deprecated");
346
            }
M
mitaa 已提交
347 348
            base
        }).unwrap_or(String::new())
349
    }
350 351

    pub fn stable_since(&self) -> Option<&str> {
M
mitaa 已提交
352
        self.stability.as_ref().map(|s| &s.since[..])
353
    }
354 355
}

J
Jorge Aparicio 已提交
356
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
357
pub enum ItemEnum {
358 359
    ExternCrateItem(String, Option<String>),
    ImportItem(Import),
C
Corey Richardson 已提交
360 361 362 363
    StructItem(Struct),
    EnumItem(Enum),
    FunctionItem(Function),
    ModuleItem(Module),
364
    TypedefItem(Typedef, bool /* is associated type */),
C
Corey Richardson 已提交
365
    StaticItem(Static),
366
    ConstantItem(Constant),
C
Corey Richardson 已提交
367 368
    TraitItem(Trait),
    ImplItem(Impl),
369 370
    /// A method signature only. Used for required methods in traits (ie,
    /// non-default-methods).
C
Corey Richardson 已提交
371
    TyMethodItem(TyMethod),
372
    /// A method with a body.
C
Corey Richardson 已提交
373
    MethodItem(Method),
374
    StructFieldItem(Type),
C
Corey Richardson 已提交
375
    VariantItem(Variant),
376
    /// `fn`s from an extern block
377
    ForeignFunctionItem(Function),
378
    /// `static`s from an extern block
379
    ForeignStaticItem(Static),
380
    MacroItem(Macro),
381
    PrimitiveItem(PrimitiveType),
382
    AssociatedConstItem(Type, Option<String>),
383
    AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
384
    DefaultImplItem(DefaultImpl),
385 386
    /// An item that has been stripped by a rustdoc pass
    StrippedItem(Box<ItemEnum>),
C
Corey Richardson 已提交
387 388
}

J
Jorge Aparicio 已提交
389
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
390
pub struct Module {
391 392
    pub items: Vec<Item>,
    pub is_crate: bool,
C
Corey Richardson 已提交
393 394 395
}

impl Clean<Item> for doctree::Module {
396
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
397
        let name = if self.name.is_some() {
398
            self.name.unwrap().clean(cx)
C
Corey Richardson 已提交
399
        } else {
400
            "".to_string()
C
Corey Richardson 已提交
401
        };
402 403 404

        let mut items: Vec<Item> = vec![];
        items.extend(self.extern_crates.iter().map(|x| x.clean(cx)));
405
        items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
406 407 408
        items.extend(self.structs.iter().map(|x| x.clean(cx)));
        items.extend(self.enums.iter().map(|x| x.clean(cx)));
        items.extend(self.fns.iter().map(|x| x.clean(cx)));
409
        items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx)));
410 411 412 413 414
        items.extend(self.mods.iter().map(|x| x.clean(cx)));
        items.extend(self.typedefs.iter().map(|x| x.clean(cx)));
        items.extend(self.statics.iter().map(|x| x.clean(cx)));
        items.extend(self.constants.iter().map(|x| x.clean(cx)));
        items.extend(self.traits.iter().map(|x| x.clean(cx)));
415
        items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
416
        items.extend(self.macros.iter().map(|x| x.clean(cx)));
417
        items.extend(self.def_traits.iter().map(|x| x.clean(cx)));
418 419 420

        // determine if we should display the inner contents or
        // the outer `mod` item for the source code.
421
        let whence = {
422
            let cm = cx.sess().codemap();
423 424 425 426 427 428 429 430 431 432 433
            let outer = cm.lookup_char_pos(self.where_outer.lo);
            let inner = cm.lookup_char_pos(self.where_inner.lo);
            if outer.file.start_pos == inner.file.start_pos {
                // mod foo { ... }
                self.where_outer
            } else {
                // mod foo; (and a separate FileMap for the contents)
                self.where_inner
            }
        };

C
Corey Richardson 已提交
434 435
        Item {
            name: Some(name),
436 437 438 439
            attrs: self.attrs.clean(cx),
            source: whence.clean(cx),
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
440
            deprecation: self.depr.clean(cx),
441
            def_id: cx.map.local_def_id(self.id),
C
Corey Richardson 已提交
442
            inner: ModuleItem(Module {
443
               is_crate: self.is_crate,
444
               items: items
C
Corey Richardson 已提交
445 446 447 448 449
            })
        }
    }
}

M
mitaa 已提交
450 451 452
pub trait Attributes {
    fn has_word(&self, &str) -> bool;
    fn value<'a>(&'a self, &str) -> Option<&'a str>;
453
    fn list<'a>(&'a self, &str) -> &'a [Attribute];
M
mitaa 已提交
454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
}

impl Attributes for [Attribute] {
    /// Returns whether the attribute list contains a specific `Word`
    fn has_word(&self, word: &str) -> bool {
        for attr in self {
            if let Word(ref w) = *attr {
                if word == *w {
                    return true;
                }
            }
        }
        false
    }

    /// Finds an attribute as NameValue and returns the corresponding value found.
    fn value<'a>(&'a self, name: &str) -> Option<&'a str> {
        for attr in self {
            if let NameValue(ref x, ref v) = *attr {
                if name == *x {
                    return Some(v);
                }
            }
        }
        None
    }

    /// Finds an attribute as List and returns the list of attributes nested inside.
482
    fn list<'a>(&'a self, name: &str) -> &'a [Attribute] {
M
mitaa 已提交
483 484 485 486 487 488 489 490 491 492 493
        for attr in self {
            if let List(ref x, ref list) = *attr {
                if name == *x {
                    return &list[..];
                }
            }
        }
        &[]
    }
}

J
Jorge Aparicio 已提交
494
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
495
pub enum Attribute {
496
    Word(String),
M
mitaa 已提交
497
    List(String, Vec<Attribute>),
498
    NameValue(String, String)
C
Corey Richardson 已提交
499 500
}

501
impl Clean<Attribute> for ast::MetaItem {
502
    fn clean(&self, cx: &DocContext) -> Attribute {
503 504 505 506 507 508
        if self.is_word() {
            Word(self.name().to_string())
        } else if let Some(v) = self.value_str() {
            NameValue(self.name().to_string(), v.to_string())
        } else { // must be a list
            let l = self.meta_item_list().unwrap();
C
cgswords 已提交
509
            List(self.name().to_string(), l.clean(cx))
510
       }
C
Corey Richardson 已提交
511 512 513
    }
}

514
impl Clean<Attribute> for ast::Attribute {
515
    fn clean(&self, cx: &DocContext) -> Attribute {
516
        self.with_desugared_doc(|a| a.meta().clean(cx))
C
Corey Richardson 已提交
517 518 519
    }
}

520
// This is a rough approximation that gets us what we want.
521
impl attr::AttrMetaMethods for Attribute {
522
    fn name(&self) -> InternedString {
523
        match *self {
524
            Word(ref n) | List(ref n, _) | NameValue(ref n, _) => {
525
                token::intern_and_get_ident(n)
526
            }
527 528 529
        }
    }

530
    fn value_str(&self) -> Option<InternedString> {
531
        match *self {
532
            NameValue(_, ref v) => {
533
                Some(token::intern_and_get_ident(v))
534
            }
535 536 537
            _ => None,
        }
    }
538
    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<ast::MetaItem>]> { None }
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560

    fn is_word(&self) -> bool {
      match *self {
        Word(_) => true,
        _ => false,
      }
    }

    fn is_value_str(&self) -> bool {
      match *self {
        NameValue(..) => true,
        _ => false,
      }
    }

    fn is_meta_item_list(&self) -> bool {
      match *self {
        List(..) => true,
        _ => false,
      }
    }

561
    fn span(&self) -> syntax_pos::Span { unimplemented!() }
562 563
}

J
Jorge Aparicio 已提交
564
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
565
pub struct TyParam {
566
    pub name: String,
N
Niko Matsakis 已提交
567
    pub did: DefId,
568
    pub bounds: Vec<TyParamBound>,
569
    pub default: Option<Type>,
570
}
C
Corey Richardson 已提交
571

572
impl Clean<TyParam> for hir::TyParam {
573
    fn clean(&self, cx: &DocContext) -> TyParam {
C
Corey Richardson 已提交
574
        TyParam {
575
            name: self.name.clean(cx),
576
            did: cx.map.local_def_id(self.id),
577
            bounds: self.bounds.clean(cx),
578
            default: self.default.clean(cx),
C
Corey Richardson 已提交
579 580 581 582
        }
    }
}

583
impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> {
584
    fn clean(&self, cx: &DocContext) -> TyParam {
M
mitaa 已提交
585
        cx.renderinfo.borrow_mut().external_typarams.insert(self.def_id, self.name.clean(cx));
586
        TyParam {
587
            name: self.name.clean(cx),
588
            did: self.def_id,
589
            bounds: vec![], // these are filled in from the where-clauses
590
            default: self.default.clean(cx),
591 592 593 594
        }
    }
}

J
Jorge Aparicio 已提交
595
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
596
pub enum TyParamBound {
597
    RegionBound(Lifetime),
598
    TraitBound(PolyTrait, hir::TraitBoundModifier)
C
Corey Richardson 已提交
599 600
}

601 602
impl TyParamBound {
    fn maybe_sized(cx: &DocContext) -> TyParamBound {
603
        use rustc::hir::TraitBoundModifier as TBM;
604
        let mut sized_bound = ty::BoundSized.clean(cx);
605 606 607 608 609 610 611
        if let TyParamBound::TraitBound(_, ref mut tbm) = sized_bound {
            *tbm = TBM::Maybe
        };
        sized_bound
    }

    fn is_sized_bound(&self, cx: &DocContext) -> bool {
612
        use rustc::hir::TraitBoundModifier as TBM;
613
        if let Some(tcx) = cx.tcx_opt() {
614 615 616
            if let TyParamBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
                if trait_.def_id() == tcx.lang_items.sized_trait() {
                    return true;
617 618 619 620 621 622 623
                }
            }
        }
        false
    }
}

624
impl Clean<TyParamBound> for hir::TyParamBound {
625
    fn clean(&self, cx: &DocContext) -> TyParamBound {
C
Corey Richardson 已提交
626
        match *self {
627 628
            hir::RegionTyParamBound(lt) => RegionBound(lt.clean(cx)),
            hir::TraitTyParamBound(ref t, modifier) => TraitBound(t.clean(cx), modifier),
C
Corey Richardson 已提交
629 630 631 632
        }
    }
}

633 634 635 636
impl<'tcx> Clean<(Vec<TyParamBound>, Vec<TypeBinding>)> for ty::ExistentialBounds<'tcx> {
    fn clean(&self, cx: &DocContext) -> (Vec<TyParamBound>, Vec<TypeBinding>) {
        let mut tp_bounds = vec![];
        self.region_bound.clean(cx).map(|b| tp_bounds.push(RegionBound(b)));
637
        for bb in &self.builtin_bounds {
638
            tp_bounds.push(bb.clean(cx));
639
        }
N
Niko Matsakis 已提交
640

641
        let mut bindings = vec![];
642
        for &ty::Binder(ref pb) in &self.projection_bounds {
643 644 645 646 647
            bindings.push(TypeBinding {
                name: pb.projection_ty.item_name.clean(cx),
                ty: pb.ty.clean(cx)
            });
        }
N
Niko Matsakis 已提交
648

649
        (tp_bounds, bindings)
650 651 652
    }
}

N
Niko Matsakis 已提交
653
fn external_path_params(cx: &DocContext, trait_did: Option<DefId>,
654
                        bindings: Vec<TypeBinding>, substs: &subst::Substs) -> PathParameters {
655
    let lifetimes = substs.regions.get_slice(subst::TypeSpace)
656
                    .iter()
657
                    .filter_map(|v| v.clean(cx))
658
                    .collect();
659
    let types = substs.types.get_slice(subst::TypeSpace).to_vec();
660 661 662 663

    match (trait_did, cx.tcx_opt()) {
        // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
        (Some(did), Some(ref tcx)) if tcx.lang_items.fn_trait_kind(did).is_some() => {
664
            assert_eq!(types.len(), 1);
665
            let inputs = match types[0].sty {
666
                ty::TyTuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
667 668 669
                _ => {
                    return PathParameters::AngleBracketed {
                        lifetimes: lifetimes,
670
                        types: types.clean(cx),
671
                        bindings: bindings
672 673 674
                    }
                }
            };
675 676 677
            let output = None;
            // FIXME(#20299) return type comes from a projection now
            // match types[1].sty {
678
            //     ty::TyTuple(ref v) if v.is_empty() => None, // -> ()
679 680
            //     _ => Some(types[1].clean(cx))
            // };
681 682 683 684 685 686 687 688 689
            PathParameters::Parenthesized {
                inputs: inputs,
                output: output
            }
        },
        (_, _) => {
            PathParameters::AngleBracketed {
                lifetimes: lifetimes,
                types: types.clean(cx),
690
                bindings: bindings
691 692 693 694 695 696 697
            }
        }
    }
}

// trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
// from Fn<(A, B,), C> to Fn(A, B) -> C
N
Niko Matsakis 已提交
698
fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>,
699
                 bindings: Vec<TypeBinding>, substs: &subst::Substs) -> Path {
700 701 702
    Path {
        global: false,
        segments: vec![PathSegment {
703
            name: name.to_string(),
704
            params: external_path_params(cx, trait_did, bindings, substs)
705
        }],
706 707 708 709
    }
}

impl Clean<TyParamBound> for ty::BuiltinBound {
710 711 712
    fn clean(&self, cx: &DocContext) -> TyParamBound {
        let tcx = match cx.tcx_opt() {
            Some(tcx) => tcx,
713
            None => return RegionBound(Lifetime::statik())
714
        };
715
        let empty = subst::Substs::empty();
716 717
        let (did, path) = match *self {
            ty::BoundSend =>
718
                (tcx.lang_items.send_trait().unwrap(),
719
                 external_path(cx, "Send", None, vec![], &empty)),
720
            ty::BoundSized =>
721
                (tcx.lang_items.sized_trait().unwrap(),
722
                 external_path(cx, "Sized", None, vec![], &empty)),
723
            ty::BoundCopy =>
724
                (tcx.lang_items.copy_trait().unwrap(),
725
                 external_path(cx, "Copy", None, vec![], &empty)),
A
Alex Crichton 已提交
726 727
            ty::BoundSync =>
                (tcx.lang_items.sync_trait().unwrap(),
728
                 external_path(cx, "Sync", None, vec![], &empty)),
729
        };
M
mitaa 已提交
730
        inline::record_extern_fqn(cx, did, TypeTrait);
731 732 733 734 735
        TraitBound(PolyTrait {
            trait_: ResolvedPath {
                path: path,
                typarams: None,
                did: did,
736
                is_generic: false,
737 738
            },
            lifetimes: vec![]
739
        }, hir::TraitBoundModifier::None)
740 741 742
    }
}

743
impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
744 745 746
    fn clean(&self, cx: &DocContext) -> TyParamBound {
        let tcx = match cx.tcx_opt() {
            Some(tcx) => tcx,
747
            None => return RegionBound(Lifetime::statik())
748
        };
M
mitaa 已提交
749 750
        inline::record_extern_fqn(cx, self.def_id, TypeTrait);
        let path = external_path(cx, &tcx.item_name(self.def_id).as_str(),
751
                                 Some(self.def_id), vec![], self.substs);
752

753
        debug!("ty::TraitRef\n  substs.types(TypeSpace): {:?}\n",
754 755 756 757
               self.substs.types.get_slice(ParamSpace::TypeSpace));

        // collect any late bound regions
        let mut late_bounds = vec![];
758
        for &ty_s in self.substs.types.get_slice(ParamSpace::TypeSpace) {
759
            if let ty::TyTuple(ts) = ty_s.sty {
760
                for &ty_s in ts {
761 762
                    if let ty::TyRef(ref reg, _) = ty_s.sty {
                        if let &ty::Region::ReLateBound(_, _) = *reg {
763
                            debug!("  hit an ReLateBound {:?}", reg);
764
                            if let Some(lt) = reg.clean(cx) {
M
mitaa 已提交
765
                                late_bounds.push(lt);
766 767 768 769 770 771 772
                            }
                        }
                    }
                }
            }
        }

773 774 775 776 777 778 779 780 781
        TraitBound(
            PolyTrait {
                trait_: ResolvedPath {
                    path: path,
                    typarams: None,
                    did: self.def_id,
                    is_generic: false,
                },
                lifetimes: late_bounds,
782
            },
783 784
            hir::TraitBoundModifier::None
        )
785 786 787
    }
}

788
impl<'tcx> Clean<Option<Vec<TyParamBound>>> for subst::Substs<'tcx> {
789
    fn clean(&self, cx: &DocContext) -> Option<Vec<TyParamBound>> {
790
        let mut v = Vec::new();
791
        v.extend(self.regions.iter().filter_map(|r| r.clean(cx)).map(RegionBound));
792 793 794
        v.extend(self.types.iter().map(|t| TraitBound(PolyTrait {
            trait_: t.clean(cx),
            lifetimes: vec![]
795
        }, hir::TraitBoundModifier::None)));
796
        if !v.is_empty() {Some(v)} else {None}
797 798 799
    }
}

J
Jorge Aparicio 已提交
800
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
801
pub struct Lifetime(String);
C
Corey Richardson 已提交
802

803 804 805
impl Lifetime {
    pub fn get_ref<'a>(&'a self) -> &'a str {
        let Lifetime(ref s) = *self;
806
        let s: &'a str = s;
807 808
        return s;
    }
809 810 811 812

    pub fn statik() -> Lifetime {
        Lifetime("'static".to_string())
    }
813 814
}

815
impl Clean<Lifetime> for hir::Lifetime {
816
    fn clean(&self, _: &DocContext) -> Lifetime {
817
        Lifetime(self.name.to_string())
C
Corey Richardson 已提交
818 819 820
    }
}

821
impl Clean<Lifetime> for hir::LifetimeDef {
822
    fn clean(&self, _: &DocContext) -> Lifetime {
823 824 825 826 827 828 829 830 831 832 833
        if self.bounds.len() > 0 {
            let mut s = format!("{}: {}",
                                self.lifetime.name.to_string(),
                                self.bounds[0].name.to_string());
            for bound in self.bounds.iter().skip(1) {
                s.push_str(&format!(" + {}", bound.name.to_string()));
            }
            Lifetime(s)
        } else {
            Lifetime(self.lifetime.name.to_string())
        }
834 835 836
    }
}

837
impl Clean<Lifetime> for ty::RegionParameterDef {
838
    fn clean(&self, _: &DocContext) -> Lifetime {
839
        Lifetime(self.name.to_string())
840 841 842 843
    }
}

impl Clean<Option<Lifetime>> for ty::Region {
844
    fn clean(&self, cx: &DocContext) -> Option<Lifetime> {
845
        match *self {
846
            ty::ReStatic => Some(Lifetime::statik()),
847
            ty::ReLateBound(_, ty::BrNamed(_, name, _)) => Some(Lifetime(name.to_string())),
N
Niko Matsakis 已提交
848
            ty::ReEarlyBound(ref data) => Some(Lifetime(data.name.clean(cx))),
849 850 851 852

            ty::ReLateBound(..) |
            ty::ReFree(..) |
            ty::ReScope(..) |
853 854
            ty::ReVar(..) |
            ty::ReSkolemized(..) |
855 856
            ty::ReEmpty |
            ty::ReErased => None
857 858 859 860
        }
    }
}

J
Jorge Aparicio 已提交
861
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
862 863 864
pub enum WherePredicate {
    BoundPredicate { ty: Type, bounds: Vec<TyParamBound> },
    RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>},
865
    EqPredicate { lhs: Type, rhs: Type }
866 867
}

868
impl Clean<WherePredicate> for hir::WherePredicate {
869
    fn clean(&self, cx: &DocContext) -> WherePredicate {
N
Nick Cameron 已提交
870
        match *self {
871
            hir::WherePredicate::BoundPredicate(ref wbp) => {
872
                WherePredicate::BoundPredicate {
873
                    ty: wbp.bounded_ty.clean(cx),
N
Nick Cameron 已提交
874 875 876
                    bounds: wbp.bounds.clean(cx)
                }
            }
877

878
            hir::WherePredicate::RegionPredicate(ref wrp) => {
879 880 881 882 883 884
                WherePredicate::RegionPredicate {
                    lifetime: wrp.lifetime.clean(cx),
                    bounds: wrp.bounds.clean(cx)
                }
            }

885
            hir::WherePredicate::EqPredicate(_) => {
886
                unimplemented!() // FIXME(#20041)
N
Nick Cameron 已提交
887
            }
888 889 890 891
        }
    }
}

892 893
impl<'a> Clean<WherePredicate> for ty::Predicate<'a> {
    fn clean(&self, cx: &DocContext) -> WherePredicate {
894
        use rustc::ty::Predicate;
895 896 897 898 899 900

        match *self {
            Predicate::Trait(ref pred) => pred.clean(cx),
            Predicate::Equate(ref pred) => pred.clean(cx),
            Predicate::RegionOutlives(ref pred) => pred.clean(cx),
            Predicate::TypeOutlives(ref pred) => pred.clean(cx),
901 902 903
            Predicate::Projection(ref pred) => pred.clean(cx),
            Predicate::WellFormed(_) => panic!("not user writable"),
            Predicate::ObjectSafe(_) => panic!("not user writable"),
904
            Predicate::ClosureKind(..) => panic!("not user writable"),
A
fixes  
Ariel Ben-Yehuda 已提交
905
            Predicate::Rfc1592(..) => panic!("not user writable"),
906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962
        }
    }
}

impl<'a> Clean<WherePredicate> for ty::TraitPredicate<'a> {
    fn clean(&self, cx: &DocContext) -> WherePredicate {
        WherePredicate::BoundPredicate {
            ty: self.trait_ref.substs.self_ty().clean(cx).unwrap(),
            bounds: vec![self.trait_ref.clean(cx)]
        }
    }
}

impl<'tcx> Clean<WherePredicate> for ty::EquatePredicate<'tcx> {
    fn clean(&self, cx: &DocContext) -> WherePredicate {
        let ty::EquatePredicate(ref lhs, ref rhs) = *self;
        WherePredicate::EqPredicate {
            lhs: lhs.clean(cx),
            rhs: rhs.clean(cx)
        }
    }
}

impl Clean<WherePredicate> for ty::OutlivesPredicate<ty::Region, ty::Region> {
    fn clean(&self, cx: &DocContext) -> WherePredicate {
        let ty::OutlivesPredicate(ref a, ref b) = *self;
        WherePredicate::RegionPredicate {
            lifetime: a.clean(cx).unwrap(),
            bounds: vec![b.clean(cx).unwrap()]
        }
    }
}

impl<'tcx> Clean<WherePredicate> for ty::OutlivesPredicate<ty::Ty<'tcx>, ty::Region> {
    fn clean(&self, cx: &DocContext) -> WherePredicate {
        let ty::OutlivesPredicate(ref ty, ref lt) = *self;

        WherePredicate::BoundPredicate {
            ty: ty.clean(cx),
            bounds: vec![TyParamBound::RegionBound(lt.clean(cx).unwrap())]
        }
    }
}

impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
    fn clean(&self, cx: &DocContext) -> WherePredicate {
        WherePredicate::EqPredicate {
            lhs: self.projection_ty.clean(cx),
            rhs: self.ty.clean(cx)
        }
    }
}

impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
    fn clean(&self, cx: &DocContext) -> Type {
        let trait_ = match self.trait_ref.clean(cx) {
            TyParamBound::TraitBound(t, _) => t.trait_,
963 964 965
            TyParamBound::RegionBound(_) => {
                panic!("cleaning a trait got a region")
            }
966 967 968 969 970 971 972 973 974
        };
        Type::QPath {
            name: self.item_name.clean(cx),
            self_type: box self.trait_ref.self_ty().clean(cx),
            trait_: box trait_
        }
    }
}

975
// maybe use a Generic enum and use Vec<Generic>?
J
Jorge Aparicio 已提交
976
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
977
pub struct Generics {
978 979
    pub lifetimes: Vec<Lifetime>,
    pub type_params: Vec<TyParam>,
980
    pub where_predicates: Vec<WherePredicate>
981
}
C
Corey Richardson 已提交
982

983
impl Clean<Generics> for hir::Generics {
984
    fn clean(&self, cx: &DocContext) -> Generics {
C
Corey Richardson 已提交
985
        Generics {
986 987
            lifetimes: self.lifetimes.clean(cx),
            type_params: self.ty_params.clean(cx),
988
            where_predicates: self.where_clause.predicates.clean(cx)
C
Corey Richardson 已提交
989 990 991 992
        }
    }
}

993 994 995
impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
                                    &'a ty::GenericPredicates<'tcx>,
                                    subst::ParamSpace) {
996
    fn clean(&self, cx: &DocContext) -> Generics {
997 998
        use self::WherePredicate as WP;

999 1000
        let (gens, preds, space) = *self;

1001 1002 1003
        // Bounds in the type_params and lifetimes fields are repeated in the
        // predicates field (see rustc_typeck::collect::ty_generics), so remove
        // them.
1004
        let stripped_typarams = gens.types.get_slice(space).iter().map(|tp| {
1005
            tp.clean(cx)
1006 1007 1008 1009 1010 1011 1012
        }).collect::<Vec<_>>();
        let stripped_lifetimes = gens.regions.get_slice(space).iter().map(|rp| {
            let mut srp = rp.clone();
            srp.bounds = Vec::new();
            srp.clean(cx)
        }).collect::<Vec<_>>();

1013 1014
        let mut where_predicates = preds.predicates.get_slice(space)
                                                   .to_vec().clean(cx);
1015

1016
        // Type parameters and have a Sized bound by default unless removed with
1017 1018
        // ?Sized.  Scan through the predicates and mark any type parameter with
        // a Sized bound, removing the bounds as we find them.
1019 1020
        //
        // Note that associated types also have a sized bound by default, but we
1021
        // don't actually know the set of associated types right here so that's
1022
        // handled in cleaning associated types
1023
        let mut sized_params = HashSet::new();
1024 1025 1026 1027 1028 1029 1030 1031 1032
        where_predicates.retain(|pred| {
            match *pred {
                WP::BoundPredicate { ty: Generic(ref g), ref bounds } => {
                    if bounds.iter().any(|b| b.is_sized_bound(cx)) {
                        sized_params.insert(g.clone());
                        false
                    } else {
                        true
                    }
1033
                }
1034
                _ => true,
1035
            }
1036
        });
1037

1038
        // Run through the type parameters again and insert a ?Sized
1039
        // unbound for any we didn't find to be Sized.
1040
        for tp in &stripped_typarams {
1041 1042 1043
            if !sized_params.contains(&tp.name) {
                where_predicates.push(WP::BoundPredicate {
                    ty: Type::Generic(tp.name.clone()),
1044
                    bounds: vec![TyParamBound::maybe_sized(cx)],
1045 1046 1047 1048 1049 1050 1051 1052
                })
            }
        }

        // It would be nice to collect all of the bounds on a type and recombine
        // them if possible, to avoid e.g. `where T: Foo, T: Bar, T: Sized, T: 'a`
        // and instead see `where T: Foo + Bar + Sized + 'a`

1053
        Generics {
1054
            type_params: simplify::ty_params(stripped_typarams),
1055
            lifetimes: stripped_lifetimes,
1056
            where_predicates: simplify::where_clauses(cx, where_predicates),
1057 1058 1059 1060
        }
    }
}

J
Jorge Aparicio 已提交
1061
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1062
pub struct Method {
1063
    pub generics: Generics,
1064 1065
    pub unsafety: hir::Unsafety,
    pub constness: hir::Constness,
1066
    pub decl: FnDecl,
1067
    pub abi: Abi,
C
Corey Richardson 已提交
1068 1069
}

1070
impl Clean<Method> for hir::MethodSig {
1071
    fn clean(&self, cx: &DocContext) -> Method {
1072
        let decl = FnDecl {
1073
            inputs: Arguments {
1074
                values: self.decl.inputs.clean(cx),
1075
            },
1076
            output: self.decl.output.clean(cx),
1077
            variadic: false,
1078
            attrs: Vec::new()
1079
        };
1080
        Method {
1081
            generics: self.generics.clean(cx),
1082 1083
            unsafety: self.unsafety,
            constness: self.constness,
1084
            decl: decl,
1085
            abi: self.abi
C
Corey Richardson 已提交
1086 1087 1088 1089
        }
    }
}

J
Jorge Aparicio 已提交
1090
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1091
pub struct TyMethod {
1092
    pub unsafety: hir::Unsafety,
1093 1094
    pub decl: FnDecl,
    pub generics: Generics,
1095
    pub abi: Abi,
C
Corey Richardson 已提交
1096 1097
}

1098
impl Clean<TyMethod> for hir::MethodSig {
1099
    fn clean(&self, cx: &DocContext) -> TyMethod {
1100
        let decl = FnDecl {
1101
            inputs: Arguments {
1102
                values: self.decl.inputs.clean(cx),
1103
            },
1104
            output: self.decl.output.clean(cx),
1105
            variadic: false,
1106
            attrs: Vec::new()
1107
        };
1108 1109 1110 1111 1112
        TyMethod {
            unsafety: self.unsafety.clone(),
            decl: decl,
            generics: self.generics.clean(cx),
            abi: self.abi
C
Corey Richardson 已提交
1113 1114 1115 1116
        }
    }
}

J
Jorge Aparicio 已提交
1117
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1118
pub struct Function {
1119 1120
    pub decl: FnDecl,
    pub generics: Generics,
1121 1122
    pub unsafety: hir::Unsafety,
    pub constness: hir::Constness,
1123
    pub abi: Abi,
C
Corey Richardson 已提交
1124 1125 1126
}

impl Clean<Item> for doctree::Function {
1127
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1128
        Item {
1129 1130 1131 1132 1133
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
1134
            deprecation: self.depr.clean(cx),
1135
            def_id: cx.map.local_def_id(self.id),
C
Corey Richardson 已提交
1136
            inner: FunctionItem(Function {
1137 1138
                decl: self.decl.clean(cx),
                generics: self.generics.clean(cx),
N
Niko Matsakis 已提交
1139
                unsafety: self.unsafety,
1140
                constness: self.constness,
1141
                abi: self.abi,
C
Corey Richardson 已提交
1142 1143 1144 1145 1146
            }),
        }
    }
}

J
Jorge Aparicio 已提交
1147
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
1148
pub struct FnDecl {
1149
    pub inputs: Arguments,
1150
    pub output: FunctionRetTy,
1151
    pub variadic: bool,
1152 1153
    pub attrs: Vec<Attribute>,
}
C
Corey Richardson 已提交
1154

1155 1156 1157 1158 1159 1160
impl FnDecl {
    pub fn has_self(&self) -> bool {
        return self.inputs.values.len() > 0 && self.inputs.values[0].name == "self";
    }
}

J
Jorge Aparicio 已提交
1161
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1162
pub struct Arguments {
1163
    pub values: Vec<Argument>,
1164 1165
}

1166
impl Clean<FnDecl> for hir::FnDecl {
1167
    fn clean(&self, cx: &DocContext) -> FnDecl {
C
Corey Richardson 已提交
1168
        FnDecl {
1169
            inputs: Arguments {
1170
                values: self.inputs.clean(cx),
1171
            },
1172
            output: self.output.clean(cx),
1173
            variadic: self.variadic,
1174
            attrs: Vec::new()
C
Corey Richardson 已提交
1175 1176 1177 1178
        }
    }
}

1179
impl<'tcx> Clean<Type> for ty::FnOutput<'tcx> {
J
Jakub Bukaj 已提交
1180 1181 1182 1183 1184 1185 1186 1187
    fn clean(&self, cx: &DocContext) -> Type {
        match *self {
            ty::FnConverging(ty) => ty.clean(cx),
            ty::FnDiverging => Bottom
        }
    }
}

N
Niko Matsakis 已提交
1188
impl<'a, 'tcx> Clean<FnDecl> for (DefId, &'a ty::PolyFnSig<'tcx>) {
1189
    fn clean(&self, cx: &DocContext) -> FnDecl {
1190
        let (did, sig) = *self;
M
mitaa 已提交
1191
        let mut names = if cx.map.as_local_node_id(did).is_some() {
1192
            vec![].into_iter()
1193
        } else {
A
Ariel Ben-Yehuda 已提交
1194
            cx.tcx().sess.cstore.method_arg_names(did).into_iter()
1195
        }.peekable();
1196
        FnDecl {
1197
            output: Return(sig.0.output.clean(cx)),
1198
            attrs: Vec::new(),
1199
            variadic: sig.0.variadic,
1200
            inputs: Arguments {
1201
                values: sig.0.inputs.iter().map(|t| {
1202
                    Argument {
1203
                        type_: t.clean(cx),
1204
                        id: 0,
1205
                        name: names.next().unwrap_or("".to_string()),
1206 1207 1208 1209 1210 1211 1212
                    }
                }).collect(),
            },
        }
    }
}

J
Jorge Aparicio 已提交
1213
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
1214
pub struct Argument {
1215
    pub type_: Type,
1216
    pub name: String,
1217
    pub id: ast::NodeId,
C
Corey Richardson 已提交
1218 1219
}

1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
pub enum SelfTy {
    SelfValue,
    SelfBorrowed(Option<Lifetime>, Mutability),
    SelfExplicit(Type),
}

impl Argument {
    pub fn to_self(&self) -> Option<SelfTy> {
        if self.name == "self" {
            match self.type_ {
                Infer => Some(SelfValue),
                BorrowedRef{ref lifetime, mutability, ref type_} if **type_ == Infer => {
                    Some(SelfBorrowed(lifetime.clone(), mutability))
                }
                _ => Some(SelfExplicit(self.type_.clone()))
            }
        } else {
            None
        }
    }
}

1243
impl Clean<Argument> for hir::Arg {
1244
    fn clean(&self, cx: &DocContext) -> Argument {
C
Corey Richardson 已提交
1245
        Argument {
1246
            name: name_from_pat(&*self.pat),
1247
            type_: (self.ty.clean(cx)),
C
Corey Richardson 已提交
1248 1249 1250 1251 1252
            id: self.id
        }
    }
}

J
Jorge Aparicio 已提交
1253
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1254 1255
pub enum FunctionRetTy {
    Return(Type),
1256
    DefaultReturn,
1257
    NoReturn
C
Corey Richardson 已提交
1258 1259
}

1260
impl Clean<FunctionRetTy> for hir::FunctionRetTy {
1261
    fn clean(&self, cx: &DocContext) -> FunctionRetTy {
C
Corey Richardson 已提交
1262
        match *self {
1263 1264 1265
            hir::Return(ref typ) => Return(typ.clean(cx)),
            hir::DefaultReturn(..) => DefaultReturn,
            hir::NoReturn(..) => NoReturn
C
Corey Richardson 已提交
1266 1267 1268 1269
        }
    }
}

J
Jorge Aparicio 已提交
1270
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1271
pub struct Trait {
1272
    pub unsafety: hir::Unsafety,
1273
    pub items: Vec<Item>,
1274
    pub generics: Generics,
1275
    pub bounds: Vec<TyParamBound>,
C
Corey Richardson 已提交
1276 1277 1278
}

impl Clean<Item> for doctree::Trait {
1279
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1280
        Item {
1281 1282 1283
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
1284
            def_id: cx.map.local_def_id(self.id),
1285 1286
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
1287
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
1288
            inner: TraitItem(Trait {
1289
                unsafety: self.unsafety,
1290 1291 1292
                items: self.items.clean(cx),
                generics: self.generics.clean(cx),
                bounds: self.bounds.clean(cx),
C
Corey Richardson 已提交
1293 1294 1295 1296 1297
            }),
        }
    }
}

1298
impl Clean<Type> for hir::TraitRef {
1299
    fn clean(&self, cx: &DocContext) -> Type {
N
Niko Matsakis 已提交
1300
        resolve_type(cx, self.path.clean(cx), self.ref_id)
C
Corey Richardson 已提交
1301 1302 1303
    }
}

1304
impl Clean<PolyTrait> for hir::PolyTraitRef {
1305 1306 1307 1308 1309
    fn clean(&self, cx: &DocContext) -> PolyTrait {
        PolyTrait {
            trait_: self.trait_ref.clean(cx),
            lifetimes: self.bound_lifetimes.clean(cx)
        }
N
Niko Matsakis 已提交
1310 1311 1312
    }
}

1313
impl Clean<Item> for hir::TraitItem {
1314 1315
    fn clean(&self, cx: &DocContext) -> Item {
        let inner = match self.node {
1316
            hir::ConstTraitItem(ref ty, ref default) => {
1317
                AssociatedConstItem(ty.clean(cx),
1318
                                    default.as_ref().map(|e| pprust::expr_to_string(&e)))
1319
            }
1320
            hir::MethodTraitItem(ref sig, Some(_)) => {
1321 1322
                MethodItem(sig.clean(cx))
            }
1323
            hir::MethodTraitItem(ref sig, None) => {
1324 1325
                TyMethodItem(sig.clean(cx))
            }
1326
            hir::TypeTraitItem(ref bounds, ref default) => {
1327 1328 1329 1330
                AssociatedTypeItem(bounds.clean(cx), default.clean(cx))
            }
        };
        Item {
V
Vadim Petrochenkov 已提交
1331
            name: Some(self.name.clean(cx)),
1332 1333
            attrs: self.attrs.clean(cx),
            source: self.span.clean(cx),
1334
            def_id: cx.map.local_def_id(self.id),
1335
            visibility: None,
1336
            stability: get_stability(cx, cx.map.local_def_id(self.id)),
1337
            deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
1338
            inner: inner
1339 1340 1341 1342
        }
    }
}

1343
impl Clean<Item> for hir::ImplItem {
1344 1345
    fn clean(&self, cx: &DocContext) -> Item {
        let inner = match self.node {
1346
            hir::ImplItemKind::Const(ref ty, ref expr) => {
1347
                AssociatedConstItem(ty.clean(cx),
1348
                                    Some(pprust::expr_to_string(expr)))
1349
            }
1350
            hir::ImplItemKind::Method(ref sig, _) => {
1351 1352
                MethodItem(sig.clean(cx))
            }
1353
            hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef {
1354 1355 1356 1357 1358 1359
                type_: ty.clean(cx),
                generics: Generics {
                    lifetimes: Vec::new(),
                    type_params: Vec::new(),
                    where_predicates: Vec::new()
                },
1360
            }, true),
1361 1362
        };
        Item {
V
Vadim Petrochenkov 已提交
1363
            name: Some(self.name.clean(cx)),
1364 1365
            source: self.span.clean(cx),
            attrs: self.attrs.clean(cx),
1366
            def_id: cx.map.local_def_id(self.id),
1367
            visibility: self.vis.clean(cx),
1368
            stability: get_stability(cx, cx.map.local_def_id(self.id)),
1369
            deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
1370
            inner: inner
C
Corey Richardson 已提交
1371 1372 1373 1374
        }
    }
}

1375
impl<'tcx> Clean<Item> for ty::Method<'tcx> {
1376
    fn clean(&self, cx: &DocContext) -> Item {
1377 1378
        let generics = (&self.generics, &self.predicates,
                        subst::FnSpace).clean(cx);
1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391
        let mut decl = (self.def_id, &self.fty.sig).clean(cx);
        match self.explicit_self {
            ty::ExplicitSelfCategory::ByValue => {
                decl.inputs.values[0].type_ = Infer;
            }
            ty::ExplicitSelfCategory::ByReference(..) => {
                match decl.inputs.values[0].type_ {
                    BorrowedRef{ref mut type_, ..} => **type_ = Infer,
                    _ => unreachable!(),
                }
            }
            _ => {}
        }
1392 1393 1394
        let provided = match self.container {
            ty::ImplContainer(..) => false,
            ty::TraitContainer(did) => {
1395
                cx.tcx().provided_trait_methods(did).iter().any(|m| {
1396 1397 1398 1399 1400 1401 1402 1403 1404
                    m.def_id == self.def_id
                })
            }
        };
        let inner = if provided {
            MethodItem(Method {
                unsafety: self.fty.unsafety,
                generics: generics,
                decl: decl,
N
Niko Matsakis 已提交
1405 1406 1407
                abi: self.fty.abi,

                // trait methods canot (currently, at least) be const
1408
                constness: hir::Constness::NotConst,
1409 1410 1411 1412 1413 1414
            })
        } else {
            TyMethodItem(TyMethod {
                unsafety: self.fty.unsafety,
                generics: generics,
                decl: decl,
N
Niko Matsakis 已提交
1415
                abi: self.fty.abi,
1416 1417 1418
            })
        };

1419
        Item {
1420
            name: Some(self.name.clean(cx)),
J
Jeffrey Seyfried 已提交
1421
            visibility: Some(Inherited),
1422
            stability: get_stability(cx, self.def_id),
1423
            deprecation: get_deprecation(cx, self.def_id),
1424
            def_id: self.def_id,
1425
            attrs: inline::load_attrs(cx, cx.tcx(), self.def_id),
1426
            source: Span::empty(),
1427
            inner: inner,
1428
        }
1429 1430 1431
    }
}

1432
impl<'tcx> Clean<Item> for ty::ImplOrTraitItem<'tcx> {
1433
    fn clean(&self, cx: &DocContext) -> Item {
1434
        match *self {
1435
            ty::ConstTraitItem(ref cti) => cti.clean(cx),
1436
            ty::MethodTraitItem(ref mti) => mti.clean(cx),
1437
            ty::TypeTraitItem(ref tti) => tti.clean(cx),
1438 1439 1440 1441
        }
    }
}

1442
/// A trait reference, which may have higher ranked lifetimes.
J
Jorge Aparicio 已提交
1443
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1444 1445 1446 1447 1448
pub struct PolyTrait {
    pub trait_: Type,
    pub lifetimes: Vec<Lifetime>
}

C
Corey Richardson 已提交
1449
/// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
1450
/// type out of the AST/TyCtxt given one of these, if more information is needed. Most importantly
C
Corey Richardson 已提交
1451
/// it does not preserve mutability or boxes.
J
Jorge Aparicio 已提交
1452
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
1453
pub enum Type {
1454
    /// structs/enums/traits (most that'd be an hir::TyPath)
1455
    ResolvedPath {
S
Steven Fackler 已提交
1456 1457
        path: Path,
        typarams: Option<Vec<TyParamBound>>,
N
Niko Matsakis 已提交
1458
        did: DefId,
1459 1460
        /// true if is a `T::Name` path for associated types
        is_generic: bool,
1461
    },
1462 1463 1464
    /// For parameterized types, so the consumer of the JSON don't go
    /// looking for types which don't exist anywhere.
    Generic(String),
1465
    /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
1466
    /// arrays, slices, and tuples.
1467
    Primitive(PrimitiveType),
C
Corey Richardson 已提交
1468
    /// extern "ABI" fn
1469
    BareFunction(Box<BareFunctionDecl>),
1470
    Tuple(Vec<Type>),
1471
    Vector(Box<Type>),
1472
    FixedVector(Box<Type>, String),
1473
    /// aka TyBot
C
Corey Richardson 已提交
1474
    Bottom,
1475 1476
    Unique(Box<Type>),
    RawPointer(Mutability, Box<Type>),
1477
    BorrowedRef {
S
Steven Fackler 已提交
1478 1479 1480
        lifetime: Option<Lifetime>,
        mutability: Mutability,
        type_: Box<Type>,
1481
    },
1482 1483

    // <Type as Trait>::Name
T
Tom Jakubowski 已提交
1484 1485 1486 1487 1488
    QPath {
        name: String,
        self_type: Box<Type>,
        trait_: Box<Type>
    },
1489 1490 1491 1492 1493 1494

    // _
    Infer,

    // for<'a> Foo(&'a)
    PolyTraitRef(Vec<TyParamBound>),
C
Corey Richardson 已提交
1495 1496
}

J
Jorge Aparicio 已提交
1497
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
1498
pub enum PrimitiveType {
1499 1500
    Isize, I8, I16, I32, I64,
    Usize, U8, U16, U32, U64,
1501
    F32, F64,
1502 1503 1504 1505
    Char,
    Bool,
    Str,
    Slice,
1506
    Array,
1507
    PrimitiveTuple,
1508
    PrimitiveRawPointer,
1509 1510
}

J
Jorge Aparicio 已提交
1511
#[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
1512 1513 1514
pub enum TypeKind {
    TypeEnum,
    TypeFunction,
1515
    TypeModule,
1516
    TypeConst,
1517 1518 1519 1520
    TypeStatic,
    TypeStruct,
    TypeTrait,
    TypeVariant,
1521
    TypeTypedef,
1522 1523
}

1524 1525 1526 1527 1528 1529 1530 1531 1532 1533
pub trait GetDefId {
    fn def_id(&self) -> Option<DefId>;
}

impl<T: GetDefId> GetDefId for Option<T> {
    fn def_id(&self) -> Option<DefId> {
        self.as_ref().and_then(|d| d.def_id())
    }
}

1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546
impl Type {
    pub fn primitive_type(&self) -> Option<PrimitiveType> {
        match *self {
            Primitive(p) | BorrowedRef { type_: box Primitive(p), ..} => Some(p),
            Vector(..) | BorrowedRef{ type_: box Vector(..), ..  } => Some(Slice),
            FixedVector(..) | BorrowedRef { type_: box FixedVector(..), .. } => {
                Some(Array)
            }
            Tuple(..) => Some(PrimitiveTuple),
            RawPointer(..) => Some(PrimitiveRawPointer),
            _ => None,
        }
    }
1547

1548 1549 1550 1551 1552 1553
    pub fn is_generic(&self) -> bool {
        match *self {
            ResolvedPath { is_generic, .. } => is_generic,
            _ => false,
        }
    }
1554
}
1555

1556
impl GetDefId for Type {
1557 1558 1559 1560 1561 1562
    fn def_id(&self) -> Option<DefId> {
        match *self {
            ResolvedPath { did, .. } => Some(did),
            _ => None,
        }
    }
1563 1564
}

1565 1566
impl PrimitiveType {
    fn from_str(s: &str) -> Option<PrimitiveType> {
1567
        match s {
1568
            "isize" => Some(Isize),
1569 1570 1571 1572
            "i8" => Some(I8),
            "i16" => Some(I16),
            "i32" => Some(I32),
            "i64" => Some(I64),
1573
            "usize" => Some(Usize),
1574 1575 1576 1577 1578 1579 1580 1581 1582
            "u8" => Some(U8),
            "u16" => Some(U16),
            "u32" => Some(U32),
            "u64" => Some(U64),
            "bool" => Some(Bool),
            "char" => Some(Char),
            "str" => Some(Str),
            "f32" => Some(F32),
            "f64" => Some(F64),
1583
            "array" => Some(Array),
1584 1585
            "slice" => Some(Slice),
            "tuple" => Some(PrimitiveTuple),
1586
            "pointer" => Some(PrimitiveRawPointer),
1587 1588 1589 1590
            _ => None,
        }
    }

1591
    fn find(attrs: &[Attribute]) -> Option<PrimitiveType> {
1592
        for attr in attrs.list("doc") {
M
mitaa 已提交
1593 1594 1595 1596 1597
            if let NameValue(ref k, ref v) = *attr {
                if "primitive" == *k {
                    if let ret@Some(..) = PrimitiveType::from_str(v) {
                        return ret;
                    }
1598 1599 1600
                }
            }
        }
M
mitaa 已提交
1601
        None
1602 1603
    }

1604
    pub fn to_string(&self) -> &'static str {
1605
        match *self {
1606
            Isize => "isize",
1607 1608 1609 1610
            I8 => "i8",
            I16 => "i16",
            I32 => "i32",
            I64 => "i64",
1611
            Usize => "usize",
1612 1613 1614 1615 1616 1617 1618 1619 1620
            U8 => "u8",
            U16 => "u16",
            U32 => "u32",
            U64 => "u64",
            F32 => "f32",
            F64 => "f64",
            Str => "str",
            Bool => "bool",
            Char => "char",
1621
            Array => "array",
1622 1623
            Slice => "slice",
            PrimitiveTuple => "tuple",
1624
            PrimitiveRawPointer => "pointer",
1625 1626 1627 1628
        }
    }

    pub fn to_url_str(&self) -> &'static str {
1629
        self.to_string()
1630 1631 1632 1633 1634
    }

    /// Creates a rustdoc-specific node id for primitive types.
    ///
    /// These node ids are generally never used by the AST itself.
1635 1636 1637
    pub fn to_def_index(&self) -> DefIndex {
        let x = u32::MAX - 1 - (*self as u32);
        DefIndex::new(x as usize)
1638 1639 1640
    }
}

1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677

// Poor man's type parameter substitution at HIR level.
// Used to replace private type aliases in public signatures with their aliased types.
struct SubstAlias<'a, 'tcx: 'a> {
    tcx: &'a ty::TyCtxt<'a, 'tcx, 'tcx>,
    // Table type parameter definition -> substituted type
    ty_substs: HashMap<Def, hir::Ty>,
    // Table node id of lifetime parameter definition -> substituted lifetime
    lt_substs: HashMap<ast::NodeId, hir::Lifetime>,
}

impl<'a, 'tcx: 'a, 'b: 'tcx> Folder for SubstAlias<'a, 'tcx> {
    fn fold_ty(&mut self, ty: P<hir::Ty>) -> P<hir::Ty> {
        if let hir::TyPath(..) = ty.node {
            let def = self.tcx.expect_def(ty.id);
            if let Some(new_ty) = self.ty_substs.get(&def).cloned() {
                return P(new_ty);
            }
        }
        hir::fold::noop_fold_ty(ty, self)
    }
    fn fold_lifetime(&mut self, lt: hir::Lifetime) -> hir::Lifetime {
        let def = self.tcx.named_region_map.defs.get(&lt.id).cloned();
        match def {
            Some(DefEarlyBoundRegion(_, _, node_id)) |
            Some(DefLateBoundRegion(_, node_id)) |
            Some(DefFreeRegion(_, node_id)) => {
                if let Some(lt) = self.lt_substs.get(&node_id).cloned() {
                    return lt;
                }
            }
            _ => {}
        }
        hir::fold::noop_fold_lifetime(lt, self)
    }
}

1678
impl Clean<Type> for hir::Ty {
1679
    fn clean(&self, cx: &DocContext) -> Type {
1680
        use rustc::hir::*;
1681
        match self.node {
1682
            TyPtr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
1683
            TyRptr(ref l, ref m) =>
1684 1685
                BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx),
                             type_: box m.ty.clean(cx)},
1686
            TyVec(ref ty) => Vector(box ty.clean(cx)),
1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705
            TyFixedLengthVec(ref ty, ref e) => {
                let n = if let Some(tcx) = cx.tcx_opt() {
                    use rustc_const_math::{ConstInt, ConstUsize};
                    use rustc_const_eval::eval_const_expr;
                    use rustc::middle::const_val::ConstVal;
                    match eval_const_expr(tcx, e) {
                        ConstVal::Integral(ConstInt::Usize(u)) => match u {
                            ConstUsize::Us16(u) => u.to_string(),
                            ConstUsize::Us32(u) => u.to_string(),
                            ConstUsize::Us64(u) => u.to_string(),
                        },
                        // after type checking this can't fail
                        _ => unreachable!(),
                    }
                } else {
                    pprust::expr_to_string(e)
                };
                FixedVector(box ty.clean(cx), n)
            },
1706
            TyTup(ref tys) => Tuple(tys.clean(cx)),
1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746
            TyPath(None, ref path) => {
                if let Some(tcx) = cx.tcx_opt() {
                    // Substitute private type aliases
                    let def = tcx.expect_def(self.id);
                    if let Def::TyAlias(def_id) = def {
                        if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
                            if !cx.access_levels.borrow().is_exported(def_id) {
                                let item = tcx.map.expect_item(node_id);
                                if let hir::ItemTy(ref ty, ref generics) = item.node {
                                    let provided_params = &path.segments.last().unwrap().parameters;
                                    let mut ty_substs = HashMap::new();
                                    let mut lt_substs = HashMap::new();
                                    for (i, ty_param) in generics.ty_params.iter().enumerate() {
                                        let ty_param_def = tcx.expect_def(ty_param.id);
                                        if let Some(ty) = provided_params.types().get(i).cloned()
                                                                                        .cloned() {
                                            ty_substs.insert(ty_param_def, ty.unwrap());
                                        } else if let Some(default) = ty_param.default.clone() {
                                            ty_substs.insert(ty_param_def, default.unwrap());
                                        }
                                    }
                                    for (i, lt_param) in generics.lifetimes.iter().enumerate() {
                                        if let Some(lt) = provided_params.lifetimes().get(i)
                                                                                     .cloned()
                                                                                     .cloned() {
                                            lt_substs.insert(lt_param.lifetime.id, lt);
                                        }
                                    }
                                    let mut subst_alias = SubstAlias {
                                        tcx: &tcx,
                                        ty_substs: ty_substs,
                                        lt_substs: lt_substs
                                    };
                                    return subst_alias.fold_ty(ty.clone()).clean(cx);
                                }
                            }
                        }
                    }
                }
                resolve_type(cx, path.clean(cx), self.id)
N
Niko Matsakis 已提交
1747
            }
1748
            TyPath(Some(ref qself), ref p) => {
1749 1750 1751 1752 1753 1754 1755
                let mut segments: Vec<_> = p.segments.clone().into();
                segments.pop();
                let trait_path = hir::Path {
                    span: p.span,
                    global: p.global,
                    segments: segments.into(),
                };
1756
                Type::QPath {
V
Vadim Petrochenkov 已提交
1757
                    name: p.segments.last().unwrap().name.clean(cx),
1758
                    self_type: box qself.ty.clean(cx),
1759
                    trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
1760 1761
                }
            }
N
Niko Matsakis 已提交
1762 1763 1764
            TyObjectSum(ref lhs, ref bounds) => {
                let lhs_ty = lhs.clean(cx);
                match lhs_ty {
1765 1766 1767 1768 1769 1770 1771
                    ResolvedPath { path, typarams: None, did, is_generic } => {
                        ResolvedPath {
                            path: path,
                            typarams: Some(bounds.clean(cx)),
                            did: did,
                            is_generic: is_generic,
                        }
N
Niko Matsakis 已提交
1772 1773 1774 1775 1776
                    }
                    _ => {
                        lhs_ty // shouldn't happen
                    }
                }
1777
            }
1778
            TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
M
mitaa 已提交
1779 1780 1781
            TyPolyTraitRef(ref bounds) => PolyTraitRef(bounds.clean(cx)),
            TyInfer => Infer,
            TyTypeof(..) => panic!("Unimplemented type {:?}", self.node),
1782
        }
C
Corey Richardson 已提交
1783 1784 1785
    }
}

1786
impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
1787
    fn clean(&self, cx: &DocContext) -> Type {
1788
        match self.sty {
1789 1790
            ty::TyBool => Primitive(Bool),
            ty::TyChar => Primitive(Char),
1791 1792 1793 1794 1795 1796 1797 1798 1799 1800
            ty::TyInt(ast::IntTy::Is) => Primitive(Isize),
            ty::TyInt(ast::IntTy::I8) => Primitive(I8),
            ty::TyInt(ast::IntTy::I16) => Primitive(I16),
            ty::TyInt(ast::IntTy::I32) => Primitive(I32),
            ty::TyInt(ast::IntTy::I64) => Primitive(I64),
            ty::TyUint(ast::UintTy::Us) => Primitive(Usize),
            ty::TyUint(ast::UintTy::U8) => Primitive(U8),
            ty::TyUint(ast::UintTy::U16) => Primitive(U16),
            ty::TyUint(ast::UintTy::U32) => Primitive(U32),
            ty::TyUint(ast::UintTy::U64) => Primitive(U64),
1801 1802
            ty::TyFloat(ast::FloatTy::F32) => Primitive(F32),
            ty::TyFloat(ast::FloatTy::F64) => Primitive(F64),
1803 1804
            ty::TyStr => Primitive(Str),
            ty::TyBox(t) => {
1805
                let box_did = cx.tcx_opt().and_then(|tcx| {
A
Alex Crichton 已提交
1806 1807
                    tcx.lang_items.owned_box()
                });
1808
                lang_struct(cx, box_did, t, "Box", Unique)
A
Alex Crichton 已提交
1809
            }
1810 1811 1812
            ty::TySlice(ty) => Vector(box ty.clean(cx)),
            ty::TyArray(ty, i) => FixedVector(box ty.clean(cx),
                                              format!("{}", i)),
1813 1814
            ty::TyRawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
            ty::TyRef(r, mt) => BorrowedRef {
1815 1816 1817
                lifetime: r.clean(cx),
                mutability: mt.mutbl.clean(cx),
                type_: box mt.ty.clean(cx),
1818
            },
1819
            ty::TyFnDef(_, _, ref fty) |
1820
            ty::TyFnPtr(ref fty) => BareFunction(box BareFunctionDecl {
N
Niko Matsakis 已提交
1821
                unsafety: fty.unsafety,
1822
                generics: Generics {
1823 1824 1825
                    lifetimes: Vec::new(),
                    type_params: Vec::new(),
                    where_predicates: Vec::new()
1826
                },
1827
                decl: (cx.map.local_def_id(0), &fty.sig).clean(cx),
1828
                abi: fty.abi,
1829
            }),
1830 1831 1832
            ty::TyStruct(def, substs) |
            ty::TyEnum(def, substs) => {
                let did = def.did;
1833
                let kind = match self.sty {
1834
                    ty::TyStruct(..) => TypeStruct,
1835 1836
                    _ => TypeEnum,
                };
M
mitaa 已提交
1837 1838
                inline::record_extern_fqn(cx, did, kind);
                let path = external_path(cx, &cx.tcx().item_name(did).as_str(),
1839
                                         None, vec![], substs);
1840
                ResolvedPath {
1841
                    path: path,
1842 1843
                    typarams: None,
                    did: did,
1844
                    is_generic: false,
1845 1846
                }
            }
1847
            ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => {
1848
                let did = principal.def_id();
M
mitaa 已提交
1849
                inline::record_extern_fqn(cx, did, TypeTrait);
1850
                let (typarams, bindings) = bounds.clean(cx);
M
mitaa 已提交
1851
                let path = external_path(cx, &cx.tcx().item_name(did).as_str(),
1852
                                         Some(did), bindings, principal.substs());
1853 1854
                ResolvedPath {
                    path: path,
1855
                    typarams: Some(typarams),
1856
                    did: did,
1857
                    is_generic: false,
1858 1859
                }
            }
1860
            ty::TyTuple(ref t) => Tuple(t.clean(cx)),
1861

1862
            ty::TyProjection(ref data) => data.clean(cx),
1863

1864
            ty::TyParam(ref p) => Generic(p.name.to_string()),
1865

1866
            ty::TyClosure(..) => Tuple(vec![]), // FIXME(pcwalton)
1867

1868 1869
            ty::TyInfer(..) => panic!("TyInfer"),
            ty::TyError => panic!("TyError"),
1870 1871 1872 1873
        }
    }
}

1874
impl Clean<Item> for hir::StructField {
1875
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1876
        Item {
1877 1878
            name: Some(self.name).clean(cx),
            attrs: self.attrs.clean(cx),
1879
            source: self.span.clean(cx),
1880
            visibility: self.vis.clean(cx),
1881 1882 1883
            stability: get_stability(cx, cx.map.local_def_id(self.id)),
            deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
            def_id: cx.map.local_def_id(self.id),
1884
            inner: StructFieldItem(self.ty.clean(cx)),
C
Corey Richardson 已提交
1885 1886 1887 1888
        }
    }
}

A
Ariel Ben-Yehuda 已提交
1889
impl<'tcx> Clean<Item> for ty::FieldDefData<'tcx, 'static> {
1890
    fn clean(&self, cx: &DocContext) -> Item {
A
Ariel Ben-Yehuda 已提交
1891
        // FIXME: possible O(n^2)-ness! Not my fault.
1892
        let attr_map = cx.tcx().sess.cstore.crate_struct_field_attrs(self.did.krate);
1893
        Item {
1894 1895
            name: Some(self.name).clean(cx),
            attrs: attr_map.get(&self.did).unwrap_or(&Vec::new()).clean(cx),
1896
            source: Span::empty(),
1897
            visibility: self.vis.clean(cx),
1898
            stability: get_stability(cx, self.did),
1899
            deprecation: get_deprecation(cx, self.did),
1900
            def_id: self.did,
1901
            inner: StructFieldItem(self.unsubst_ty().clean(cx)),
1902 1903 1904 1905
        }
    }
}

J
Jeffrey Seyfried 已提交
1906 1907 1908 1909 1910
#[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug)]
pub enum Visibility {
    Public,
    Inherited,
}
C
Corey Richardson 已提交
1911

1912
impl Clean<Option<Visibility>> for hir::Visibility {
1913
    fn clean(&self, _: &DocContext) -> Option<Visibility> {
J
Jeffrey Seyfried 已提交
1914
        Some(if *self == hir::Visibility::Public { Public } else { Inherited })
1915 1916 1917 1918 1919
    }
}

impl Clean<Option<Visibility>> for ty::Visibility {
    fn clean(&self, _: &DocContext) -> Option<Visibility> {
J
Jeffrey Seyfried 已提交
1920
        Some(if *self == ty::Visibility::Public { Public } else { Inherited })
C
Corey Richardson 已提交
1921 1922 1923
    }
}

J
Jorge Aparicio 已提交
1924
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1925
pub struct Struct {
1926 1927 1928 1929
    pub struct_type: doctree::StructType,
    pub generics: Generics,
    pub fields: Vec<Item>,
    pub fields_stripped: bool,
C
Corey Richardson 已提交
1930 1931 1932
}

impl Clean<Item> for doctree::Struct {
1933
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1934
        Item {
1935 1936 1937
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
1938
            def_id: cx.map.local_def_id(self.id),
1939 1940
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
1941
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
1942 1943
            inner: StructItem(Struct {
                struct_type: self.struct_type,
1944 1945
                generics: self.generics.clean(cx),
                fields: self.fields.clean(cx),
S
Steven Fackler 已提交
1946
                fields_stripped: false,
C
Corey Richardson 已提交
1947 1948 1949 1950 1951
            }),
        }
    }
}

1952
/// This is a more limited form of the standard Struct, different in that
C
Corey Richardson 已提交
1953 1954
/// it lacks the things most items have (name, id, parameterization). Found
/// only as a variant in an enum.
J
Jorge Aparicio 已提交
1955
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1956
pub struct VariantStruct {
1957 1958 1959
    pub struct_type: doctree::StructType,
    pub fields: Vec<Item>,
    pub fields_stripped: bool,
C
Corey Richardson 已提交
1960 1961
}

1962
impl Clean<VariantStruct> for ::rustc::hir::VariantData {
1963
    fn clean(&self, cx: &DocContext) -> VariantStruct {
C
Corey Richardson 已提交
1964 1965
        VariantStruct {
            struct_type: doctree::struct_type_from_def(self),
1966
            fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
S
Steven Fackler 已提交
1967
            fields_stripped: false,
C
Corey Richardson 已提交
1968 1969 1970 1971
        }
    }
}

J
Jorge Aparicio 已提交
1972
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1973
pub struct Enum {
1974 1975 1976
    pub variants: Vec<Item>,
    pub generics: Generics,
    pub variants_stripped: bool,
C
Corey Richardson 已提交
1977 1978 1979
}

impl Clean<Item> for doctree::Enum {
1980
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1981
        Item {
1982 1983 1984
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
1985
            def_id: cx.map.local_def_id(self.id),
1986 1987
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
1988
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
1989
            inner: EnumItem(Enum {
1990 1991
                variants: self.variants.clean(cx),
                generics: self.generics.clean(cx),
S
Steven Fackler 已提交
1992
                variants_stripped: false,
C
Corey Richardson 已提交
1993 1994 1995 1996 1997
            }),
        }
    }
}

J
Jorge Aparicio 已提交
1998
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1999
pub struct Variant {
2000
    pub kind: VariantKind,
C
Corey Richardson 已提交
2001 2002 2003
}

impl Clean<Item> for doctree::Variant {
2004
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
2005
        Item {
2006 2007 2008
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2009
            visibility: None,
2010
            stability: self.stab.clean(cx),
2011
            deprecation: self.depr.clean(cx),
2012
            def_id: cx.map.local_def_id(self.def.id()),
C
Corey Richardson 已提交
2013
            inner: VariantItem(Variant {
2014
                kind: struct_def_to_variant_kind(&self.def, cx),
C
Corey Richardson 已提交
2015 2016 2017 2018 2019
            }),
        }
    }
}

A
Ariel Ben-Yehuda 已提交
2020
impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
2021
    fn clean(&self, cx: &DocContext) -> Item {
2022
        let kind = match self.kind {
2023 2024 2025 2026 2027
            ty::VariantKind::Unit => CLikeVariant,
            ty::VariantKind::Tuple => {
                TupleVariant(
                    self.fields.iter().map(|f| f.unsubst_ty().clean(cx)).collect()
                )
2028
            }
2029
            ty::VariantKind::Struct => {
2030 2031 2032
                StructVariant(VariantStruct {
                    struct_type: doctree::Plain,
                    fields_stripped: false,
2033
                    fields: self.fields.iter().map(|field| {
2034 2035
                        Item {
                            source: Span::empty(),
2036
                            name: Some(field.name.clean(cx)),
2037
                            attrs: cx.tcx().get_attrs(field.did).clean(cx),
2038
                            visibility: field.vis.clean(cx),
2039 2040 2041
                            def_id: field.did,
                            stability: get_stability(cx, field.did),
                            deprecation: get_deprecation(cx, field.did),
2042
                            inner: StructFieldItem(field.unsubst_ty().clean(cx))
2043 2044 2045 2046 2047 2048
                        }
                    }).collect()
                })
            }
        };
        Item {
2049
            name: Some(self.name.clean(cx)),
2050
            attrs: inline::load_attrs(cx, cx.tcx(), self.did),
2051
            source: Span::empty(),
J
Jeffrey Seyfried 已提交
2052
            visibility: Some(Inherited),
2053
            def_id: self.did,
2054
            inner: VariantItem(Variant { kind: kind }),
2055
            stability: get_stability(cx, self.did),
2056
            deprecation: get_deprecation(cx, self.did),
2057 2058 2059 2060
        }
    }
}

J
Jorge Aparicio 已提交
2061
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
2062 2063
pub enum VariantKind {
    CLikeVariant,
2064
    TupleVariant(Vec<Type>),
C
Corey Richardson 已提交
2065 2066 2067
    StructVariant(VariantStruct),
}

2068
fn struct_def_to_variant_kind(struct_def: &hir::VariantData, cx: &DocContext) -> VariantKind {
2069
    if struct_def.is_struct() {
2070
        StructVariant(struct_def.clean(cx))
2071
    } else if struct_def.is_unit() {
2072 2073
        CLikeVariant
    } else {
2074
        TupleVariant(struct_def.fields().iter().map(|x| x.ty.clean(cx)).collect())
2075 2076 2077
    }
}

J
Jorge Aparicio 已提交
2078
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2079
pub struct Span {
2080
    pub filename: String,
2081 2082 2083 2084
    pub loline: usize,
    pub locol: usize,
    pub hiline: usize,
    pub hicol: usize,
2085 2086
}

2087 2088 2089
impl Span {
    fn empty() -> Span {
        Span {
2090
            filename: "".to_string(),
2091 2092 2093 2094 2095 2096
            loline: 0, locol: 0,
            hiline: 0, hicol: 0,
        }
    }
}

2097
impl Clean<Span> for syntax_pos::Span {
2098
    fn clean(&self, cx: &DocContext) -> Span {
2099 2100 2101 2102
        if *self == DUMMY_SP {
            return Span::empty();
        }

2103
        let cm = cx.sess().codemap();
2104 2105 2106 2107
        let filename = cm.span_to_filename(*self);
        let lo = cm.lookup_char_pos(self.lo);
        let hi = cm.lookup_char_pos(self.hi);
        Span {
2108
            filename: filename.to_string(),
2109
            loline: lo.line,
2110
            locol: lo.col.to_usize(),
2111
            hiline: hi.line,
2112
            hicol: hi.col.to_usize(),
2113
        }
C
Corey Richardson 已提交
2114 2115 2116
    }
}

J
Jorge Aparicio 已提交
2117
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
2118
pub struct Path {
2119 2120
    pub global: bool,
    pub segments: Vec<PathSegment>,
C
Corey Richardson 已提交
2121 2122
}

2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136
impl Path {
    pub fn singleton(name: String) -> Path {
        Path {
            global: false,
            segments: vec![PathSegment {
                name: name,
                params: PathParameters::AngleBracketed {
                    lifetimes: Vec::new(),
                    types: Vec::new(),
                    bindings: Vec::new()
                }
            }]
        }
    }
2137 2138 2139 2140

    pub fn last_name(&self) -> String {
        self.segments.last().unwrap().name.clone()
    }
2141 2142
}

2143
impl Clean<Path> for hir::Path {
2144
    fn clean(&self, cx: &DocContext) -> Path {
C
Corey Richardson 已提交
2145
        Path {
2146
            global: self.global,
2147
            segments: self.segments.clean(cx),
2148 2149 2150 2151
        }
    }
}

J
Jorge Aparicio 已提交
2152
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2153 2154 2155 2156
pub enum PathParameters {
    AngleBracketed {
        lifetimes: Vec<Lifetime>,
        types: Vec<Type>,
2157
        bindings: Vec<TypeBinding>
2158 2159 2160 2161 2162
    },
    Parenthesized {
        inputs: Vec<Type>,
        output: Option<Type>
    }
2163 2164
}

2165
impl Clean<PathParameters> for hir::PathParameters {
2166 2167
    fn clean(&self, cx: &DocContext) -> PathParameters {
        match *self {
2168
            hir::AngleBracketedParameters(ref data) => {
2169 2170
                PathParameters::AngleBracketed {
                    lifetimes: data.lifetimes.clean(cx),
2171 2172
                    types: data.types.clean(cx),
                    bindings: data.bindings.clean(cx)
2173
                }
2174 2175
            }

2176
            hir::ParenthesizedParameters(ref data) => {
2177 2178 2179 2180
                PathParameters::Parenthesized {
                    inputs: data.inputs.clean(cx),
                    output: data.output.clean(cx)
                }
2181
            }
2182 2183 2184
        }
    }
}
2185

J
Jorge Aparicio 已提交
2186
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2187 2188 2189 2190 2191
pub struct PathSegment {
    pub name: String,
    pub params: PathParameters
}

2192
impl Clean<PathSegment> for hir::PathSegment {
2193
    fn clean(&self, cx: &DocContext) -> PathSegment {
2194
        PathSegment {
V
Vadim Petrochenkov 已提交
2195
            name: self.name.clean(cx),
2196
            params: self.parameters.clean(cx)
C
Corey Richardson 已提交
2197 2198 2199 2200
        }
    }
}

2201
fn path_to_string(p: &hir::Path) -> String {
2202
    let mut s = String::new();
C
Corey Richardson 已提交
2203
    let mut first = true;
V
Vadim Petrochenkov 已提交
2204
    for i in p.segments.iter().map(|x| x.name.as_str()) {
C
Corey Richardson 已提交
2205 2206 2207 2208 2209
        if !first || p.global {
            s.push_str("::");
        } else {
            first = false;
        }
G
GuillaumeGomez 已提交
2210
        s.push_str(&i);
C
Corey Richardson 已提交
2211
    }
2212
    s
C
Corey Richardson 已提交
2213 2214
}

2215
impl Clean<String> for ast::Name {
2216
    fn clean(&self, _: &DocContext) -> String {
2217
        self.to_string()
2218 2219 2220
    }
}

J
Jorge Aparicio 已提交
2221
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
2222
pub struct Typedef {
2223 2224
    pub type_: Type,
    pub generics: Generics,
C
Corey Richardson 已提交
2225 2226 2227
}

impl Clean<Item> for doctree::Typedef {
2228
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
2229
        Item {
2230 2231 2232
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2233
            def_id: cx.map.local_def_id(self.id.clone()),
2234 2235
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
2236
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
2237
            inner: TypedefItem(Typedef {
2238 2239
                type_: self.ty.clean(cx),
                generics: self.gen.clean(cx),
2240
            }, false),
C
Corey Richardson 已提交
2241 2242 2243 2244
        }
    }
}

J
Jorge Aparicio 已提交
2245
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
2246
pub struct BareFunctionDecl {
2247
    pub unsafety: hir::Unsafety,
2248 2249
    pub generics: Generics,
    pub decl: FnDecl,
2250
    pub abi: Abi,
C
Corey Richardson 已提交
2251 2252
}

2253
impl Clean<BareFunctionDecl> for hir::BareFnTy {
2254
    fn clean(&self, cx: &DocContext) -> BareFunctionDecl {
C
Corey Richardson 已提交
2255
        BareFunctionDecl {
N
Niko Matsakis 已提交
2256
            unsafety: self.unsafety,
C
Corey Richardson 已提交
2257
            generics: Generics {
2258
                lifetimes: self.lifetimes.clean(cx),
2259
                type_params: Vec::new(),
2260
                where_predicates: Vec::new()
C
Corey Richardson 已提交
2261
            },
2262
            decl: self.decl.clean(cx),
2263
            abi: self.abi,
C
Corey Richardson 已提交
2264 2265 2266 2267
        }
    }
}

J
Jorge Aparicio 已提交
2268
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
2269
pub struct Static {
2270 2271
    pub type_: Type,
    pub mutability: Mutability,
C
Corey Richardson 已提交
2272 2273 2274
    /// It's useful to have the value of a static documented, but I have no
    /// desire to represent expressions (that'd basically be all of the AST,
    /// which is huge!). So, have a string.
2275
    pub expr: String,
C
Corey Richardson 已提交
2276 2277 2278
}

impl Clean<Item> for doctree::Static {
2279
    fn clean(&self, cx: &DocContext) -> Item {
2280
        debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
C
Corey Richardson 已提交
2281
        Item {
2282 2283 2284
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2285
            def_id: cx.map.local_def_id(self.id),
2286 2287
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
2288
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
2289
            inner: StaticItem(Static {
2290 2291
                type_: self.type_.clean(cx),
                mutability: self.mutability.clean(cx),
2292
                expr: pprust::expr_to_string(&self.expr),
C
Corey Richardson 已提交
2293 2294 2295 2296 2297
            }),
        }
    }
}

J
Jorge Aparicio 已提交
2298
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309
pub struct Constant {
    pub type_: Type,
    pub expr: String,
}

impl Clean<Item> for doctree::Constant {
    fn clean(&self, cx: &DocContext) -> Item {
        Item {
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2310
            def_id: cx.map.local_def_id(self.id),
2311 2312
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
2313
            deprecation: self.depr.clean(cx),
2314 2315
            inner: ConstantItem(Constant {
                type_: self.type_.clean(cx),
2316
                expr: pprust::expr_to_string(&self.expr),
2317 2318 2319 2320 2321
            }),
        }
    }
}

J
Jorge Aparicio 已提交
2322
#[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Copy)]
C
Corey Richardson 已提交
2323 2324 2325 2326 2327
pub enum Mutability {
    Mutable,
    Immutable,
}

2328
impl Clean<Mutability> for hir::Mutability {
2329
    fn clean(&self, _: &DocContext) -> Mutability {
C
Corey Richardson 已提交
2330
        match self {
2331 2332
            &hir::MutMutable => Mutable,
            &hir::MutImmutable => Immutable,
C
Corey Richardson 已提交
2333 2334 2335 2336
        }
    }
}

J
Jorge Aparicio 已提交
2337
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Copy, Debug)]
2338 2339 2340 2341 2342
pub enum ImplPolarity {
    Positive,
    Negative,
}

2343
impl Clean<ImplPolarity> for hir::ImplPolarity {
2344 2345
    fn clean(&self, _: &DocContext) -> ImplPolarity {
        match self {
2346 2347
            &hir::ImplPolarity::Positive => ImplPolarity::Positive,
            &hir::ImplPolarity::Negative => ImplPolarity::Negative,
2348 2349 2350 2351
        }
    }
}

J
Jorge Aparicio 已提交
2352
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
2353
pub struct Impl {
2354
    pub unsafety: hir::Unsafety,
2355
    pub generics: Generics,
2356
    pub provided_trait_methods: HashSet<String>,
2357 2358
    pub trait_: Option<Type>,
    pub for_: Type,
2359
    pub items: Vec<Item>,
2360
    pub polarity: Option<ImplPolarity>,
C
Corey Richardson 已提交
2361 2362
}

2363 2364 2365 2366 2367 2368 2369 2370
impl Clean<Vec<Item>> for doctree::Impl {
    fn clean(&self, cx: &DocContext) -> Vec<Item> {
        let mut ret = Vec::new();
        let trait_ = self.trait_.clean(cx);
        let items = self.items.clean(cx);

        // If this impl block is an implementation of the Deref trait, then we
        // need to try inlining the target's inherent impl blocks as well.
2371 2372
        if trait_.def_id() == cx.deref_trait_did.get() {
            build_deref_target_impls(cx, &items, &mut ret);
2373 2374
        }

2375 2376 2377 2378 2379 2380 2381 2382 2383
        let provided = trait_.def_id().and_then(|did| {
            cx.tcx_opt().map(|tcx| {
                tcx.provided_trait_methods(did)
                   .into_iter()
                   .map(|meth| meth.name.to_string())
                   .collect()
            })
        }).unwrap_or(HashSet::new());

2384
        ret.push(Item {
C
Corey Richardson 已提交
2385
            name: None,
2386 2387
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2388
            def_id: cx.map.local_def_id(self.id),
2389 2390
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
2391
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
2392
            inner: ImplItem(Impl {
2393
                unsafety: self.unsafety,
2394
                generics: self.generics.clean(cx),
2395
                provided_trait_methods: provided,
2396
                trait_: trait_,
2397
                for_: self.for_.clean(cx),
2398
                items: items,
2399
                polarity: Some(self.polarity.clean(cx)),
C
Corey Richardson 已提交
2400
            }),
2401
        });
M
mitaa 已提交
2402
        ret
2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415
    }
}

fn build_deref_target_impls(cx: &DocContext,
                            items: &[Item],
                            ret: &mut Vec<Item>) {
    let tcx = match cx.tcx_opt() {
        Some(t) => t,
        None => return,
    };

    for item in items {
        let target = match item.inner {
2416
            TypedefItem(ref t, true) => &t.type_,
2417 2418 2419
            _ => continue,
        };
        let primitive = match *target {
N
Niko Matsakis 已提交
2420
            ResolvedPath { did, .. } if did.is_local() => continue,
2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451
            ResolvedPath { did, .. } => {
                ret.extend(inline::build_impls(cx, tcx, did));
                continue
            }
            _ => match target.primitive_type() {
                Some(prim) => prim,
                None => continue,
            }
        };
        let did = match primitive {
            Isize => tcx.lang_items.isize_impl(),
            I8 => tcx.lang_items.i8_impl(),
            I16 => tcx.lang_items.i16_impl(),
            I32 => tcx.lang_items.i32_impl(),
            I64 => tcx.lang_items.i64_impl(),
            Usize => tcx.lang_items.usize_impl(),
            U8 => tcx.lang_items.u8_impl(),
            U16 => tcx.lang_items.u16_impl(),
            U32 => tcx.lang_items.u32_impl(),
            U64 => tcx.lang_items.u64_impl(),
            F32 => tcx.lang_items.f32_impl(),
            F64 => tcx.lang_items.f64_impl(),
            Char => tcx.lang_items.char_impl(),
            Bool => None,
            Str => tcx.lang_items.str_impl(),
            Slice => tcx.lang_items.slice_impl(),
            Array => tcx.lang_items.slice_impl(),
            PrimitiveTuple => None,
            PrimitiveRawPointer => tcx.lang_items.const_ptr_impl(),
        };
        if let Some(did) = did {
N
Niko Matsakis 已提交
2452
            if !did.is_local() {
2453 2454
                inline::build_impl(cx, tcx, did, ret);
            }
C
Corey Richardson 已提交
2455 2456 2457 2458
        }
    }
}

2459 2460
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct DefaultImpl {
2461
    pub unsafety: hir::Unsafety,
2462 2463 2464 2465 2466 2467 2468 2469 2470
    pub trait_: Type,
}

impl Clean<Item> for doctree::DefaultImpl {
    fn clean(&self, cx: &DocContext) -> Item {
        Item {
            name: None,
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2471
            def_id: cx.map.local_def_id(self.id),
J
Jeffrey Seyfried 已提交
2472
            visibility: Some(Public),
2473
            stability: None,
2474
            deprecation: None,
2475 2476 2477 2478 2479 2480 2481 2482
            inner: DefaultImplItem(DefaultImpl {
                unsafety: self.unsafety,
                trait_: self.trait_.clean(cx),
            }),
        }
    }
}

2483 2484 2485 2486 2487 2488
impl Clean<Item> for doctree::ExternCrate {
    fn clean(&self, cx: &DocContext) -> Item {
        Item {
            name: None,
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
M
mitaa 已提交
2489
            def_id: DefId { krate: self.cnum, index: CRATE_DEF_INDEX },
2490 2491
            visibility: self.vis.clean(cx),
            stability: None,
2492
            deprecation: None,
2493 2494 2495
            inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
        }
    }
C
Corey Richardson 已提交
2496 2497
}

2498
impl Clean<Vec<Item>> for doctree::Import {
2499
    fn clean(&self, cx: &DocContext) -> Vec<Item> {
J
Joseph Crail 已提交
2500
        // We consider inlining the documentation of `pub use` statements, but we
2501 2502
        // forcefully don't inline if this is not public or if the
        // #[doc(no_inline)] attribute is present.
2503
        // Don't inline doc(hidden) imports so they can be stripped at a later stage.
2504
        let denied = self.vis != hir::Public || self.attrs.iter().any(|a| {
2505
            &a.name()[..] == "doc" && match a.meta_item_list() {
2506 2507
                Some(l) => attr::contains_name(l, "no_inline") ||
                           attr::contains_name(l, "hidden"),
2508 2509 2510
                None => false,
            }
        });
2511
        let (mut ret, inner) = match self.node {
2512
            hir::ViewPathGlob(ref p) => {
2513
                (vec![], GlobImport(resolve_use_source(cx, p.clean(cx), self.id)))
2514
            }
2515
            hir::ViewPathList(ref p, ref list) => {
2516 2517 2518 2519 2520 2521
                // Attempt to inline all reexported items, but be sure
                // to keep any non-inlineable reexports so they can be
                // listed in the documentation.
                let mut ret = vec![];
                let remaining = if !denied {
                    let mut remaining = vec![];
2522
                    for path in list {
2523
                        match inline::try_inline(cx, path.node.id(), path.node.rename()) {
2524
                            Some(items) => {
2525
                                ret.extend(items);
2526 2527 2528
                            }
                            None => {
                                remaining.push(path.clean(cx));
2529 2530 2531
                            }
                        }
                    }
2532 2533 2534
                    remaining
                } else {
                    list.clean(cx)
P
Patrick Walton 已提交
2535
                };
2536 2537 2538 2539 2540
                if remaining.is_empty() {
                    return ret;
                }
                (ret, ImportList(resolve_use_source(cx, p.clean(cx), self.id),
                                 remaining))
P
Patrick Walton 已提交
2541
            }
2542
            hir::ViewPathSimple(name, ref p) => {
2543
                if !denied {
M
mitaa 已提交
2544 2545
                    if let Some(items) = inline::try_inline(cx, self.id, Some(name)) {
                        return items;
2546 2547
                    }
                }
2548
                (vec![], SimpleImport(name.clean(cx),
2549
                                      resolve_use_source(cx, p.clean(cx), self.id)))
2550
            }
2551 2552 2553 2554 2555
        };
        ret.push(Item {
            name: None,
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2556
            def_id: cx.map.local_def_id(0),
2557 2558
            visibility: self.vis.clean(cx),
            stability: None,
2559
            deprecation: None,
2560 2561 2562
            inner: ImportItem(inner)
        });
        ret
C
Corey Richardson 已提交
2563 2564 2565
    }
}

J
Jorge Aparicio 已提交
2566
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2567
pub enum Import {
2568
    // use source as str;
2569
    SimpleImport(String, ImportSource),
A
Alex Crichton 已提交
2570 2571 2572
    // use source::*;
    GlobImport(ImportSource),
    // use source::{a, b, c};
2573
    ImportList(ImportSource, Vec<ViewListIdent>),
A
Alex Crichton 已提交
2574 2575
}

J
Jorge Aparicio 已提交
2576
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
A
Alex Crichton 已提交
2577
pub struct ImportSource {
2578
    pub path: Path,
N
Niko Matsakis 已提交
2579
    pub did: Option<DefId>,
C
Corey Richardson 已提交
2580 2581
}

J
Jorge Aparicio 已提交
2582
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
A
Alex Crichton 已提交
2583
pub struct ViewListIdent {
2584
    pub name: String,
2585
    pub rename: Option<String>,
N
Niko Matsakis 已提交
2586
    pub source: Option<DefId>,
A
Alex Crichton 已提交
2587
}
C
Corey Richardson 已提交
2588

2589
impl Clean<ViewListIdent> for hir::PathListItem {
2590
    fn clean(&self, cx: &DocContext) -> ViewListIdent {
J
Jakub Wieczorek 已提交
2591
        match self.node {
2592
            hir::PathListIdent { id, name, rename } => ViewListIdent {
2593
                name: name.clean(cx),
2594
                rename: rename.map(|r| r.clean(cx)),
2595
                source: resolve_def(cx, id)
J
Jakub Wieczorek 已提交
2596
            },
2597
            hir::PathListMod { id, rename } => ViewListIdent {
2598
                name: "self".to_string(),
2599
                rename: rename.map(|r| r.clean(cx)),
2600
                source: resolve_def(cx, id)
J
Jakub Wieczorek 已提交
2601
            }
A
Alex Crichton 已提交
2602
        }
C
Corey Richardson 已提交
2603 2604 2605
    }
}

2606
impl Clean<Vec<Item>> for hir::ForeignMod {
2607
    fn clean(&self, cx: &DocContext) -> Vec<Item> {
2608 2609
        let mut items = self.items.clean(cx);
        for item in &mut items {
M
mitaa 已提交
2610 2611
            if let ForeignFunctionItem(ref mut f) = item.inner {
                f.abi = self.abi;
2612 2613 2614
            }
        }
        items
2615 2616 2617
    }
}

2618
impl Clean<Item> for hir::ForeignItem {
2619
    fn clean(&self, cx: &DocContext) -> Item {
2620
        let inner = match self.node {
2621
            hir::ForeignItemFn(ref decl, ref generics) => {
2622
                ForeignFunctionItem(Function {
2623 2624
                    decl: decl.clean(cx),
                    generics: generics.clean(cx),
2625
                    unsafety: hir::Unsafety::Unsafe,
2626
                    abi: Abi::Rust,
2627
                    constness: hir::Constness::NotConst,
2628 2629
                })
            }
2630
            hir::ForeignItemStatic(ref ty, mutbl) => {
2631
                ForeignStaticItem(Static {
2632
                    type_: ty.clean(cx),
2633
                    mutability: if mutbl {Mutable} else {Immutable},
2634
                    expr: "".to_string(),
2635 2636 2637 2638
                })
            }
        };
        Item {
V
Vadim Petrochenkov 已提交
2639
            name: Some(self.name.clean(cx)),
2640 2641
            attrs: self.attrs.clean(cx),
            source: self.span.clean(cx),
2642
            def_id: cx.map.local_def_id(self.id),
2643
            visibility: self.vis.clean(cx),
2644
            stability: get_stability(cx, cx.map.local_def_id(self.id)),
2645
            deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
2646 2647 2648 2649 2650
            inner: inner,
        }
    }
}

C
Corey Richardson 已提交
2651 2652 2653
// Utilities

trait ToSource {
2654
    fn to_src(&self, cx: &DocContext) -> String;
C
Corey Richardson 已提交
2655 2656
}

2657
impl ToSource for syntax_pos::Span {
2658
    fn to_src(&self, cx: &DocContext) -> String {
2659
        debug!("converting span {:?} to snippet", self.clean(cx));
2660
        let sn = match cx.sess().codemap().span_to_snippet(*self) {
2661 2662
            Ok(x) => x.to_string(),
            Err(_) => "".to_string()
C
Corey Richardson 已提交
2663
        };
2664
        debug!("got snippet {}", sn);
C
Corey Richardson 已提交
2665 2666 2667 2668
        sn
    }
}

2669
fn name_from_pat(p: &hir::Pat) -> String {
2670
    use rustc::hir::*;
2671
    debug!("Trying to get a name from pattern: {:?}", p);
2672

C
Corey Richardson 已提交
2673
    match p.node {
2674
        PatKind::Wild => "_".to_string(),
2675
        PatKind::Binding(_, ref p, _) => p.node.to_string(),
2676 2677 2678
        PatKind::TupleStruct(ref p, _, _) | PatKind::Path(None, ref p) => path_to_string(p),
        PatKind::Path(..) => panic!("tried to get argument name from qualified PatKind::Path, \
                                     which is not allowed in function arguments"),
2679
        PatKind::Struct(ref name, ref fields, etc) => {
2680
            format!("{} {{ {}{} }}", path_to_string(name),
2681
                fields.iter().map(|&Spanned { node: ref fp, .. }|
2682
                                  format!("{}: {}", fp.name, name_from_pat(&*fp.pat)))
2683
                             .collect::<Vec<String>>().join(", "),
2684 2685 2686
                if etc { ", ..." } else { "" }
            )
        },
2687
        PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
2688
                                            .collect::<Vec<String>>().join(", ")),
2689 2690 2691 2692
        PatKind::Box(ref p) => name_from_pat(&**p),
        PatKind::Ref(ref p, _) => name_from_pat(&**p),
        PatKind::Lit(..) => {
            warn!("tried to get argument name from PatKind::Lit, \
2693
                  which is silly in function arguments");
2694
            "()".to_string()
2695
        },
2696
        PatKind::Range(..) => panic!("tried to get argument name from PatKind::Range, \
2697
                              which is not allowed in function arguments"),
2698
        PatKind::Vec(ref begin, ref mid, ref end) => {
2699 2700 2701
            let begin = begin.iter().map(|p| name_from_pat(&**p));
            let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter();
            let end = end.iter().map(|p| name_from_pat(&**p));
2702
            format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
2703
        },
C
Corey Richardson 已提交
2704 2705 2706 2707
    }
}

/// Given a Type, resolve it using the def_map
N
Niko Matsakis 已提交
2708 2709
fn resolve_type(cx: &DocContext,
                path: Path,
2710
                id: ast::NodeId) -> Type {
2711
    debug!("resolve_type({:?},{:?})", path, id);
2712 2713
    let tcx = match cx.tcx_opt() {
        Some(tcx) => tcx,
2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725
        // If we're extracting tests, this return value's accuracy is not
        // important, all we want is a string representation to help people
        // figure out what doctests are failing.
        None => {
            let did = DefId::local(DefIndex::from_u32(0));
            return ResolvedPath {
                path: path,
                typarams: None,
                did: did,
                is_generic: false
            };
        }
2726
    };
2727
    let def = tcx.expect_def(id);
2728 2729
    debug!("resolve_type: def={:?}", def);

2730
    let is_generic = match def {
2731
        Def::PrimTy(p) => match p {
2732 2733 2734
            hir::TyStr => return Primitive(Str),
            hir::TyBool => return Primitive(Bool),
            hir::TyChar => return Primitive(Char),
2735 2736 2737 2738 2739 2740 2741 2742 2743 2744
            hir::TyInt(ast::IntTy::Is) => return Primitive(Isize),
            hir::TyInt(ast::IntTy::I8) => return Primitive(I8),
            hir::TyInt(ast::IntTy::I16) => return Primitive(I16),
            hir::TyInt(ast::IntTy::I32) => return Primitive(I32),
            hir::TyInt(ast::IntTy::I64) => return Primitive(I64),
            hir::TyUint(ast::UintTy::Us) => return Primitive(Usize),
            hir::TyUint(ast::UintTy::U8) => return Primitive(U8),
            hir::TyUint(ast::UintTy::U16) => return Primitive(U16),
            hir::TyUint(ast::UintTy::U32) => return Primitive(U32),
            hir::TyUint(ast::UintTy::U64) => return Primitive(U64),
2745 2746
            hir::TyFloat(ast::FloatTy::F32) => return Primitive(F32),
            hir::TyFloat(ast::FloatTy::F64) => return Primitive(F64),
C
Corey Richardson 已提交
2747
        },
2748
        Def::SelfTy(..) if path.segments.len() == 1 => {
2749
            return Generic(keywords::SelfType.name().to_string());
2750
        }
2751
        Def::SelfTy(..) | Def::TyParam(..) | Def::AssociatedTy(..) => true,
2752
        _ => false,
2753
    };
2754
    let did = register_def(&*cx, def);
2755
    ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
2756 2757
}

2758
fn register_def(cx: &DocContext, def: Def) -> DefId {
2759 2760
    debug!("register_def({:?})", def);

2761
    let (did, kind) = match def {
2762 2763 2764 2765 2766 2767 2768 2769 2770
        Def::Fn(i) => (i, TypeFunction),
        Def::TyAlias(i) => (i, TypeTypedef),
        Def::Enum(i) => (i, TypeEnum),
        Def::Trait(i) => (i, TypeTrait),
        Def::Struct(i) => (i, TypeStruct),
        Def::Mod(i) => (i, TypeModule),
        Def::Static(i, _) => (i, TypeStatic),
        Def::Variant(i, _) => (i, TypeEnum),
        Def::SelfTy(Some(def_id), _) => (def_id, TypeTrait),
2771 2772 2773 2774 2775 2776
        Def::SelfTy(_, Some(impl_id)) => {
            // For Def::SelfTy() values inlined from another crate, the
            // impl_id will be DUMMY_NODE_ID, which would cause problems.
            // But we should never run into an impl from another crate here.
            return cx.map.local_def_id(impl_id)
        }
2777
        _ => return def.def_id()
C
Corey Richardson 已提交
2778
    };
N
Niko Matsakis 已提交
2779
    if did.is_local() { return did }
2780 2781 2782
    let tcx = match cx.tcx_opt() {
        Some(tcx) => tcx,
        None => return did
2783
    };
2784
    inline::record_extern_fqn(cx, did, kind);
2785 2786
    if let TypeTrait = kind {
        let t = inline::build_external_trait(cx, tcx, did);
M
mitaa 已提交
2787
        cx.external_traits.borrow_mut().insert(did, t);
2788
    }
M
mitaa 已提交
2789
    did
C
Corey Richardson 已提交
2790
}
A
Alex Crichton 已提交
2791

2792
fn resolve_use_source(cx: &DocContext, path: Path, id: ast::NodeId) -> ImportSource {
A
Alex Crichton 已提交
2793 2794
    ImportSource {
        path: path,
2795
        did: resolve_def(cx, id),
A
Alex Crichton 已提交
2796 2797 2798
    }
}

N
Niko Matsakis 已提交
2799
fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option<DefId> {
2800
    cx.tcx_opt().and_then(|tcx| {
2801
        tcx.expect_def_or_none(id).map(|def| register_def(cx, def))
2802
    })
A
Alex Crichton 已提交
2803
}
2804

J
Jorge Aparicio 已提交
2805
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2806
pub struct Macro {
2807
    pub source: String,
2808
    pub imported_from: Option<String>,
2809 2810 2811
}

impl Clean<Item> for doctree::Macro {
2812
    fn clean(&self, cx: &DocContext) -> Item {
2813
        let name = format!("{}!", self.name.clean(cx));
2814
        Item {
2815
            name: Some(name.clone()),
2816 2817
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
J
Jeffrey Seyfried 已提交
2818
            visibility: Some(Public),
2819
            stability: self.stab.clean(cx),
2820
            deprecation: self.depr.clean(cx),
2821
            def_id: cx.map.local_def_id(self.id),
2822
            inner: MacroItem(Macro {
2823 2824
                source: format!("macro_rules! {} {{\n{}}}",
                    name.trim_right_matches('!'), self.matchers.iter().map(|span|
J
;  
Jonas Schievink 已提交
2825
                        format!("    {} => {{ ... }};\n", span.to_src(cx))).collect::<String>()),
2826
                imported_from: self.imported_from.clean(cx),
2827 2828 2829 2830
            }),
        }
    }
}
2831

J
Jorge Aparicio 已提交
2832
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2833
pub struct Stability {
V
Vadim Petrochenkov 已提交
2834
    pub level: stability::StabilityLevel,
2835 2836
    pub feature: String,
    pub since: String,
2837
    pub deprecated_since: String,
2838 2839
    pub reason: String,
    pub issue: Option<u32>
2840 2841
}

2842 2843 2844 2845 2846 2847
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Deprecation {
    pub since: String,
    pub note: String,
}

2848
impl Clean<Stability> for attr::Stability {
2849 2850
    fn clean(&self, _: &DocContext) -> Stability {
        Stability {
V
Vadim Petrochenkov 已提交
2851
            level: stability::StabilityLevel::from_attr_level(&self.level),
2852
            feature: self.feature.to_string(),
V
Vadim Petrochenkov 已提交
2853 2854 2855 2856
            since: match self.level {
                attr::Stable {ref since} => since.to_string(),
                _ => "".to_string(),
            },
2857 2858
            deprecated_since: match self.rustc_depr {
                Some(attr::RustcDeprecation {ref since, ..}) => since.to_string(),
V
Vadim Petrochenkov 已提交
2859 2860
                _=> "".to_string(),
            },
2861
            reason: {
M
mitaa 已提交
2862 2863 2864 2865
                match (&self.rustc_depr, &self.level) {
                    (&Some(ref depr), _) => depr.reason.to_string(),
                    (&None, &attr::Unstable {reason: Some(ref reason), ..}) => reason.to_string(),
                    _ => "".to_string(),
2866
                }
V
Vadim Petrochenkov 已提交
2867 2868 2869 2870 2871
            },
            issue: match self.level {
                attr::Unstable {issue, ..} => Some(issue),
                _ => None,
            }
2872 2873 2874 2875 2876
        }
    }
}

impl<'a> Clean<Stability> for &'a attr::Stability {
V
Vadim Petrochenkov 已提交
2877 2878
    fn clean(&self, dc: &DocContext) -> Stability {
        (**self).clean(dc)
2879 2880
    }
}
A
Alex Crichton 已提交
2881

2882 2883 2884 2885 2886 2887 2888 2889 2890
impl Clean<Deprecation> for attr::Deprecation {
    fn clean(&self, _: &DocContext) -> Deprecation {
        Deprecation {
            since: self.since.as_ref().map_or("".to_string(), |s| s.to_string()),
            note: self.note.as_ref().map_or("".to_string(), |s| s.to_string()),
        }
    }
}

2891 2892 2893 2894 2895 2896 2897 2898 2899 2900
impl<'tcx> Clean<Item> for ty::AssociatedConst<'tcx> {
    fn clean(&self, cx: &DocContext) -> Item {
        Item {
            source: DUMMY_SP.clean(cx),
            name: Some(self.name.clean(cx)),
            attrs: Vec::new(),
            inner: AssociatedConstItem(self.ty.clean(cx), None),
            visibility: None,
            def_id: self.def_id,
            stability: None,
2901
            deprecation: None,
2902 2903 2904 2905
        }
    }
}

2906
impl<'tcx> Clean<Item> for ty::AssociatedType<'tcx> {
2907
    fn clean(&self, cx: &DocContext) -> Item {
2908
        let my_name = self.name.clean(cx);
2909 2910 2911 2912 2913 2914

        let mut bounds = if let ty::TraitContainer(did) = self.container {
            // When loading a cross-crate associated type, the bounds for this type
            // are actually located on the trait/impl itself, so we need to load
            // all of the generics from there and then look for bounds that are
            // applied to this associated type in question.
2915 2916
            let def = cx.tcx().lookup_trait_def(did);
            let predicates = cx.tcx().lookup_predicates(did);
2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939
            let generics = (&def.generics, &predicates, subst::TypeSpace).clean(cx);
            generics.where_predicates.iter().filter_map(|pred| {
                let (name, self_type, trait_, bounds) = match *pred {
                    WherePredicate::BoundPredicate {
                        ty: QPath { ref name, ref self_type, ref trait_ },
                        ref bounds
                    } => (name, self_type, trait_, bounds),
                    _ => return None,
                };
                if *name != my_name { return None }
                match **trait_ {
                    ResolvedPath { did, .. } if did == self.container.id() => {}
                    _ => return None,
                }
                match **self_type {
                    Generic(ref s) if *s == "Self" => {}
                    _ => return None,
                }
                Some(bounds)
            }).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>()
        } else {
            vec![]
        };
2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950

        // Our Sized/?Sized bound didn't get handled when creating the generics
        // because we didn't actually get our whole set of bounds until just now
        // (some of them may have come from the trait). If we do have a sized
        // bound, we remove it, and if we don't then we add the `?Sized` bound
        // at the end.
        match bounds.iter().position(|b| b.is_sized_bound(cx)) {
            Some(i) => { bounds.remove(i); }
            None => bounds.push(TyParamBound::maybe_sized(cx)),
        }

2951 2952
        Item {
            source: DUMMY_SP.clean(cx),
2953
            name: Some(self.name.clean(cx)),
2954
            attrs: inline::load_attrs(cx, cx.tcx(), self.def_id),
2955
            inner: AssociatedTypeItem(bounds, self.ty.clean(cx)),
2956
            visibility: self.vis.clean(cx),
2957
            def_id: self.def_id,
2958 2959
            stability: cx.tcx().lookup_stability(self.def_id).clean(cx),
            deprecation: cx.tcx().lookup_deprecation(self.def_id).clean(cx),
2960 2961 2962 2963
        }
    }
}

2964 2965
impl<'a> Clean<Typedef> for (ty::TypeScheme<'a>, ty::GenericPredicates<'a>,
                             ParamSpace) {
2966
    fn clean(&self, cx: &DocContext) -> Typedef {
2967
        let (ref ty_scheme, ref predicates, ps) = *self;
2968 2969
        Typedef {
            type_: ty_scheme.ty.clean(cx),
2970
            generics: (&ty_scheme.generics, predicates, ps).clean(cx)
2971 2972 2973 2974
        }
    }
}

N
Niko Matsakis 已提交
2975
fn lang_struct(cx: &DocContext, did: Option<DefId>,
2976
               t: ty::Ty, name: &str,
A
Alex Crichton 已提交
2977 2978 2979
               fallback: fn(Box<Type>) -> Type) -> Type {
    let did = match did {
        Some(did) => did,
2980
        None => return fallback(box t.clean(cx)),
A
Alex Crichton 已提交
2981
    };
M
mitaa 已提交
2982
    inline::record_extern_fqn(cx, did, TypeStruct);
A
Alex Crichton 已提交
2983 2984 2985 2986 2987 2988 2989
    ResolvedPath {
        typarams: None,
        did: did,
        path: Path {
            global: false,
            segments: vec![PathSegment {
                name: name.to_string(),
2990 2991 2992
                params: PathParameters::AngleBracketed {
                    lifetimes: vec![],
                    types: vec![t.clean(cx)],
2993
                    bindings: vec![]
2994
                }
A
Alex Crichton 已提交
2995 2996
            }],
        },
2997
        is_generic: false,
A
Alex Crichton 已提交
2998 2999
    }
}
3000 3001

/// An equality constraint on an associated type, e.g. `A=Bar` in `Foo<A=Bar>`
J
Jorge Aparicio 已提交
3002
#[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Debug)]
3003 3004 3005 3006 3007
pub struct TypeBinding {
    pub name: String,
    pub ty: Type
}

3008
impl Clean<TypeBinding> for hir::TypeBinding {
3009 3010
    fn clean(&self, cx: &DocContext) -> TypeBinding {
        TypeBinding {
3011
            name: self.name.clean(cx),
3012 3013 3014 3015
            ty: self.ty.clean(cx)
        }
    }
}