mod.rs 95.8 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

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

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

47
use rustc::hir;
48

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

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

62
pub mod inline;
63
mod simplify;
64

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

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

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

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

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

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

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

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

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

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

M
mitaa 已提交
120
#[derive(Clone, Debug)]
C
Corey Richardson 已提交
121
pub struct Crate {
122
    pub name: String,
A
Alex Crichton 已提交
123
    pub src: PathBuf,
124 125
    pub module: Option<Item>,
    pub externs: Vec<(ast::CrateNum, ExternalCrate)>,
126
    pub primitives: Vec<PrimitiveType>,
M
mitaa 已提交
127 128 129
    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 已提交
130
    pub external_traits: HashMap<DefId, Trait>,
C
Corey Richardson 已提交
131 132
}

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

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

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

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

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

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

        // Collect all inner modules which are tagged as implementations of
        // primitives.
165 166 167
        //
        // 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
168
        // item tagged with `#[doc(primitive)]` then we would also have to
169 170 171 172 173 174 175 176 177 178 179
        // 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.
180 181 182 183 184 185 186
        let mut primitives = Vec::new();
        {
            let m = match module.inner {
                ModuleItem(ref mut m) => m,
                _ => unreachable!(),
            };
            let mut tmp = Vec::new();
187
            for child in &mut m.items {
M
mitaa 已提交
188 189
                if !child.is_mod() {
                    continue;
190
                }
191
                let prim = match PrimitiveType::find(&child.attrs) {
192 193 194 195
                    Some(prim) => prim,
                    None => continue,
                };
                primitives.push(prim);
196
                tmp.push(Item {
197 198
                    source: Span::empty(),
                    name: Some(prim.to_url_str().to_string()),
199
                    attrs: child.attrs.clone(),
J
Jeffrey Seyfried 已提交
200
                    visibility: Some(Public),
201
                    stability: None,
202
                    deprecation: None,
203
                    def_id: DefId::local(prim.to_def_index()),
204
                    inner: PrimitiveItem(prim),
205
                });
206
            }
207
            m.items.extend(tmp);
208 209
        }

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

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

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

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

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

/// 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 已提交
267
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
268 269
pub struct Item {
    /// Stringified span
270
    pub source: Span,
C
Corey Richardson 已提交
271
    /// Not everything has a name. E.g., impls
272
    pub name: Option<String>,
M
mitaa 已提交
273
    pub attrs: Vec<Attribute>,
274 275
    pub inner: ItemEnum,
    pub visibility: Option<Visibility>,
N
Niko Matsakis 已提交
276
    pub def_id: DefId,
277
    pub stability: Option<Stability>,
278
    pub deprecation: Option<Deprecation>,
C
Corey Richardson 已提交
279 280
}

281 282 283 284
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 已提交
285
        self.attrs.value("doc")
286
    }
M
mitaa 已提交
287 288
    pub fn is_crate(&self) -> bool {
        match self.inner {
289 290 291
            StrippedItem(box ModuleItem(Module { is_crate: true, ..})) |
            ModuleItem(Module { is_crate: true, ..}) => true,
            _ => false,
M
mitaa 已提交
292 293
        }
    }
294
    pub fn is_mod(&self) -> bool {
295
        ItemType::from_item(self) == ItemType::Module
296 297
    }
    pub fn is_trait(&self) -> bool {
298
        ItemType::from_item(self) == ItemType::Trait
299 300
    }
    pub fn is_struct(&self) -> bool {
301
        ItemType::from_item(self) == ItemType::Struct
302 303
    }
    pub fn is_enum(&self) -> bool {
304
        ItemType::from_item(self) == ItemType::Module
305 306
    }
    pub fn is_fn(&self) -> bool {
307
        ItemType::from_item(self) == ItemType::Function
308
    }
M
mitaa 已提交
309
    pub fn is_associated_type(&self) -> bool {
310
        ItemType::from_item(self) == ItemType::AssociatedType
M
mitaa 已提交
311 312
    }
    pub fn is_associated_const(&self) -> bool {
313
        ItemType::from_item(self) == ItemType::AssociatedConst
M
mitaa 已提交
314 315
    }
    pub fn is_method(&self) -> bool {
316
        ItemType::from_item(self) == ItemType::Method
M
mitaa 已提交
317 318
    }
    pub fn is_ty_method(&self) -> bool {
319 320 321 322
        ItemType::from_item(self) == ItemType::TyMethod
    }
    pub fn is_stripped(&self) -> bool {
        match self.inner { StrippedItem(..) => true, _ => false }
M
mitaa 已提交
323
    }
324 325 326 327 328 329 330 331 332
    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,
        }
    }
333 334

    pub fn stability_class(&self) -> String {
M
mitaa 已提交
335 336 337 338 339 340 341
        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");
342
            }
M
mitaa 已提交
343 344
            base
        }).unwrap_or(String::new())
345
    }
346 347

    pub fn stable_since(&self) -> Option<&str> {
M
mitaa 已提交
348
        self.stability.as_ref().map(|s| &s.since[..])
349
    }
350 351
}

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

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

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

        let mut items: Vec<Item> = vec![];
        items.extend(self.extern_crates.iter().map(|x| x.clean(cx)));
401
        items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
402 403 404
        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)));
405
        items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx)));
406 407 408 409 410
        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)));
411
        items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
412
        items.extend(self.macros.iter().map(|x| x.clean(cx)));
413
        items.extend(self.def_traits.iter().map(|x| x.clean(cx)));
414 415 416

        // determine if we should display the inner contents or
        // the outer `mod` item for the source code.
417
        let whence = {
418
            let cm = cx.sess().codemap();
419 420 421 422 423 424 425 426 427 428 429
            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 已提交
430 431
        Item {
            name: Some(name),
432 433 434 435
            attrs: self.attrs.clean(cx),
            source: whence.clean(cx),
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
436
            deprecation: self.depr.clean(cx),
437
            def_id: cx.map.local_def_id(self.id),
C
Corey Richardson 已提交
438
            inner: ModuleItem(Module {
439
               is_crate: self.is_crate,
440
               items: items
C
Corey Richardson 已提交
441 442 443 444 445
            })
        }
    }
}

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

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.
478
    fn list<'a>(&'a self, name: &str) -> &'a [Attribute] {
M
mitaa 已提交
479 480 481 482 483 484 485 486 487 488 489
        for attr in self {
            if let List(ref x, ref list) = *attr {
                if name == *x {
                    return &list[..];
                }
            }
        }
        &[]
    }
}

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

497
impl Clean<Attribute> for ast::MetaItem {
498
    fn clean(&self, cx: &DocContext) -> Attribute {
C
Corey Richardson 已提交
499
        match self.node {
500 501
            ast::MetaItemKind::Word(ref s) => Word(s.to_string()),
            ast::MetaItemKind::List(ref s, ref l) => {
G
GuillaumeGomez 已提交
502
                List(s.to_string(), l.clean(cx))
503
            }
504
            ast::MetaItemKind::NameValue(ref s, ref v) => {
G
GuillaumeGomez 已提交
505
                NameValue(s.to_string(), lit_to_string(v))
506
            }
C
Corey Richardson 已提交
507 508 509 510
        }
    }
}

511
impl Clean<Attribute> for ast::Attribute {
512
    fn clean(&self, cx: &DocContext) -> Attribute {
513
        self.with_desugared_doc(|a| a.node.value.clean(cx))
C
Corey Richardson 已提交
514 515 516
    }
}

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

527
    fn value_str(&self) -> Option<InternedString> {
528
        match *self {
529
            NameValue(_, ref v) => {
530
                Some(token::intern_and_get_ident(v))
531
            }
532 533 534
            _ => None,
        }
    }
535
    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<ast::MetaItem>]> { None }
536
    fn span(&self) -> codemap::Span { unimplemented!() }
537 538
}

J
Jorge Aparicio 已提交
539
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
540
pub struct TyParam {
541
    pub name: String,
N
Niko Matsakis 已提交
542
    pub did: DefId,
543
    pub bounds: Vec<TyParamBound>,
544
    pub default: Option<Type>,
545
}
C
Corey Richardson 已提交
546

547
impl Clean<TyParam> for hir::TyParam {
548
    fn clean(&self, cx: &DocContext) -> TyParam {
C
Corey Richardson 已提交
549
        TyParam {
550
            name: self.name.clean(cx),
551
            did: cx.map.local_def_id(self.id),
552
            bounds: self.bounds.clean(cx),
553
            default: self.default.clean(cx),
C
Corey Richardson 已提交
554 555 556 557
        }
    }
}

558
impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> {
559
    fn clean(&self, cx: &DocContext) -> TyParam {
M
mitaa 已提交
560
        cx.renderinfo.borrow_mut().external_typarams.insert(self.def_id, self.name.clean(cx));
561
        TyParam {
562
            name: self.name.clean(cx),
563
            did: self.def_id,
564
            bounds: vec![], // these are filled in from the where-clauses
565
            default: self.default.clean(cx),
566 567 568 569
        }
    }
}

J
Jorge Aparicio 已提交
570
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
571
pub enum TyParamBound {
572
    RegionBound(Lifetime),
573
    TraitBound(PolyTrait, hir::TraitBoundModifier)
C
Corey Richardson 已提交
574 575
}

576 577
impl TyParamBound {
    fn maybe_sized(cx: &DocContext) -> TyParamBound {
578
        use rustc::hir::TraitBoundModifier as TBM;
579
        let mut sized_bound = ty::BoundSized.clean(cx);
580 581 582 583 584 585 586
        if let TyParamBound::TraitBound(_, ref mut tbm) = sized_bound {
            *tbm = TBM::Maybe
        };
        sized_bound
    }

    fn is_sized_bound(&self, cx: &DocContext) -> bool {
587
        use rustc::hir::TraitBoundModifier as TBM;
588
        if let Some(tcx) = cx.tcx_opt() {
589 590 591
            if let TyParamBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
                if trait_.def_id() == tcx.lang_items.sized_trait() {
                    return true;
592 593 594 595 596 597 598
                }
            }
        }
        false
    }
}

599
impl Clean<TyParamBound> for hir::TyParamBound {
600
    fn clean(&self, cx: &DocContext) -> TyParamBound {
C
Corey Richardson 已提交
601
        match *self {
602 603
            hir::RegionTyParamBound(lt) => RegionBound(lt.clean(cx)),
            hir::TraitTyParamBound(ref t, modifier) => TraitBound(t.clean(cx), modifier),
C
Corey Richardson 已提交
604 605 606 607
        }
    }
}

608 609 610 611
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)));
612
        for bb in &self.builtin_bounds {
613
            tp_bounds.push(bb.clean(cx));
614
        }
N
Niko Matsakis 已提交
615

616
        let mut bindings = vec![];
617
        for &ty::Binder(ref pb) in &self.projection_bounds {
618 619 620 621 622
            bindings.push(TypeBinding {
                name: pb.projection_ty.item_name.clean(cx),
                ty: pb.ty.clean(cx)
            });
        }
N
Niko Matsakis 已提交
623

624
        (tp_bounds, bindings)
625 626 627
    }
}

N
Niko Matsakis 已提交
628
fn external_path_params(cx: &DocContext, trait_did: Option<DefId>,
629
                        bindings: Vec<TypeBinding>, substs: &subst::Substs) -> PathParameters {
630
    let lifetimes = substs.regions.get_slice(subst::TypeSpace)
631
                    .iter()
632
                    .filter_map(|v| v.clean(cx))
633
                    .collect();
634
    let types = substs.types.get_slice(subst::TypeSpace).to_vec();
635 636 637 638

    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() => {
639
            assert_eq!(types.len(), 1);
640
            let inputs = match types[0].sty {
641
                ty::TyTuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
642 643 644
                _ => {
                    return PathParameters::AngleBracketed {
                        lifetimes: lifetimes,
645
                        types: types.clean(cx),
646
                        bindings: bindings
647 648 649
                    }
                }
            };
650 651 652
            let output = None;
            // FIXME(#20299) return type comes from a projection now
            // match types[1].sty {
653
            //     ty::TyTuple(ref v) if v.is_empty() => None, // -> ()
654 655
            //     _ => Some(types[1].clean(cx))
            // };
656 657 658 659 660 661 662 663 664
            PathParameters::Parenthesized {
                inputs: inputs,
                output: output
            }
        },
        (_, _) => {
            PathParameters::AngleBracketed {
                lifetimes: lifetimes,
                types: types.clean(cx),
665
                bindings: bindings
666 667 668 669 670 671 672
            }
        }
    }
}

// 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 已提交
673
fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>,
674
                 bindings: Vec<TypeBinding>, substs: &subst::Substs) -> Path {
675 676 677
    Path {
        global: false,
        segments: vec![PathSegment {
678
            name: name.to_string(),
679
            params: external_path_params(cx, trait_did, bindings, substs)
680
        }],
681 682 683 684
    }
}

impl Clean<TyParamBound> for ty::BuiltinBound {
685 686 687
    fn clean(&self, cx: &DocContext) -> TyParamBound {
        let tcx = match cx.tcx_opt() {
            Some(tcx) => tcx,
688
            None => return RegionBound(Lifetime::statik())
689
        };
690
        let empty = subst::Substs::empty();
691 692
        let (did, path) = match *self {
            ty::BoundSend =>
693
                (tcx.lang_items.send_trait().unwrap(),
694
                 external_path(cx, "Send", None, vec![], &empty)),
695
            ty::BoundSized =>
696
                (tcx.lang_items.sized_trait().unwrap(),
697
                 external_path(cx, "Sized", None, vec![], &empty)),
698
            ty::BoundCopy =>
699
                (tcx.lang_items.copy_trait().unwrap(),
700
                 external_path(cx, "Copy", None, vec![], &empty)),
A
Alex Crichton 已提交
701 702
            ty::BoundSync =>
                (tcx.lang_items.sync_trait().unwrap(),
703
                 external_path(cx, "Sync", None, vec![], &empty)),
704
        };
M
mitaa 已提交
705
        inline::record_extern_fqn(cx, did, TypeTrait);
706 707 708 709 710
        TraitBound(PolyTrait {
            trait_: ResolvedPath {
                path: path,
                typarams: None,
                did: did,
711
                is_generic: false,
712 713
            },
            lifetimes: vec![]
714
        }, hir::TraitBoundModifier::None)
715 716 717
    }
}

718
impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
719 720 721
    fn clean(&self, cx: &DocContext) -> TyParamBound {
        let tcx = match cx.tcx_opt() {
            Some(tcx) => tcx,
722
            None => return RegionBound(Lifetime::statik())
723
        };
M
mitaa 已提交
724 725
        inline::record_extern_fqn(cx, self.def_id, TypeTrait);
        let path = external_path(cx, &tcx.item_name(self.def_id).as_str(),
726
                                 Some(self.def_id), vec![], self.substs);
727

728
        debug!("ty::TraitRef\n  substs.types(TypeSpace): {:?}\n",
729 730 731 732
               self.substs.types.get_slice(ParamSpace::TypeSpace));

        // collect any late bound regions
        let mut late_bounds = vec![];
733
        for &ty_s in self.substs.types.get_slice(ParamSpace::TypeSpace) {
734
            if let ty::TyTuple(ref ts) = ty_s.sty {
735
                for &ty_s in ts {
736 737
                    if let ty::TyRef(ref reg, _) = ty_s.sty {
                        if let &ty::Region::ReLateBound(_, _) = *reg {
738
                            debug!("  hit an ReLateBound {:?}", reg);
739
                            if let Some(lt) = reg.clean(cx) {
M
mitaa 已提交
740
                                late_bounds.push(lt);
741 742 743 744 745 746 747
                            }
                        }
                    }
                }
            }
        }

748 749 750 751 752 753 754 755 756
        TraitBound(
            PolyTrait {
                trait_: ResolvedPath {
                    path: path,
                    typarams: None,
                    did: self.def_id,
                    is_generic: false,
                },
                lifetimes: late_bounds,
757
            },
758 759
            hir::TraitBoundModifier::None
        )
760 761 762
    }
}

763
impl<'tcx> Clean<Option<Vec<TyParamBound>>> for subst::Substs<'tcx> {
764
    fn clean(&self, cx: &DocContext) -> Option<Vec<TyParamBound>> {
765
        let mut v = Vec::new();
766
        v.extend(self.regions.iter().filter_map(|r| r.clean(cx)).map(RegionBound));
767 768 769
        v.extend(self.types.iter().map(|t| TraitBound(PolyTrait {
            trait_: t.clean(cx),
            lifetimes: vec![]
770
        }, hir::TraitBoundModifier::None)));
771
        if !v.is_empty() {Some(v)} else {None}
772 773 774
    }
}

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

778 779 780
impl Lifetime {
    pub fn get_ref<'a>(&'a self) -> &'a str {
        let Lifetime(ref s) = *self;
781
        let s: &'a str = s;
782 783
        return s;
    }
784 785 786 787

    pub fn statik() -> Lifetime {
        Lifetime("'static".to_string())
    }
788 789
}

790
impl Clean<Lifetime> for hir::Lifetime {
791
    fn clean(&self, _: &DocContext) -> Lifetime {
792
        Lifetime(self.name.to_string())
C
Corey Richardson 已提交
793 794 795
    }
}

796
impl Clean<Lifetime> for hir::LifetimeDef {
797
    fn clean(&self, _: &DocContext) -> Lifetime {
798
        Lifetime(self.lifetime.name.to_string())
799 800 801
    }
}

802
impl Clean<Lifetime> for ty::RegionParameterDef {
803
    fn clean(&self, _: &DocContext) -> Lifetime {
804
        Lifetime(self.name.to_string())
805 806 807 808
    }
}

impl Clean<Option<Lifetime>> for ty::Region {
809
    fn clean(&self, cx: &DocContext) -> Option<Lifetime> {
810
        match *self {
811
            ty::ReStatic => Some(Lifetime::statik()),
M
mitaa 已提交
812
            ty::ReLateBound(_, ty::BrNamed(_, name)) => Some(Lifetime(name.to_string())),
N
Niko Matsakis 已提交
813
            ty::ReEarlyBound(ref data) => Some(Lifetime(data.name.clean(cx))),
814 815 816 817

            ty::ReLateBound(..) |
            ty::ReFree(..) |
            ty::ReScope(..) |
818 819
            ty::ReVar(..) |
            ty::ReSkolemized(..) |
V
Vadim Petrochenkov 已提交
820
            ty::ReEmpty => None
821 822 823 824
        }
    }
}

J
Jorge Aparicio 已提交
825
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
826 827 828
pub enum WherePredicate {
    BoundPredicate { ty: Type, bounds: Vec<TyParamBound> },
    RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>},
829
    EqPredicate { lhs: Type, rhs: Type }
830 831
}

832
impl Clean<WherePredicate> for hir::WherePredicate {
833
    fn clean(&self, cx: &DocContext) -> WherePredicate {
N
Nick Cameron 已提交
834
        match *self {
835
            hir::WherePredicate::BoundPredicate(ref wbp) => {
836
                WherePredicate::BoundPredicate {
837
                    ty: wbp.bounded_ty.clean(cx),
N
Nick Cameron 已提交
838 839 840
                    bounds: wbp.bounds.clean(cx)
                }
            }
841

842
            hir::WherePredicate::RegionPredicate(ref wrp) => {
843 844 845 846 847 848
                WherePredicate::RegionPredicate {
                    lifetime: wrp.lifetime.clean(cx),
                    bounds: wrp.bounds.clean(cx)
                }
            }

849
            hir::WherePredicate::EqPredicate(_) => {
850
                unimplemented!() // FIXME(#20041)
N
Nick Cameron 已提交
851
            }
852 853 854 855
        }
    }
}

856 857
impl<'a> Clean<WherePredicate> for ty::Predicate<'a> {
    fn clean(&self, cx: &DocContext) -> WherePredicate {
858
        use rustc::ty::Predicate;
859 860 861 862 863 864

        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),
865 866 867
            Predicate::Projection(ref pred) => pred.clean(cx),
            Predicate::WellFormed(_) => panic!("not user writable"),
            Predicate::ObjectSafe(_) => panic!("not user writable"),
868
            Predicate::ClosureKind(..) => panic!("not user writable"),
A
fixes  
Ariel Ben-Yehuda 已提交
869
            Predicate::Rfc1592(..) => panic!("not user writable"),
870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926
        }
    }
}

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_,
927 928 929
            TyParamBound::RegionBound(_) => {
                panic!("cleaning a trait got a region")
            }
930 931 932 933 934 935 936 937 938
        };
        Type::QPath {
            name: self.item_name.clean(cx),
            self_type: box self.trait_ref.self_ty().clean(cx),
            trait_: box trait_
        }
    }
}

939
// maybe use a Generic enum and use Vec<Generic>?
J
Jorge Aparicio 已提交
940
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
941
pub struct Generics {
942 943
    pub lifetimes: Vec<Lifetime>,
    pub type_params: Vec<TyParam>,
944
    pub where_predicates: Vec<WherePredicate>
945
}
C
Corey Richardson 已提交
946

947
impl Clean<Generics> for hir::Generics {
948
    fn clean(&self, cx: &DocContext) -> Generics {
C
Corey Richardson 已提交
949
        Generics {
950 951
            lifetimes: self.lifetimes.clean(cx),
            type_params: self.ty_params.clean(cx),
952
            where_predicates: self.where_clause.predicates.clean(cx)
C
Corey Richardson 已提交
953 954 955 956
        }
    }
}

957 958 959
impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
                                    &'a ty::GenericPredicates<'tcx>,
                                    subst::ParamSpace) {
960
    fn clean(&self, cx: &DocContext) -> Generics {
961 962
        use self::WherePredicate as WP;

963 964
        let (gens, preds, space) = *self;

965 966 967
        // Bounds in the type_params and lifetimes fields are repeated in the
        // predicates field (see rustc_typeck::collect::ty_generics), so remove
        // them.
968
        let stripped_typarams = gens.types.get_slice(space).iter().map(|tp| {
969
            tp.clean(cx)
970 971 972 973 974 975 976
        }).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<_>>();

977 978
        let mut where_predicates = preds.predicates.get_slice(space)
                                                   .to_vec().clean(cx);
979

980
        // Type parameters and have a Sized bound by default unless removed with
981 982
        // ?Sized.  Scan through the predicates and mark any type parameter with
        // a Sized bound, removing the bounds as we find them.
983 984
        //
        // Note that associated types also have a sized bound by default, but we
985
        // don't actually know the set of associated types right here so that's
986
        // handled in cleaning associated types
987
        let mut sized_params = HashSet::new();
988 989 990 991 992 993 994 995 996
        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
                    }
997
                }
998
                _ => true,
999
            }
1000
        });
1001

1002
        // Run through the type parameters again and insert a ?Sized
1003
        // unbound for any we didn't find to be Sized.
1004
        for tp in &stripped_typarams {
1005 1006 1007
            if !sized_params.contains(&tp.name) {
                where_predicates.push(WP::BoundPredicate {
                    ty: Type::Generic(tp.name.clone()),
1008
                    bounds: vec![TyParamBound::maybe_sized(cx)],
1009 1010 1011 1012 1013 1014 1015 1016
                })
            }
        }

        // 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`

1017
        Generics {
1018
            type_params: simplify::ty_params(stripped_typarams),
1019
            lifetimes: stripped_lifetimes,
1020
            where_predicates: simplify::where_clauses(cx, where_predicates),
1021 1022 1023 1024
        }
    }
}

J
Jorge Aparicio 已提交
1025
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1026
pub struct Method {
1027 1028
    pub generics: Generics,
    pub self_: SelfTy,
1029 1030
    pub unsafety: hir::Unsafety,
    pub constness: hir::Constness,
1031
    pub decl: FnDecl,
1032
    pub abi: Abi,
C
Corey Richardson 已提交
1033 1034
}

1035
impl Clean<Method> for hir::MethodSig {
1036
    fn clean(&self, cx: &DocContext) -> Method {
1037 1038
        let all_inputs = &self.decl.inputs;
        let inputs = match self.explicit_self.node {
1039
            hir::SelfStatic => &**all_inputs,
J
Jorge Aparicio 已提交
1040
            _ => &all_inputs[1..]
1041 1042
        };
        let decl = FnDecl {
1043
            inputs: Arguments {
1044
                values: inputs.clean(cx),
1045
            },
1046
            output: self.decl.output.clean(cx),
1047
            variadic: false,
1048
            attrs: Vec::new()
1049
        };
1050
        Method {
1051 1052
            generics: self.generics.clean(cx),
            self_: self.explicit_self.node.clean(cx),
1053 1054
            unsafety: self.unsafety,
            constness: self.constness,
1055
            decl: decl,
1056
            abi: self.abi
C
Corey Richardson 已提交
1057 1058 1059 1060
        }
    }
}

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

1070
impl Clean<TyMethod> for hir::MethodSig {
1071
    fn clean(&self, cx: &DocContext) -> TyMethod {
1072
        let inputs = match self.explicit_self.node {
1073
            hir::SelfStatic => &*self.decl.inputs,
J
Jorge Aparicio 已提交
1074
            _ => &self.decl.inputs[1..]
1075 1076
        };
        let decl = FnDecl {
1077
            inputs: Arguments {
1078
                values: inputs.clean(cx),
1079
            },
1080
            output: self.decl.output.clean(cx),
1081
            variadic: false,
1082
            attrs: Vec::new()
1083
        };
1084 1085 1086 1087 1088 1089
        TyMethod {
            unsafety: self.unsafety.clone(),
            decl: decl,
            self_: self.explicit_self.node.clean(cx),
            generics: self.generics.clean(cx),
            abi: self.abi
C
Corey Richardson 已提交
1090 1091 1092 1093
        }
    }
}

J
Jorge Aparicio 已提交
1094
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
1095 1096 1097 1098
pub enum SelfTy {
    SelfStatic,
    SelfValue,
    SelfBorrowed(Option<Lifetime>, Mutability),
1099
    SelfExplicit(Type),
C
Corey Richardson 已提交
1100 1101
}

1102
impl Clean<SelfTy> for hir::ExplicitSelf_ {
1103
    fn clean(&self, cx: &DocContext) -> SelfTy {
1104
        match *self {
1105 1106 1107
            hir::SelfStatic => SelfStatic,
            hir::SelfValue(_) => SelfValue,
            hir::SelfRegion(ref lt, ref mt, _) => {
1108
                SelfBorrowed(lt.clean(cx), mt.clean(cx))
1109
            }
1110
            hir::SelfExplicit(ref typ, _) => SelfExplicit(typ.clean(cx)),
C
Corey Richardson 已提交
1111 1112 1113 1114
        }
    }
}

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

impl Clean<Item> for doctree::Function {
1125
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1126
        Item {
1127 1128 1129 1130 1131
            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),
1132
            deprecation: self.depr.clean(cx),
1133
            def_id: cx.map.local_def_id(self.id),
C
Corey Richardson 已提交
1134
            inner: FunctionItem(Function {
1135 1136
                decl: self.decl.clean(cx),
                generics: self.generics.clean(cx),
N
Niko Matsakis 已提交
1137
                unsafety: self.unsafety,
1138
                constness: self.constness,
1139
                abi: self.abi,
C
Corey Richardson 已提交
1140 1141 1142 1143 1144
            }),
        }
    }
}

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

J
Jorge Aparicio 已提交
1153
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1154
pub struct Arguments {
1155
    pub values: Vec<Argument>,
1156 1157
}

1158
impl Clean<FnDecl> for hir::FnDecl {
1159
    fn clean(&self, cx: &DocContext) -> FnDecl {
C
Corey Richardson 已提交
1160
        FnDecl {
1161
            inputs: Arguments {
1162
                values: self.inputs.clean(cx),
1163
            },
1164
            output: self.output.clean(cx),
1165
            variadic: self.variadic,
1166
            attrs: Vec::new()
C
Corey Richardson 已提交
1167 1168 1169 1170
        }
    }
}

1171
impl<'tcx> Clean<Type> for ty::FnOutput<'tcx> {
J
Jakub Bukaj 已提交
1172 1173 1174 1175 1176 1177 1178 1179
    fn clean(&self, cx: &DocContext) -> Type {
        match *self {
            ty::FnConverging(ty) => ty.clean(cx),
            ty::FnDiverging => Bottom
        }
    }
}

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

J
Jorge Aparicio 已提交
1208
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
1209
pub struct Argument {
1210
    pub type_: Type,
1211
    pub name: String,
1212
    pub id: ast::NodeId,
C
Corey Richardson 已提交
1213 1214
}

1215
impl Clean<Argument> for hir::Arg {
1216
    fn clean(&self, cx: &DocContext) -> Argument {
C
Corey Richardson 已提交
1217
        Argument {
1218
            name: name_from_pat(&*self.pat),
1219
            type_: (self.ty.clean(cx)),
C
Corey Richardson 已提交
1220 1221 1222 1223 1224
            id: self.id
        }
    }
}

J
Jorge Aparicio 已提交
1225
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1226 1227
pub enum FunctionRetTy {
    Return(Type),
1228
    DefaultReturn,
1229
    NoReturn
C
Corey Richardson 已提交
1230 1231
}

1232
impl Clean<FunctionRetTy> for hir::FunctionRetTy {
1233
    fn clean(&self, cx: &DocContext) -> FunctionRetTy {
C
Corey Richardson 已提交
1234
        match *self {
1235 1236 1237
            hir::Return(ref typ) => Return(typ.clean(cx)),
            hir::DefaultReturn(..) => DefaultReturn,
            hir::NoReturn(..) => NoReturn
C
Corey Richardson 已提交
1238 1239 1240 1241
        }
    }
}

J
Jorge Aparicio 已提交
1242
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1243
pub struct Trait {
1244
    pub unsafety: hir::Unsafety,
1245
    pub items: Vec<Item>,
1246
    pub generics: Generics,
1247
    pub bounds: Vec<TyParamBound>,
C
Corey Richardson 已提交
1248 1249 1250
}

impl Clean<Item> for doctree::Trait {
1251
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1252
        Item {
1253 1254 1255
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
1256
            def_id: cx.map.local_def_id(self.id),
1257 1258
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
1259
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
1260
            inner: TraitItem(Trait {
1261
                unsafety: self.unsafety,
1262 1263 1264
                items: self.items.clean(cx),
                generics: self.generics.clean(cx),
                bounds: self.bounds.clean(cx),
C
Corey Richardson 已提交
1265 1266 1267 1268 1269
            }),
        }
    }
}

1270
impl Clean<Type> for hir::TraitRef {
1271
    fn clean(&self, cx: &DocContext) -> Type {
N
Niko Matsakis 已提交
1272
        resolve_type(cx, self.path.clean(cx), self.ref_id)
C
Corey Richardson 已提交
1273 1274 1275
    }
}

1276
impl Clean<PolyTrait> for hir::PolyTraitRef {
1277 1278 1279 1280 1281
    fn clean(&self, cx: &DocContext) -> PolyTrait {
        PolyTrait {
            trait_: self.trait_ref.clean(cx),
            lifetimes: self.bound_lifetimes.clean(cx)
        }
N
Niko Matsakis 已提交
1282 1283 1284
    }
}

1285
impl Clean<Item> for hir::TraitItem {
1286 1287
    fn clean(&self, cx: &DocContext) -> Item {
        let inner = match self.node {
1288
            hir::ConstTraitItem(ref ty, ref default) => {
1289
                AssociatedConstItem(ty.clean(cx),
1290
                                    default.as_ref().map(|e| pprust::expr_to_string(&e)))
1291
            }
1292
            hir::MethodTraitItem(ref sig, Some(_)) => {
1293 1294
                MethodItem(sig.clean(cx))
            }
1295
            hir::MethodTraitItem(ref sig, None) => {
1296 1297
                TyMethodItem(sig.clean(cx))
            }
1298
            hir::TypeTraitItem(ref bounds, ref default) => {
1299 1300 1301 1302
                AssociatedTypeItem(bounds.clean(cx), default.clean(cx))
            }
        };
        Item {
V
Vadim Petrochenkov 已提交
1303
            name: Some(self.name.clean(cx)),
1304 1305
            attrs: self.attrs.clean(cx),
            source: self.span.clean(cx),
1306
            def_id: cx.map.local_def_id(self.id),
1307
            visibility: None,
1308
            stability: get_stability(cx, cx.map.local_def_id(self.id)),
1309
            deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
1310
            inner: inner
1311 1312 1313 1314
        }
    }
}

1315
impl Clean<Item> for hir::ImplItem {
1316 1317
    fn clean(&self, cx: &DocContext) -> Item {
        let inner = match self.node {
1318
            hir::ImplItemKind::Const(ref ty, ref expr) => {
1319
                AssociatedConstItem(ty.clean(cx),
1320
                                    Some(pprust::expr_to_string(expr)))
1321
            }
1322
            hir::ImplItemKind::Method(ref sig, _) => {
1323 1324
                MethodItem(sig.clean(cx))
            }
1325
            hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef {
1326 1327 1328 1329 1330 1331
                type_: ty.clean(cx),
                generics: Generics {
                    lifetimes: Vec::new(),
                    type_params: Vec::new(),
                    where_predicates: Vec::new()
                },
1332
            }, true),
1333 1334
        };
        Item {
V
Vadim Petrochenkov 已提交
1335
            name: Some(self.name.clean(cx)),
1336 1337
            source: self.span.clean(cx),
            attrs: self.attrs.clean(cx),
1338
            def_id: cx.map.local_def_id(self.id),
1339
            visibility: self.vis.clean(cx),
1340
            stability: get_stability(cx, cx.map.local_def_id(self.id)),
1341
            deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
1342
            inner: inner
C
Corey Richardson 已提交
1343 1344 1345 1346
        }
    }
}

1347
impl<'tcx> Clean<Item> for ty::Method<'tcx> {
1348
    fn clean(&self, cx: &DocContext) -> Item {
1349
        let (self_, sig) = match self.explicit_self {
1350 1351
            ty::ExplicitSelfCategory::Static => (hir::SelfStatic.clean(cx),
                                                 self.fty.sig.clone()),
1352
            s => {
1353
                let sig = ty::Binder(ty::FnSig {
J
Jorge Aparicio 已提交
1354
                    inputs: self.fty.sig.0.inputs[1..].to_vec(),
1355 1356
                    ..self.fty.sig.0.clone()
                });
1357
                let s = match s {
1358 1359
                    ty::ExplicitSelfCategory::ByValue => SelfValue,
                    ty::ExplicitSelfCategory::ByReference(..) => {
1360
                        match self.fty.sig.0.inputs[0].sty {
1361
                            ty::TyRef(r, mt) => {
1362
                                SelfBorrowed(r.clean(cx), mt.mutbl.clean(cx))
1363
                            }
A
Alex Crichton 已提交
1364
                            _ => unreachable!(),
1365 1366
                        }
                    }
1367
                    ty::ExplicitSelfCategory::ByBox => {
1368
                        SelfExplicit(self.fty.sig.0.inputs[0].clean(cx))
1369
                    }
1370
                    ty::ExplicitSelfCategory::Static => unreachable!(),
1371 1372 1373 1374
                };
                (s, sig)
            }
        };
1375

1376 1377 1378 1379 1380 1381
        let generics = (&self.generics, &self.predicates,
                        subst::FnSpace).clean(cx);
        let decl = (self.def_id, &sig).clean(cx);
        let provided = match self.container {
            ty::ImplContainer(..) => false,
            ty::TraitContainer(did) => {
1382
                cx.tcx().provided_trait_methods(did).iter().any(|m| {
1383 1384 1385 1386 1387 1388 1389 1390 1391 1392
                    m.def_id == self.def_id
                })
            }
        };
        let inner = if provided {
            MethodItem(Method {
                unsafety: self.fty.unsafety,
                generics: generics,
                self_: self_,
                decl: decl,
N
Niko Matsakis 已提交
1393 1394 1395
                abi: self.fty.abi,

                // trait methods canot (currently, at least) be const
1396
                constness: hir::Constness::NotConst,
1397 1398 1399 1400 1401 1402 1403
            })
        } else {
            TyMethodItem(TyMethod {
                unsafety: self.fty.unsafety,
                generics: generics,
                self_: self_,
                decl: decl,
N
Niko Matsakis 已提交
1404
                abi: self.fty.abi,
1405 1406 1407
            })
        };

1408
        Item {
1409
            name: Some(self.name.clean(cx)),
J
Jeffrey Seyfried 已提交
1410
            visibility: Some(Inherited),
1411
            stability: get_stability(cx, self.def_id),
1412
            deprecation: get_deprecation(cx, self.def_id),
1413
            def_id: self.def_id,
1414
            attrs: inline::load_attrs(cx, cx.tcx(), self.def_id),
1415
            source: Span::empty(),
1416
            inner: inner,
1417
        }
1418 1419 1420
    }
}

1421
impl<'tcx> Clean<Item> for ty::ImplOrTraitItem<'tcx> {
1422
    fn clean(&self, cx: &DocContext) -> Item {
1423
        match *self {
1424
            ty::ConstTraitItem(ref cti) => cti.clean(cx),
1425
            ty::MethodTraitItem(ref mti) => mti.clean(cx),
1426
            ty::TypeTraitItem(ref tti) => tti.clean(cx),
1427 1428 1429 1430
        }
    }
}

1431
/// A trait reference, which may have higher ranked lifetimes.
J
Jorge Aparicio 已提交
1432
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1433 1434 1435 1436 1437
pub struct PolyTrait {
    pub trait_: Type,
    pub lifetimes: Vec<Lifetime>
}

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

    // <Type as Trait>::Name
T
Tom Jakubowski 已提交
1473 1474 1475 1476 1477
    QPath {
        name: String,
        self_type: Box<Type>,
        trait_: Box<Type>
    },
1478 1479 1480 1481 1482 1483

    // _
    Infer,

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

J
Jorge Aparicio 已提交
1486
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
1487
pub enum PrimitiveType {
1488 1489
    Isize, I8, I16, I32, I64,
    Usize, U8, U16, U32, U64,
1490
    F32, F64,
1491 1492 1493 1494
    Char,
    Bool,
    Str,
    Slice,
1495
    Array,
1496
    PrimitiveTuple,
1497
    PrimitiveRawPointer,
1498 1499
}

J
Jorge Aparicio 已提交
1500
#[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
1501 1502 1503
pub enum TypeKind {
    TypeEnum,
    TypeFunction,
1504
    TypeModule,
1505
    TypeConst,
1506 1507 1508 1509
    TypeStatic,
    TypeStruct,
    TypeTrait,
    TypeVariant,
1510
    TypeTypedef,
1511 1512
}

1513 1514 1515 1516 1517 1518 1519 1520 1521 1522
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())
    }
}

1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535
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,
        }
    }
1536 1537 1538 1539 1540 1541 1542

    pub fn trait_name(&self) -> Option<String> {
        match *self {
            ResolvedPath { ref path, .. } => Some(path.last_name()),
            _ => None,
        }
    }
1543 1544 1545 1546 1547 1548 1549

    pub fn is_generic(&self) -> bool {
        match *self {
            ResolvedPath { is_generic, .. } => is_generic,
            _ => false,
        }
    }
1550
}
1551

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

1561 1562
impl PrimitiveType {
    fn from_str(s: &str) -> Option<PrimitiveType> {
1563
        match s {
1564
            "isize" => Some(Isize),
1565 1566 1567 1568
            "i8" => Some(I8),
            "i16" => Some(I16),
            "i32" => Some(I32),
            "i64" => Some(I64),
1569
            "usize" => Some(Usize),
1570 1571 1572 1573 1574 1575 1576 1577 1578
            "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),
1579
            "array" => Some(Array),
1580 1581
            "slice" => Some(Slice),
            "tuple" => Some(PrimitiveTuple),
1582
            "pointer" => Some(PrimitiveRawPointer),
1583 1584 1585 1586
            _ => None,
        }
    }

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

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

    pub fn to_url_str(&self) -> &'static str {
1625
        self.to_string()
1626 1627 1628 1629 1630
    }

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

1637
impl Clean<Type> for hir::Ty {
1638
    fn clean(&self, cx: &DocContext) -> Type {
1639
        use rustc::hir::*;
1640
        match self.node {
1641
            TyPtr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
1642
            TyRptr(ref l, ref m) =>
1643 1644
                BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx),
                             type_: box m.ty.clean(cx)},
1645
            TyVec(ref ty) => Vector(box ty.clean(cx)),
1646 1647
            TyFixedLengthVec(ref ty, ref e) =>
                FixedVector(box ty.clean(cx), pprust::expr_to_string(e)),
1648
            TyTup(ref tys) => Tuple(tys.clean(cx)),
1649
            TyPath(None, ref p) => {
1650
                resolve_type(cx, p.clean(cx), self.id)
N
Niko Matsakis 已提交
1651
            }
1652
            TyPath(Some(ref qself), ref p) => {
1653 1654 1655 1656 1657 1658 1659
                let mut segments: Vec<_> = p.segments.clone().into();
                segments.pop();
                let trait_path = hir::Path {
                    span: p.span,
                    global: p.global,
                    segments: segments.into(),
                };
1660
                Type::QPath {
1661
                    name: p.segments.last().unwrap().identifier.name.clean(cx),
1662
                    self_type: box qself.ty.clean(cx),
1663
                    trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
1664 1665
                }
            }
N
Niko Matsakis 已提交
1666 1667 1668
            TyObjectSum(ref lhs, ref bounds) => {
                let lhs_ty = lhs.clean(cx);
                match lhs_ty {
1669 1670 1671 1672 1673 1674 1675
                    ResolvedPath { path, typarams: None, did, is_generic } => {
                        ResolvedPath {
                            path: path,
                            typarams: Some(bounds.clean(cx)),
                            did: did,
                            is_generic: is_generic,
                        }
N
Niko Matsakis 已提交
1676 1677 1678 1679 1680
                    }
                    _ => {
                        lhs_ty // shouldn't happen
                    }
                }
1681
            }
1682
            TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
M
mitaa 已提交
1683 1684 1685
            TyPolyTraitRef(ref bounds) => PolyTraitRef(bounds.clean(cx)),
            TyInfer => Infer,
            TyTypeof(..) => panic!("Unimplemented type {:?}", self.node),
1686
        }
C
Corey Richardson 已提交
1687 1688 1689
    }
}

1690
impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
1691
    fn clean(&self, cx: &DocContext) -> Type {
1692
        match self.sty {
1693 1694
            ty::TyBool => Primitive(Bool),
            ty::TyChar => Primitive(Char),
1695 1696 1697 1698 1699 1700 1701 1702 1703 1704
            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),
1705 1706
            ty::TyFloat(ast::FloatTy::F32) => Primitive(F32),
            ty::TyFloat(ast::FloatTy::F64) => Primitive(F64),
1707 1708
            ty::TyStr => Primitive(Str),
            ty::TyBox(t) => {
1709
                let box_did = cx.tcx_opt().and_then(|tcx| {
A
Alex Crichton 已提交
1710 1711
                    tcx.lang_items.owned_box()
                });
1712
                lang_struct(cx, box_did, t, "Box", Unique)
A
Alex Crichton 已提交
1713
            }
1714 1715 1716
            ty::TySlice(ty) => Vector(box ty.clean(cx)),
            ty::TyArray(ty, i) => FixedVector(box ty.clean(cx),
                                              format!("{}", i)),
1717 1718
            ty::TyRawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
            ty::TyRef(r, mt) => BorrowedRef {
1719 1720 1721
                lifetime: r.clean(cx),
                mutability: mt.mutbl.clean(cx),
                type_: box mt.ty.clean(cx),
1722
            },
1723
            ty::TyFnDef(_, _, ref fty) |
1724
            ty::TyFnPtr(ref fty) => BareFunction(box BareFunctionDecl {
N
Niko Matsakis 已提交
1725
                unsafety: fty.unsafety,
1726
                generics: Generics {
1727 1728 1729
                    lifetimes: Vec::new(),
                    type_params: Vec::new(),
                    where_predicates: Vec::new()
1730
                },
1731
                decl: (cx.map.local_def_id(0), &fty.sig).clean(cx),
1732
                abi: fty.abi,
1733
            }),
1734 1735 1736
            ty::TyStruct(def, substs) |
            ty::TyEnum(def, substs) => {
                let did = def.did;
1737
                let kind = match self.sty {
1738
                    ty::TyStruct(..) => TypeStruct,
1739 1740
                    _ => TypeEnum,
                };
M
mitaa 已提交
1741 1742
                inline::record_extern_fqn(cx, did, kind);
                let path = external_path(cx, &cx.tcx().item_name(did).as_str(),
1743
                                         None, vec![], substs);
1744
                ResolvedPath {
1745
                    path: path,
1746 1747
                    typarams: None,
                    did: did,
1748
                    is_generic: false,
1749 1750
                }
            }
1751
            ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => {
1752
                let did = principal.def_id();
M
mitaa 已提交
1753
                inline::record_extern_fqn(cx, did, TypeTrait);
1754
                let (typarams, bindings) = bounds.clean(cx);
M
mitaa 已提交
1755
                let path = external_path(cx, &cx.tcx().item_name(did).as_str(),
1756
                                         Some(did), bindings, principal.substs());
1757 1758
                ResolvedPath {
                    path: path,
1759
                    typarams: Some(typarams),
1760
                    did: did,
1761
                    is_generic: false,
1762 1763
                }
            }
1764
            ty::TyTuple(ref t) => Tuple(t.clean(cx)),
1765

1766
            ty::TyProjection(ref data) => data.clean(cx),
1767

1768
            ty::TyParam(ref p) => Generic(p.name.to_string()),
1769

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

1772 1773
            ty::TyInfer(..) => panic!("TyInfer"),
            ty::TyError => panic!("TyError"),
1774 1775 1776 1777
        }
    }
}

1778
impl Clean<Item> for hir::StructField {
1779
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1780
        Item {
1781 1782
            name: Some(self.name).clean(cx),
            attrs: self.attrs.clean(cx),
1783
            source: self.span.clean(cx),
1784
            visibility: self.vis.clean(cx),
1785 1786 1787
            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),
1788
            inner: StructFieldItem(self.ty.clean(cx)),
C
Corey Richardson 已提交
1789 1790 1791 1792
        }
    }
}

A
Ariel Ben-Yehuda 已提交
1793
impl<'tcx> Clean<Item> for ty::FieldDefData<'tcx, 'static> {
1794
    fn clean(&self, cx: &DocContext) -> Item {
A
Ariel Ben-Yehuda 已提交
1795
        // FIXME: possible O(n^2)-ness! Not my fault.
1796
        let attr_map = cx.tcx().sess.cstore.crate_struct_field_attrs(self.did.krate);
1797
        Item {
1798 1799
            name: Some(self.name).clean(cx),
            attrs: attr_map.get(&self.did).unwrap_or(&Vec::new()).clean(cx),
1800
            source: Span::empty(),
1801
            visibility: self.vis.clean(cx),
1802
            stability: get_stability(cx, self.did),
1803
            deprecation: get_deprecation(cx, self.did),
1804
            def_id: self.did,
1805
            inner: StructFieldItem(self.unsubst_ty().clean(cx)),
1806 1807 1808 1809
        }
    }
}

J
Jeffrey Seyfried 已提交
1810 1811 1812 1813 1814
#[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug)]
pub enum Visibility {
    Public,
    Inherited,
}
C
Corey Richardson 已提交
1815

1816
impl Clean<Option<Visibility>> for hir::Visibility {
1817
    fn clean(&self, _: &DocContext) -> Option<Visibility> {
J
Jeffrey Seyfried 已提交
1818
        Some(if *self == hir::Visibility::Public { Public } else { Inherited })
1819 1820 1821 1822 1823
    }
}

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

J
Jorge Aparicio 已提交
1828
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1829
pub struct Struct {
1830 1831 1832 1833
    pub struct_type: doctree::StructType,
    pub generics: Generics,
    pub fields: Vec<Item>,
    pub fields_stripped: bool,
C
Corey Richardson 已提交
1834 1835 1836
}

impl Clean<Item> for doctree::Struct {
1837
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1838
        Item {
1839 1840 1841
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
1842
            def_id: cx.map.local_def_id(self.id),
1843 1844
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
1845
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
1846 1847
            inner: StructItem(Struct {
                struct_type: self.struct_type,
1848 1849
                generics: self.generics.clean(cx),
                fields: self.fields.clean(cx),
S
Steven Fackler 已提交
1850
                fields_stripped: false,
C
Corey Richardson 已提交
1851 1852 1853 1854 1855
            }),
        }
    }
}

1856
/// This is a more limited form of the standard Struct, different in that
C
Corey Richardson 已提交
1857 1858
/// it lacks the things most items have (name, id, parameterization). Found
/// only as a variant in an enum.
J
Jorge Aparicio 已提交
1859
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1860
pub struct VariantStruct {
1861 1862 1863
    pub struct_type: doctree::StructType,
    pub fields: Vec<Item>,
    pub fields_stripped: bool,
C
Corey Richardson 已提交
1864 1865
}

1866
impl Clean<VariantStruct> for ::rustc::hir::VariantData {
1867
    fn clean(&self, cx: &DocContext) -> VariantStruct {
C
Corey Richardson 已提交
1868 1869
        VariantStruct {
            struct_type: doctree::struct_type_from_def(self),
1870
            fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
S
Steven Fackler 已提交
1871
            fields_stripped: false,
C
Corey Richardson 已提交
1872 1873 1874 1875
        }
    }
}

J
Jorge Aparicio 已提交
1876
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1877
pub struct Enum {
1878 1879 1880
    pub variants: Vec<Item>,
    pub generics: Generics,
    pub variants_stripped: bool,
C
Corey Richardson 已提交
1881 1882 1883
}

impl Clean<Item> for doctree::Enum {
1884
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1885
        Item {
1886 1887 1888
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
1889
            def_id: cx.map.local_def_id(self.id),
1890 1891
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
1892
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
1893
            inner: EnumItem(Enum {
1894 1895
                variants: self.variants.clean(cx),
                generics: self.generics.clean(cx),
S
Steven Fackler 已提交
1896
                variants_stripped: false,
C
Corey Richardson 已提交
1897 1898 1899 1900 1901
            }),
        }
    }
}

J
Jorge Aparicio 已提交
1902
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1903
pub struct Variant {
1904
    pub kind: VariantKind,
C
Corey Richardson 已提交
1905 1906 1907
}

impl Clean<Item> for doctree::Variant {
1908
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1909
        Item {
1910 1911 1912
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
1913
            visibility: None,
1914
            stability: self.stab.clean(cx),
1915
            deprecation: self.depr.clean(cx),
1916
            def_id: cx.map.local_def_id(self.def.id()),
C
Corey Richardson 已提交
1917
            inner: VariantItem(Variant {
1918
                kind: struct_def_to_variant_kind(&self.def, cx),
C
Corey Richardson 已提交
1919 1920 1921 1922 1923
            }),
        }
    }
}

A
Ariel Ben-Yehuda 已提交
1924
impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
1925
    fn clean(&self, cx: &DocContext) -> Item {
1926 1927 1928 1929 1930 1931
        let kind = match self.kind() {
            ty::VariantKind::Unit => CLikeVariant,
            ty::VariantKind::Tuple => {
                TupleVariant(
                    self.fields.iter().map(|f| f.unsubst_ty().clean(cx)).collect()
                )
1932
            }
1933
            ty::VariantKind::Struct => {
1934 1935 1936
                StructVariant(VariantStruct {
                    struct_type: doctree::Plain,
                    fields_stripped: false,
1937
                    fields: self.fields.iter().map(|field| {
1938 1939
                        Item {
                            source: Span::empty(),
1940
                            name: Some(field.name.clean(cx)),
1941
                            attrs: cx.tcx().get_attrs(field.did).clean(cx),
1942
                            visibility: field.vis.clean(cx),
1943 1944 1945
                            def_id: field.did,
                            stability: get_stability(cx, field.did),
                            deprecation: get_deprecation(cx, field.did),
1946
                            inner: StructFieldItem(field.unsubst_ty().clean(cx))
1947 1948 1949 1950 1951 1952
                        }
                    }).collect()
                })
            }
        };
        Item {
1953
            name: Some(self.name.clean(cx)),
1954
            attrs: inline::load_attrs(cx, cx.tcx(), self.did),
1955
            source: Span::empty(),
J
Jeffrey Seyfried 已提交
1956
            visibility: Some(Inherited),
1957
            def_id: self.did,
1958
            inner: VariantItem(Variant { kind: kind }),
1959
            stability: get_stability(cx, self.did),
1960
            deprecation: get_deprecation(cx, self.did),
1961 1962 1963 1964
        }
    }
}

J
Jorge Aparicio 已提交
1965
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1966 1967
pub enum VariantKind {
    CLikeVariant,
1968
    TupleVariant(Vec<Type>),
C
Corey Richardson 已提交
1969 1970 1971
    StructVariant(VariantStruct),
}

1972
fn struct_def_to_variant_kind(struct_def: &hir::VariantData, cx: &DocContext) -> VariantKind {
1973
    if struct_def.is_struct() {
1974
        StructVariant(struct_def.clean(cx))
1975
    } else if struct_def.is_unit() {
1976 1977
        CLikeVariant
    } else {
1978
        TupleVariant(struct_def.fields().iter().map(|x| x.ty.clean(cx)).collect())
1979 1980 1981
    }
}

J
Jorge Aparicio 已提交
1982
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1983
pub struct Span {
1984
    pub filename: String,
1985 1986 1987 1988
    pub loline: usize,
    pub locol: usize,
    pub hiline: usize,
    pub hicol: usize,
1989 1990
}

1991 1992 1993
impl Span {
    fn empty() -> Span {
        Span {
1994
            filename: "".to_string(),
1995 1996 1997 1998 1999 2000
            loline: 0, locol: 0,
            hiline: 0, hicol: 0,
        }
    }
}

2001
impl Clean<Span> for syntax::codemap::Span {
2002
    fn clean(&self, cx: &DocContext) -> Span {
2003 2004 2005 2006
        if *self == DUMMY_SP {
            return Span::empty();
        }

2007
        let cm = cx.sess().codemap();
2008 2009 2010 2011
        let filename = cm.span_to_filename(*self);
        let lo = cm.lookup_char_pos(self.lo);
        let hi = cm.lookup_char_pos(self.hi);
        Span {
2012
            filename: filename.to_string(),
2013
            loline: lo.line,
2014
            locol: lo.col.to_usize(),
2015
            hiline: hi.line,
2016
            hicol: hi.col.to_usize(),
2017
        }
C
Corey Richardson 已提交
2018 2019 2020
    }
}

J
Jorge Aparicio 已提交
2021
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
2022
pub struct Path {
2023 2024
    pub global: bool,
    pub segments: Vec<PathSegment>,
C
Corey Richardson 已提交
2025 2026
}

2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040
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()
                }
            }]
        }
    }
2041 2042 2043 2044

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

2047
impl Clean<Path> for hir::Path {
2048
    fn clean(&self, cx: &DocContext) -> Path {
C
Corey Richardson 已提交
2049
        Path {
2050
            global: self.global,
2051
            segments: self.segments.clean(cx),
2052 2053 2054 2055
        }
    }
}

J
Jorge Aparicio 已提交
2056
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2057 2058 2059 2060
pub enum PathParameters {
    AngleBracketed {
        lifetimes: Vec<Lifetime>,
        types: Vec<Type>,
2061
        bindings: Vec<TypeBinding>
2062 2063 2064 2065 2066
    },
    Parenthesized {
        inputs: Vec<Type>,
        output: Option<Type>
    }
2067 2068
}

2069
impl Clean<PathParameters> for hir::PathParameters {
2070 2071
    fn clean(&self, cx: &DocContext) -> PathParameters {
        match *self {
2072
            hir::AngleBracketedParameters(ref data) => {
2073 2074
                PathParameters::AngleBracketed {
                    lifetimes: data.lifetimes.clean(cx),
2075 2076
                    types: data.types.clean(cx),
                    bindings: data.bindings.clean(cx)
2077
                }
2078 2079
            }

2080
            hir::ParenthesizedParameters(ref data) => {
2081 2082 2083 2084
                PathParameters::Parenthesized {
                    inputs: data.inputs.clean(cx),
                    output: data.output.clean(cx)
                }
2085
            }
2086 2087 2088
        }
    }
}
2089

J
Jorge Aparicio 已提交
2090
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2091 2092 2093 2094 2095
pub struct PathSegment {
    pub name: String,
    pub params: PathParameters
}

2096
impl Clean<PathSegment> for hir::PathSegment {
2097
    fn clean(&self, cx: &DocContext) -> PathSegment {
2098
        PathSegment {
2099
            name: self.identifier.name.clean(cx),
2100
            params: self.parameters.clean(cx)
C
Corey Richardson 已提交
2101 2102 2103 2104
        }
    }
}

2105
fn path_to_string(p: &hir::Path) -> String {
2106
    let mut s = String::new();
C
Corey Richardson 已提交
2107
    let mut first = true;
2108
    for i in p.segments.iter().map(|x| x.identifier.name.as_str()) {
C
Corey Richardson 已提交
2109 2110 2111 2112 2113
        if !first || p.global {
            s.push_str("::");
        } else {
            first = false;
        }
G
GuillaumeGomez 已提交
2114
        s.push_str(&i);
C
Corey Richardson 已提交
2115
    }
2116
    s
C
Corey Richardson 已提交
2117 2118
}

2119
impl Clean<String> for ast::Name {
2120
    fn clean(&self, _: &DocContext) -> String {
2121
        self.to_string()
2122 2123 2124
    }
}

J
Jorge Aparicio 已提交
2125
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
2126
pub struct Typedef {
2127 2128
    pub type_: Type,
    pub generics: Generics,
C
Corey Richardson 已提交
2129 2130 2131
}

impl Clean<Item> for doctree::Typedef {
2132
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
2133
        Item {
2134 2135 2136
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2137
            def_id: cx.map.local_def_id(self.id.clone()),
2138 2139
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
2140
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
2141
            inner: TypedefItem(Typedef {
2142 2143
                type_: self.ty.clean(cx),
                generics: self.gen.clean(cx),
2144
            }, false),
C
Corey Richardson 已提交
2145 2146 2147 2148
        }
    }
}

J
Jorge Aparicio 已提交
2149
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
2150
pub struct BareFunctionDecl {
2151
    pub unsafety: hir::Unsafety,
2152 2153
    pub generics: Generics,
    pub decl: FnDecl,
2154
    pub abi: Abi,
C
Corey Richardson 已提交
2155 2156
}

2157
impl Clean<BareFunctionDecl> for hir::BareFnTy {
2158
    fn clean(&self, cx: &DocContext) -> BareFunctionDecl {
C
Corey Richardson 已提交
2159
        BareFunctionDecl {
N
Niko Matsakis 已提交
2160
            unsafety: self.unsafety,
C
Corey Richardson 已提交
2161
            generics: Generics {
2162
                lifetimes: self.lifetimes.clean(cx),
2163
                type_params: Vec::new(),
2164
                where_predicates: Vec::new()
C
Corey Richardson 已提交
2165
            },
2166
            decl: self.decl.clean(cx),
2167
            abi: self.abi,
C
Corey Richardson 已提交
2168 2169 2170 2171
        }
    }
}

J
Jorge Aparicio 已提交
2172
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
2173
pub struct Static {
2174 2175
    pub type_: Type,
    pub mutability: Mutability,
C
Corey Richardson 已提交
2176 2177 2178
    /// 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.
2179
    pub expr: String,
C
Corey Richardson 已提交
2180 2181 2182
}

impl Clean<Item> for doctree::Static {
2183
    fn clean(&self, cx: &DocContext) -> Item {
2184
        debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
C
Corey Richardson 已提交
2185
        Item {
2186 2187 2188
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2189
            def_id: cx.map.local_def_id(self.id),
2190 2191
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
2192
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
2193
            inner: StaticItem(Static {
2194 2195
                type_: self.type_.clean(cx),
                mutability: self.mutability.clean(cx),
2196
                expr: pprust::expr_to_string(&self.expr),
C
Corey Richardson 已提交
2197 2198 2199 2200 2201
            }),
        }
    }
}

J
Jorge Aparicio 已提交
2202
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213
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),
2214
            def_id: cx.map.local_def_id(self.id),
2215 2216
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
2217
            deprecation: self.depr.clean(cx),
2218 2219
            inner: ConstantItem(Constant {
                type_: self.type_.clean(cx),
2220
                expr: pprust::expr_to_string(&self.expr),
2221 2222 2223 2224 2225
            }),
        }
    }
}

J
Jorge Aparicio 已提交
2226
#[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Copy)]
C
Corey Richardson 已提交
2227 2228 2229 2230 2231
pub enum Mutability {
    Mutable,
    Immutable,
}

2232
impl Clean<Mutability> for hir::Mutability {
2233
    fn clean(&self, _: &DocContext) -> Mutability {
C
Corey Richardson 已提交
2234
        match self {
2235 2236
            &hir::MutMutable => Mutable,
            &hir::MutImmutable => Immutable,
C
Corey Richardson 已提交
2237 2238 2239 2240
        }
    }
}

J
Jorge Aparicio 已提交
2241
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Copy, Debug)]
2242 2243 2244 2245 2246
pub enum ImplPolarity {
    Positive,
    Negative,
}

2247
impl Clean<ImplPolarity> for hir::ImplPolarity {
2248 2249
    fn clean(&self, _: &DocContext) -> ImplPolarity {
        match self {
2250 2251
            &hir::ImplPolarity::Positive => ImplPolarity::Positive,
            &hir::ImplPolarity::Negative => ImplPolarity::Negative,
2252 2253 2254 2255
        }
    }
}

J
Jorge Aparicio 已提交
2256
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
2257
pub struct Impl {
2258
    pub unsafety: hir::Unsafety,
2259
    pub generics: Generics,
2260
    pub provided_trait_methods: HashSet<String>,
2261 2262
    pub trait_: Option<Type>,
    pub for_: Type,
2263
    pub items: Vec<Item>,
2264
    pub derived: bool,
2265
    pub polarity: Option<ImplPolarity>,
C
Corey Richardson 已提交
2266 2267
}

2268
fn detect_derived<M: AttrMetaMethods>(attrs: &[M]) -> bool {
2269
    attr::contains_name(attrs, "automatically_derived")
2270 2271
}

2272 2273 2274 2275 2276 2277 2278 2279
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.
2280 2281
        if trait_.def_id() == cx.deref_trait_did.get() {
            build_deref_target_impls(cx, &items, &mut ret);
2282 2283
        }

2284 2285 2286 2287 2288 2289 2290 2291 2292
        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());

2293
        ret.push(Item {
C
Corey Richardson 已提交
2294
            name: None,
2295 2296
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2297
            def_id: cx.map.local_def_id(self.id),
2298 2299
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
2300
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
2301
            inner: ImplItem(Impl {
2302
                unsafety: self.unsafety,
2303
                generics: self.generics.clean(cx),
2304
                provided_trait_methods: provided,
2305
                trait_: trait_,
2306
                for_: self.for_.clean(cx),
2307
                items: items,
2308
                derived: detect_derived(&self.attrs),
2309
                polarity: Some(self.polarity.clean(cx)),
C
Corey Richardson 已提交
2310
            }),
2311
        });
M
mitaa 已提交
2312
        ret
2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325
    }
}

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 {
2326
            TypedefItem(ref t, true) => &t.type_,
2327 2328 2329
            _ => continue,
        };
        let primitive = match *target {
N
Niko Matsakis 已提交
2330
            ResolvedPath { did, .. } if did.is_local() => continue,
2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361
            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 已提交
2362
            if !did.is_local() {
2363 2364
                inline::build_impl(cx, tcx, did, ret);
            }
C
Corey Richardson 已提交
2365 2366 2367 2368
        }
    }
}

2369 2370
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct DefaultImpl {
2371
    pub unsafety: hir::Unsafety,
2372 2373 2374 2375 2376 2377 2378 2379 2380
    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),
2381
            def_id: cx.map.local_def_id(self.id),
J
Jeffrey Seyfried 已提交
2382
            visibility: Some(Public),
2383
            stability: None,
2384
            deprecation: None,
2385 2386 2387 2388 2389 2390 2391 2392
            inner: DefaultImplItem(DefaultImpl {
                unsafety: self.unsafety,
                trait_: self.trait_.clean(cx),
            }),
        }
    }
}

2393 2394 2395 2396 2397 2398
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 已提交
2399
            def_id: DefId { krate: self.cnum, index: CRATE_DEF_INDEX },
2400 2401
            visibility: self.vis.clean(cx),
            stability: None,
2402
            deprecation: None,
2403 2404 2405
            inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
        }
    }
C
Corey Richardson 已提交
2406 2407
}

2408
impl Clean<Vec<Item>> for doctree::Import {
2409
    fn clean(&self, cx: &DocContext) -> Vec<Item> {
J
Joseph Crail 已提交
2410
        // We consider inlining the documentation of `pub use` statements, but we
2411 2412
        // forcefully don't inline if this is not public or if the
        // #[doc(no_inline)] attribute is present.
2413
        let denied = self.vis != hir::Public || self.attrs.iter().any(|a| {
2414
            &a.name()[..] == "doc" && match a.meta_item_list() {
2415
                Some(l) => attr::contains_name(l, "no_inline"),
2416 2417 2418
                None => false,
            }
        });
2419
        let (mut ret, inner) = match self.node {
2420
            hir::ViewPathGlob(ref p) => {
2421
                (vec![], GlobImport(resolve_use_source(cx, p.clean(cx), self.id)))
2422
            }
2423
            hir::ViewPathList(ref p, ref list) => {
2424 2425 2426 2427 2428 2429
                // 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![];
2430
                    for path in list {
2431
                        match inline::try_inline(cx, path.node.id(), path.node.rename()) {
2432
                            Some(items) => {
2433
                                ret.extend(items);
2434 2435 2436
                            }
                            None => {
                                remaining.push(path.clean(cx));
2437 2438 2439
                            }
                        }
                    }
2440 2441 2442
                    remaining
                } else {
                    list.clean(cx)
P
Patrick Walton 已提交
2443
                };
2444 2445 2446 2447 2448
                if remaining.is_empty() {
                    return ret;
                }
                (ret, ImportList(resolve_use_source(cx, p.clean(cx), self.id),
                                 remaining))
P
Patrick Walton 已提交
2449
            }
2450
            hir::ViewPathSimple(name, ref p) => {
2451
                if !denied {
M
mitaa 已提交
2452 2453
                    if let Some(items) = inline::try_inline(cx, self.id, Some(name)) {
                        return items;
2454 2455
                    }
                }
2456
                (vec![], SimpleImport(name.clean(cx),
2457
                                      resolve_use_source(cx, p.clean(cx), self.id)))
2458
            }
2459 2460 2461 2462 2463
        };
        ret.push(Item {
            name: None,
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2464
            def_id: cx.map.local_def_id(0),
2465 2466
            visibility: self.vis.clean(cx),
            stability: None,
2467
            deprecation: None,
2468 2469 2470
            inner: ImportItem(inner)
        });
        ret
C
Corey Richardson 已提交
2471 2472 2473
    }
}

J
Jorge Aparicio 已提交
2474
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2475
pub enum Import {
2476
    // use source as str;
2477
    SimpleImport(String, ImportSource),
A
Alex Crichton 已提交
2478 2479 2480
    // use source::*;
    GlobImport(ImportSource),
    // use source::{a, b, c};
2481
    ImportList(ImportSource, Vec<ViewListIdent>),
A
Alex Crichton 已提交
2482 2483
}

J
Jorge Aparicio 已提交
2484
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
A
Alex Crichton 已提交
2485
pub struct ImportSource {
2486
    pub path: Path,
N
Niko Matsakis 已提交
2487
    pub did: Option<DefId>,
C
Corey Richardson 已提交
2488 2489
}

J
Jorge Aparicio 已提交
2490
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
A
Alex Crichton 已提交
2491
pub struct ViewListIdent {
2492
    pub name: String,
2493
    pub rename: Option<String>,
N
Niko Matsakis 已提交
2494
    pub source: Option<DefId>,
A
Alex Crichton 已提交
2495
}
C
Corey Richardson 已提交
2496

2497
impl Clean<ViewListIdent> for hir::PathListItem {
2498
    fn clean(&self, cx: &DocContext) -> ViewListIdent {
J
Jakub Wieczorek 已提交
2499
        match self.node {
2500
            hir::PathListIdent { id, name, rename } => ViewListIdent {
2501
                name: name.clean(cx),
2502
                rename: rename.map(|r| r.clean(cx)),
2503
                source: resolve_def(cx, id)
J
Jakub Wieczorek 已提交
2504
            },
2505
            hir::PathListMod { id, rename } => ViewListIdent {
2506
                name: "self".to_string(),
2507
                rename: rename.map(|r| r.clean(cx)),
2508
                source: resolve_def(cx, id)
J
Jakub Wieczorek 已提交
2509
            }
A
Alex Crichton 已提交
2510
        }
C
Corey Richardson 已提交
2511 2512 2513
    }
}

2514
impl Clean<Vec<Item>> for hir::ForeignMod {
2515
    fn clean(&self, cx: &DocContext) -> Vec<Item> {
2516 2517
        let mut items = self.items.clean(cx);
        for item in &mut items {
M
mitaa 已提交
2518 2519
            if let ForeignFunctionItem(ref mut f) = item.inner {
                f.abi = self.abi;
2520 2521 2522
            }
        }
        items
2523 2524 2525
    }
}

2526
impl Clean<Item> for hir::ForeignItem {
2527
    fn clean(&self, cx: &DocContext) -> Item {
2528
        let inner = match self.node {
2529
            hir::ForeignItemFn(ref decl, ref generics) => {
2530
                ForeignFunctionItem(Function {
2531 2532
                    decl: decl.clean(cx),
                    generics: generics.clean(cx),
2533
                    unsafety: hir::Unsafety::Unsafe,
2534
                    abi: Abi::Rust,
2535
                    constness: hir::Constness::NotConst,
2536 2537
                })
            }
2538
            hir::ForeignItemStatic(ref ty, mutbl) => {
2539
                ForeignStaticItem(Static {
2540
                    type_: ty.clean(cx),
2541
                    mutability: if mutbl {Mutable} else {Immutable},
2542
                    expr: "".to_string(),
2543 2544 2545 2546
                })
            }
        };
        Item {
V
Vadim Petrochenkov 已提交
2547
            name: Some(self.name.clean(cx)),
2548 2549
            attrs: self.attrs.clean(cx),
            source: self.span.clean(cx),
2550
            def_id: cx.map.local_def_id(self.id),
2551
            visibility: self.vis.clean(cx),
2552
            stability: get_stability(cx, cx.map.local_def_id(self.id)),
2553
            deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
2554 2555 2556 2557 2558
            inner: inner,
        }
    }
}

C
Corey Richardson 已提交
2559 2560 2561
// Utilities

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

2565
impl ToSource for syntax::codemap::Span {
2566
    fn to_src(&self, cx: &DocContext) -> String {
2567
        debug!("converting span {:?} to snippet", self.clean(cx));
2568
        let sn = match cx.sess().codemap().span_to_snippet(*self) {
2569 2570
            Ok(x) => x.to_string(),
            Err(_) => "".to_string()
C
Corey Richardson 已提交
2571
        };
2572
        debug!("got snippet {}", sn);
C
Corey Richardson 已提交
2573 2574 2575 2576
        sn
    }
}

2577
fn lit_to_string(lit: &ast::Lit) -> String {
C
Corey Richardson 已提交
2578
    match lit.node {
2579 2580 2581
        ast::LitKind::Str(ref st, _) => st.to_string(),
        ast::LitKind::ByteStr(ref data) => format!("{:?}", data),
        ast::LitKind::Byte(b) => {
2582
            let mut res = String::from("b'");
2583
            for c in (b as char).escape_default() {
2584
                res.push(c);
2585
            }
2586
            res.push('\'');
2587 2588
            res
        },
2589 2590 2591 2592 2593
        ast::LitKind::Char(c) => format!("'{}'", c),
        ast::LitKind::Int(i, _t) => i.to_string(),
        ast::LitKind::Float(ref f, _t) => f.to_string(),
        ast::LitKind::FloatUnsuffixed(ref f) => f.to_string(),
        ast::LitKind::Bool(b) => b.to_string(),
C
Corey Richardson 已提交
2594 2595 2596
    }
}

2597
fn name_from_pat(p: &hir::Pat) -> String {
2598
    use rustc::hir::*;
2599
    debug!("Trying to get a name from pattern: {:?}", p);
2600

C
Corey Richardson 已提交
2601
    match p.node {
2602 2603
        PatKind::Wild => "_".to_string(),
        PatKind::Ident(_, ref p, _) => p.node.to_string(),
2604
        PatKind::TupleStruct(ref p, _) | PatKind::Path(ref p) => path_to_string(p),
2605
        PatKind::QPath(..) => panic!("tried to get argument name from PatKind::QPath, \
2606
                                which is not allowed in function arguments"),
2607
        PatKind::Struct(ref name, ref fields, etc) => {
2608
            format!("{} {{ {}{} }}", path_to_string(name),
2609
                fields.iter().map(|&Spanned { node: ref fp, .. }|
2610
                                  format!("{}: {}", fp.name, name_from_pat(&*fp.pat)))
2611
                             .collect::<Vec<String>>().join(", "),
2612 2613 2614
                if etc { ", ..." } else { "" }
            )
        },
2615
        PatKind::Tup(ref elts) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
2616
                                            .collect::<Vec<String>>().join(", ")),
2617 2618 2619 2620
        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, \
2621
                  which is silly in function arguments");
2622
            "()".to_string()
2623
        },
2624
        PatKind::Range(..) => panic!("tried to get argument name from PatKind::Range, \
2625
                              which is not allowed in function arguments"),
2626
        PatKind::Vec(ref begin, ref mid, ref end) => {
2627 2628 2629
            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));
2630
            format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
2631
        },
C
Corey Richardson 已提交
2632 2633 2634 2635
    }
}

/// Given a Type, resolve it using the def_map
N
Niko Matsakis 已提交
2636 2637
fn resolve_type(cx: &DocContext,
                path: Path,
2638
                id: ast::NodeId) -> Type {
2639
    debug!("resolve_type({:?},{:?})", path, id);
2640 2641
    let tcx = match cx.tcx_opt() {
        Some(tcx) => tcx,
2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653
        // 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
            };
        }
2654
    };
M
mitaa 已提交
2655
    let def = tcx.def_map.borrow().get(&id).expect("unresolved id not in defmap").full_def();
2656 2657
    debug!("resolve_type: def={:?}", def);

2658
    let is_generic = match def {
2659
        Def::PrimTy(p) => match p {
2660 2661 2662
            hir::TyStr => return Primitive(Str),
            hir::TyBool => return Primitive(Bool),
            hir::TyChar => return Primitive(Char),
2663 2664 2665 2666 2667 2668 2669 2670 2671 2672
            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),
2673 2674
            hir::TyFloat(ast::FloatTy::F32) => return Primitive(F32),
            hir::TyFloat(ast::FloatTy::F64) => return Primitive(F64),
C
Corey Richardson 已提交
2675
        },
2676
        Def::SelfTy(..) if path.segments.len() == 1 => {
2677
            return Generic(keywords::SelfType.name().to_string());
2678
        }
2679
        Def::SelfTy(..) | Def::TyParam(..) => true,
2680
        _ => false,
2681
    };
2682
    let did = register_def(&*cx, def);
2683
    ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
2684 2685
}

2686
fn register_def(cx: &DocContext, def: Def) -> DefId {
2687 2688
    debug!("register_def({:?})", def);

2689
    let (did, kind) = match def {
2690 2691 2692 2693 2694 2695 2696 2697 2698 2699
        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),
        Def::SelfTy(_, Some((impl_id, _))) => return cx.map.local_def_id(impl_id),
2700
        _ => return def.def_id()
C
Corey Richardson 已提交
2701
    };
N
Niko Matsakis 已提交
2702
    if did.is_local() { return did }
2703 2704 2705
    let tcx = match cx.tcx_opt() {
        Some(tcx) => tcx,
        None => return did
2706
    };
2707
    inline::record_extern_fqn(cx, did, kind);
2708 2709
    if let TypeTrait = kind {
        let t = inline::build_external_trait(cx, tcx, did);
M
mitaa 已提交
2710
        cx.external_traits.borrow_mut().insert(did, t);
2711
    }
M
mitaa 已提交
2712
    did
C
Corey Richardson 已提交
2713
}
A
Alex Crichton 已提交
2714

2715
fn resolve_use_source(cx: &DocContext, path: Path, id: ast::NodeId) -> ImportSource {
A
Alex Crichton 已提交
2716 2717
    ImportSource {
        path: path,
2718
        did: resolve_def(cx, id),
A
Alex Crichton 已提交
2719 2720 2721
    }
}

N
Niko Matsakis 已提交
2722
fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option<DefId> {
2723
    cx.tcx_opt().and_then(|tcx| {
2724
        tcx.def_map.borrow().get(&id).map(|d| register_def(cx, d.full_def()))
2725
    })
A
Alex Crichton 已提交
2726
}
2727

J
Jorge Aparicio 已提交
2728
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2729
pub struct Macro {
2730
    pub source: String,
2731
    pub imported_from: Option<String>,
2732 2733 2734
}

impl Clean<Item> for doctree::Macro {
2735
    fn clean(&self, cx: &DocContext) -> Item {
2736
        let name = format!("{}!", self.name.clean(cx));
2737
        Item {
2738
            name: Some(name.clone()),
2739 2740
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
J
Jeffrey Seyfried 已提交
2741
            visibility: Some(Public),
2742
            stability: self.stab.clean(cx),
2743
            deprecation: self.depr.clean(cx),
2744
            def_id: cx.map.local_def_id(self.id),
2745
            inner: MacroItem(Macro {
2746 2747
                source: format!("macro_rules! {} {{\n{}}}",
                    name.trim_right_matches('!'), self.matchers.iter().map(|span|
J
;  
Jonas Schievink 已提交
2748
                        format!("    {} => {{ ... }};\n", span.to_src(cx))).collect::<String>()),
2749
                imported_from: self.imported_from.clean(cx),
2750 2751 2752 2753
            }),
        }
    }
}
2754

J
Jorge Aparicio 已提交
2755
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2756
pub struct Stability {
V
Vadim Petrochenkov 已提交
2757
    pub level: stability::StabilityLevel,
2758 2759
    pub feature: String,
    pub since: String,
2760
    pub deprecated_since: String,
2761 2762
    pub reason: String,
    pub issue: Option<u32>
2763 2764
}

2765 2766 2767 2768 2769 2770
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Deprecation {
    pub since: String,
    pub note: String,
}

2771
impl Clean<Stability> for attr::Stability {
2772 2773
    fn clean(&self, _: &DocContext) -> Stability {
        Stability {
V
Vadim Petrochenkov 已提交
2774
            level: stability::StabilityLevel::from_attr_level(&self.level),
2775
            feature: self.feature.to_string(),
V
Vadim Petrochenkov 已提交
2776 2777 2778 2779
            since: match self.level {
                attr::Stable {ref since} => since.to_string(),
                _ => "".to_string(),
            },
2780 2781
            deprecated_since: match self.rustc_depr {
                Some(attr::RustcDeprecation {ref since, ..}) => since.to_string(),
V
Vadim Petrochenkov 已提交
2782 2783
                _=> "".to_string(),
            },
2784
            reason: {
M
mitaa 已提交
2785 2786 2787 2788
                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(),
2789
                }
V
Vadim Petrochenkov 已提交
2790 2791 2792 2793 2794
            },
            issue: match self.level {
                attr::Unstable {issue, ..} => Some(issue),
                _ => None,
            }
2795 2796 2797 2798 2799
        }
    }
}

impl<'a> Clean<Stability> for &'a attr::Stability {
V
Vadim Petrochenkov 已提交
2800 2801
    fn clean(&self, dc: &DocContext) -> Stability {
        (**self).clean(dc)
2802 2803
    }
}
A
Alex Crichton 已提交
2804

2805 2806 2807 2808 2809 2810 2811 2812 2813
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()),
        }
    }
}

2814 2815 2816 2817 2818 2819 2820 2821 2822 2823
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,
2824
            deprecation: None,
2825 2826 2827 2828
        }
    }
}

2829
impl<'tcx> Clean<Item> for ty::AssociatedType<'tcx> {
2830
    fn clean(&self, cx: &DocContext) -> Item {
2831
        let my_name = self.name.clean(cx);
2832 2833 2834 2835 2836 2837

        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.
2838 2839
            let def = cx.tcx().lookup_trait_def(did);
            let predicates = cx.tcx().lookup_predicates(did);
2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862
            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![]
        };
2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873

        // 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)),
        }

2874 2875
        Item {
            source: DUMMY_SP.clean(cx),
2876
            name: Some(self.name.clean(cx)),
2877
            attrs: inline::load_attrs(cx, cx.tcx(), self.def_id),
2878
            inner: AssociatedTypeItem(bounds, self.ty.clean(cx)),
2879
            visibility: self.vis.clean(cx),
2880
            def_id: self.def_id,
2881
            stability: stability::lookup_stability(cx.tcx(), self.def_id).clean(cx),
2882
            deprecation: stability::lookup_deprecation(cx.tcx(), self.def_id).clean(cx),
2883 2884 2885 2886
        }
    }
}

2887 2888
impl<'a> Clean<Typedef> for (ty::TypeScheme<'a>, ty::GenericPredicates<'a>,
                             ParamSpace) {
2889
    fn clean(&self, cx: &DocContext) -> Typedef {
2890
        let (ref ty_scheme, ref predicates, ps) = *self;
2891 2892
        Typedef {
            type_: ty_scheme.ty.clean(cx),
2893
            generics: (&ty_scheme.generics, predicates, ps).clean(cx)
2894 2895 2896 2897
        }
    }
}

N
Niko Matsakis 已提交
2898
fn lang_struct(cx: &DocContext, did: Option<DefId>,
2899
               t: ty::Ty, name: &str,
A
Alex Crichton 已提交
2900 2901 2902
               fallback: fn(Box<Type>) -> Type) -> Type {
    let did = match did {
        Some(did) => did,
2903
        None => return fallback(box t.clean(cx)),
A
Alex Crichton 已提交
2904
    };
M
mitaa 已提交
2905
    inline::record_extern_fqn(cx, did, TypeStruct);
A
Alex Crichton 已提交
2906 2907 2908 2909 2910 2911 2912
    ResolvedPath {
        typarams: None,
        did: did,
        path: Path {
            global: false,
            segments: vec![PathSegment {
                name: name.to_string(),
2913 2914 2915
                params: PathParameters::AngleBracketed {
                    lifetimes: vec![],
                    types: vec![t.clean(cx)],
2916
                    bindings: vec![]
2917
                }
A
Alex Crichton 已提交
2918 2919
            }],
        },
2920
        is_generic: false,
A
Alex Crichton 已提交
2921 2922
    }
}
2923 2924

/// An equality constraint on an associated type, e.g. `A=Bar` in `Foo<A=Bar>`
J
Jorge Aparicio 已提交
2925
#[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Debug)]
2926 2927 2928 2929 2930
pub struct TypeBinding {
    pub name: String,
    pub ty: Type
}

2931
impl Clean<TypeBinding> for hir::TypeBinding {
2932 2933
    fn clean(&self, cx: &DocContext) -> TypeBinding {
        TypeBinding {
2934
            name: self.name.clean(cx),
2935 2936 2937 2938
            ty: self.ty.clean(cx)
        }
    }
}