mod.rs 94.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| tcx.lookup_stability(def_id)).clean(cx)
68 69
}

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

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(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 799 800 801 802 803 804 805 806 807 808
        if self.bounds.len() > 0 {
            let mut s = format!("{}: {}",
                                self.lifetime.name.to_string(),
                                self.bounds[0].name.to_string());
            for bound in self.bounds.iter().skip(1) {
                s.push_str(&format!(" + {}", bound.name.to_string()));
            }
            Lifetime(s)
        } else {
            Lifetime(self.lifetime.name.to_string())
        }
809 810 811
    }
}

812
impl Clean<Lifetime> for ty::RegionParameterDef {
813
    fn clean(&self, _: &DocContext) -> Lifetime {
814
        Lifetime(self.name.to_string())
815 816 817 818
    }
}

impl Clean<Option<Lifetime>> for ty::Region {
819
    fn clean(&self, cx: &DocContext) -> Option<Lifetime> {
820
        match *self {
821
            ty::ReStatic => Some(Lifetime::statik()),
M
mitaa 已提交
822
            ty::ReLateBound(_, ty::BrNamed(_, name)) => Some(Lifetime(name.to_string())),
N
Niko Matsakis 已提交
823
            ty::ReEarlyBound(ref data) => Some(Lifetime(data.name.clean(cx))),
824 825 826 827

            ty::ReLateBound(..) |
            ty::ReFree(..) |
            ty::ReScope(..) |
828 829
            ty::ReVar(..) |
            ty::ReSkolemized(..) |
V
Vadim Petrochenkov 已提交
830
            ty::ReEmpty => None
831 832 833 834
        }
    }
}

J
Jorge Aparicio 已提交
835
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
836 837 838
pub enum WherePredicate {
    BoundPredicate { ty: Type, bounds: Vec<TyParamBound> },
    RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>},
839
    EqPredicate { lhs: Type, rhs: Type }
840 841
}

842
impl Clean<WherePredicate> for hir::WherePredicate {
843
    fn clean(&self, cx: &DocContext) -> WherePredicate {
N
Nick Cameron 已提交
844
        match *self {
845
            hir::WherePredicate::BoundPredicate(ref wbp) => {
846
                WherePredicate::BoundPredicate {
847
                    ty: wbp.bounded_ty.clean(cx),
N
Nick Cameron 已提交
848 849 850
                    bounds: wbp.bounds.clean(cx)
                }
            }
851

852
            hir::WherePredicate::RegionPredicate(ref wrp) => {
853 854 855 856 857 858
                WherePredicate::RegionPredicate {
                    lifetime: wrp.lifetime.clean(cx),
                    bounds: wrp.bounds.clean(cx)
                }
            }

859
            hir::WherePredicate::EqPredicate(_) => {
860
                unimplemented!() // FIXME(#20041)
N
Nick Cameron 已提交
861
            }
862 863 864 865
        }
    }
}

866 867
impl<'a> Clean<WherePredicate> for ty::Predicate<'a> {
    fn clean(&self, cx: &DocContext) -> WherePredicate {
868
        use rustc::ty::Predicate;
869 870 871 872 873 874

        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),
875 876 877
            Predicate::Projection(ref pred) => pred.clean(cx),
            Predicate::WellFormed(_) => panic!("not user writable"),
            Predicate::ObjectSafe(_) => panic!("not user writable"),
878
            Predicate::ClosureKind(..) => panic!("not user writable"),
A
fixes  
Ariel Ben-Yehuda 已提交
879
            Predicate::Rfc1592(..) => panic!("not user writable"),
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 927 928 929 930 931 932 933 934 935 936
        }
    }
}

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_,
937 938 939
            TyParamBound::RegionBound(_) => {
                panic!("cleaning a trait got a region")
            }
940 941 942 943 944 945 946 947 948
        };
        Type::QPath {
            name: self.item_name.clean(cx),
            self_type: box self.trait_ref.self_ty().clean(cx),
            trait_: box trait_
        }
    }
}

949
// maybe use a Generic enum and use Vec<Generic>?
J
Jorge Aparicio 已提交
950
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
951
pub struct Generics {
952 953
    pub lifetimes: Vec<Lifetime>,
    pub type_params: Vec<TyParam>,
954
    pub where_predicates: Vec<WherePredicate>
955
}
C
Corey Richardson 已提交
956

957
impl Clean<Generics> for hir::Generics {
958
    fn clean(&self, cx: &DocContext) -> Generics {
C
Corey Richardson 已提交
959
        Generics {
960 961
            lifetimes: self.lifetimes.clean(cx),
            type_params: self.ty_params.clean(cx),
962
            where_predicates: self.where_clause.predicates.clean(cx)
C
Corey Richardson 已提交
963 964 965 966
        }
    }
}

967 968 969
impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
                                    &'a ty::GenericPredicates<'tcx>,
                                    subst::ParamSpace) {
970
    fn clean(&self, cx: &DocContext) -> Generics {
971 972
        use self::WherePredicate as WP;

973 974
        let (gens, preds, space) = *self;

975 976 977
        // Bounds in the type_params and lifetimes fields are repeated in the
        // predicates field (see rustc_typeck::collect::ty_generics), so remove
        // them.
978
        let stripped_typarams = gens.types.get_slice(space).iter().map(|tp| {
979
            tp.clean(cx)
980 981 982 983 984 985 986
        }).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<_>>();

987 988
        let mut where_predicates = preds.predicates.get_slice(space)
                                                   .to_vec().clean(cx);
989

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

1012
        // Run through the type parameters again and insert a ?Sized
1013
        // unbound for any we didn't find to be Sized.
1014
        for tp in &stripped_typarams {
1015 1016 1017
            if !sized_params.contains(&tp.name) {
                where_predicates.push(WP::BoundPredicate {
                    ty: Type::Generic(tp.name.clone()),
1018
                    bounds: vec![TyParamBound::maybe_sized(cx)],
1019 1020 1021 1022 1023 1024 1025 1026
                })
            }
        }

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

1027
        Generics {
1028
            type_params: simplify::ty_params(stripped_typarams),
1029
            lifetimes: stripped_lifetimes,
1030
            where_predicates: simplify::where_clauses(cx, where_predicates),
1031 1032 1033 1034
        }
    }
}

J
Jorge Aparicio 已提交
1035
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1036
pub struct Method {
1037
    pub generics: Generics,
1038 1039
    pub unsafety: hir::Unsafety,
    pub constness: hir::Constness,
1040
    pub decl: FnDecl,
1041
    pub abi: Abi,
C
Corey Richardson 已提交
1042 1043
}

1044
impl Clean<Method> for hir::MethodSig {
1045
    fn clean(&self, cx: &DocContext) -> Method {
1046
        let decl = FnDecl {
1047
            inputs: Arguments {
1048
                values: self.decl.inputs.clean(cx),
1049
            },
1050
            output: self.decl.output.clean(cx),
1051
            variadic: false,
1052
            attrs: Vec::new()
1053
        };
1054
        Method {
1055
            generics: self.generics.clean(cx),
1056 1057
            unsafety: self.unsafety,
            constness: self.constness,
1058
            decl: decl,
1059
            abi: self.abi
C
Corey Richardson 已提交
1060 1061 1062 1063
        }
    }
}

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

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

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

impl Clean<Item> for doctree::Function {
1101
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1102
        Item {
1103 1104 1105 1106 1107
            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),
1108
            deprecation: self.depr.clean(cx),
1109
            def_id: cx.map.local_def_id(self.id),
C
Corey Richardson 已提交
1110
            inner: FunctionItem(Function {
1111 1112
                decl: self.decl.clean(cx),
                generics: self.generics.clean(cx),
N
Niko Matsakis 已提交
1113
                unsafety: self.unsafety,
1114
                constness: self.constness,
1115
                abi: self.abi,
C
Corey Richardson 已提交
1116 1117 1118 1119 1120
            }),
        }
    }
}

J
Jorge Aparicio 已提交
1121
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
1122
pub struct FnDecl {
1123
    pub inputs: Arguments,
1124
    pub output: FunctionRetTy,
1125
    pub variadic: bool,
1126 1127
    pub attrs: Vec<Attribute>,
}
C
Corey Richardson 已提交
1128

1129 1130 1131 1132 1133 1134
impl FnDecl {
    pub fn has_self(&self) -> bool {
        return self.inputs.values.len() > 0 && self.inputs.values[0].name == "self";
    }
}

J
Jorge Aparicio 已提交
1135
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1136
pub struct Arguments {
1137
    pub values: Vec<Argument>,
1138 1139
}

1140
impl Clean<FnDecl> for hir::FnDecl {
1141
    fn clean(&self, cx: &DocContext) -> FnDecl {
C
Corey Richardson 已提交
1142
        FnDecl {
1143
            inputs: Arguments {
1144
                values: self.inputs.clean(cx),
1145
            },
1146
            output: self.output.clean(cx),
1147
            variadic: self.variadic,
1148
            attrs: Vec::new()
C
Corey Richardson 已提交
1149 1150 1151 1152
        }
    }
}

1153
impl<'tcx> Clean<Type> for ty::FnOutput<'tcx> {
J
Jakub Bukaj 已提交
1154 1155 1156 1157 1158 1159 1160 1161
    fn clean(&self, cx: &DocContext) -> Type {
        match *self {
            ty::FnConverging(ty) => ty.clean(cx),
            ty::FnDiverging => Bottom
        }
    }
}

N
Niko Matsakis 已提交
1162
impl<'a, 'tcx> Clean<FnDecl> for (DefId, &'a ty::PolyFnSig<'tcx>) {
1163
    fn clean(&self, cx: &DocContext) -> FnDecl {
1164
        let (did, sig) = *self;
M
mitaa 已提交
1165
        let mut names = if cx.map.as_local_node_id(did).is_some() {
1166
            vec![].into_iter()
1167
        } else {
A
Ariel Ben-Yehuda 已提交
1168
            cx.tcx().sess.cstore.method_arg_names(did).into_iter()
1169
        }.peekable();
1170
        FnDecl {
1171
            output: Return(sig.0.output.clean(cx)),
1172
            attrs: Vec::new(),
1173
            variadic: sig.0.variadic,
1174
            inputs: Arguments {
1175
                values: sig.0.inputs.iter().map(|t| {
1176
                    Argument {
1177
                        type_: t.clean(cx),
1178
                        id: 0,
1179
                        name: names.next().unwrap_or("".to_string()),
1180 1181 1182 1183 1184 1185 1186
                    }
                }).collect(),
            },
        }
    }
}

J
Jorge Aparicio 已提交
1187
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
1188
pub struct Argument {
1189
    pub type_: Type,
1190
    pub name: String,
1191
    pub id: ast::NodeId,
C
Corey Richardson 已提交
1192 1193
}

1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
pub enum SelfTy {
    SelfValue,
    SelfBorrowed(Option<Lifetime>, Mutability),
    SelfExplicit(Type),
}

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

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

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

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

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

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

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

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

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

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

1349
impl<'tcx> Clean<Item> for ty::Method<'tcx> {
1350
    fn clean(&self, cx: &DocContext) -> Item {
1351 1352
        let generics = (&self.generics, &self.predicates,
                        subst::FnSpace).clean(cx);
1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365
        let mut decl = (self.def_id, &self.fty.sig).clean(cx);
        match self.explicit_self {
            ty::ExplicitSelfCategory::ByValue => {
                decl.inputs.values[0].type_ = Infer;
            }
            ty::ExplicitSelfCategory::ByReference(..) => {
                match decl.inputs.values[0].type_ {
                    BorrowedRef{ref mut type_, ..} => **type_ = Infer,
                    _ => unreachable!(),
                }
            }
            _ => {}
        }
1366 1367 1368
        let provided = match self.container {
            ty::ImplContainer(..) => false,
            ty::TraitContainer(did) => {
1369
                cx.tcx().provided_trait_methods(did).iter().any(|m| {
1370 1371 1372 1373 1374 1375 1376 1377 1378
                    m.def_id == self.def_id
                })
            }
        };
        let inner = if provided {
            MethodItem(Method {
                unsafety: self.fty.unsafety,
                generics: generics,
                decl: decl,
N
Niko Matsakis 已提交
1379 1380 1381
                abi: self.fty.abi,

                // trait methods canot (currently, at least) be const
1382
                constness: hir::Constness::NotConst,
1383 1384 1385 1386 1387 1388
            })
        } else {
            TyMethodItem(TyMethod {
                unsafety: self.fty.unsafety,
                generics: generics,
                decl: decl,
N
Niko Matsakis 已提交
1389
                abi: self.fty.abi,
1390 1391 1392
            })
        };

1393
        Item {
1394
            name: Some(self.name.clean(cx)),
J
Jeffrey Seyfried 已提交
1395
            visibility: Some(Inherited),
1396
            stability: get_stability(cx, self.def_id),
1397
            deprecation: get_deprecation(cx, self.def_id),
1398
            def_id: self.def_id,
1399
            attrs: inline::load_attrs(cx, cx.tcx(), self.def_id),
1400
            source: Span::empty(),
1401
            inner: inner,
1402
        }
1403 1404 1405
    }
}

1406
impl<'tcx> Clean<Item> for ty::ImplOrTraitItem<'tcx> {
1407
    fn clean(&self, cx: &DocContext) -> Item {
1408
        match *self {
1409
            ty::ConstTraitItem(ref cti) => cti.clean(cx),
1410
            ty::MethodTraitItem(ref mti) => mti.clean(cx),
1411
            ty::TypeTraitItem(ref tti) => tti.clean(cx),
1412 1413 1414 1415
        }
    }
}

1416
/// A trait reference, which may have higher ranked lifetimes.
J
Jorge Aparicio 已提交
1417
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1418 1419 1420 1421 1422
pub struct PolyTrait {
    pub trait_: Type,
    pub lifetimes: Vec<Lifetime>
}

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

    // <Type as Trait>::Name
T
Tom Jakubowski 已提交
1458 1459 1460 1461 1462
    QPath {
        name: String,
        self_type: Box<Type>,
        trait_: Box<Type>
    },
1463 1464 1465 1466 1467 1468

    // _
    Infer,

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

J
Jorge Aparicio 已提交
1471
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
1472
pub enum PrimitiveType {
1473 1474
    Isize, I8, I16, I32, I64,
    Usize, U8, U16, U32, U64,
1475
    F32, F64,
1476 1477 1478 1479
    Char,
    Bool,
    Str,
    Slice,
1480
    Array,
1481
    PrimitiveTuple,
1482
    PrimitiveRawPointer,
1483 1484
}

J
Jorge Aparicio 已提交
1485
#[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
1486 1487 1488
pub enum TypeKind {
    TypeEnum,
    TypeFunction,
1489
    TypeModule,
1490
    TypeConst,
1491 1492 1493 1494
    TypeStatic,
    TypeStruct,
    TypeTrait,
    TypeVariant,
1495
    TypeTypedef,
1496 1497
}

1498 1499 1500 1501 1502 1503 1504 1505 1506 1507
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())
    }
}

1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520
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,
        }
    }
1521

1522 1523 1524 1525 1526 1527
    pub fn is_generic(&self) -> bool {
        match *self {
            ResolvedPath { is_generic, .. } => is_generic,
            _ => false,
        }
    }
1528
}
1529

1530
impl GetDefId for Type {
1531 1532 1533 1534 1535 1536
    fn def_id(&self) -> Option<DefId> {
        match *self {
            ResolvedPath { did, .. } => Some(did),
            _ => None,
        }
    }
1537 1538
}

1539 1540
impl PrimitiveType {
    fn from_str(s: &str) -> Option<PrimitiveType> {
1541
        match s {
1542
            "isize" => Some(Isize),
1543 1544 1545 1546
            "i8" => Some(I8),
            "i16" => Some(I16),
            "i32" => Some(I32),
            "i64" => Some(I64),
1547
            "usize" => Some(Usize),
1548 1549 1550 1551 1552 1553 1554 1555 1556
            "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),
1557
            "array" => Some(Array),
1558 1559
            "slice" => Some(Slice),
            "tuple" => Some(PrimitiveTuple),
1560
            "pointer" => Some(PrimitiveRawPointer),
1561 1562 1563 1564
            _ => None,
        }
    }

1565
    fn find(attrs: &[Attribute]) -> Option<PrimitiveType> {
1566
        for attr in attrs.list("doc") {
M
mitaa 已提交
1567 1568 1569 1570 1571
            if let NameValue(ref k, ref v) = *attr {
                if "primitive" == *k {
                    if let ret@Some(..) = PrimitiveType::from_str(v) {
                        return ret;
                    }
1572 1573 1574
                }
            }
        }
M
mitaa 已提交
1575
        None
1576 1577
    }

1578
    pub fn to_string(&self) -> &'static str {
1579
        match *self {
1580
            Isize => "isize",
1581 1582 1583 1584
            I8 => "i8",
            I16 => "i16",
            I32 => "i32",
            I64 => "i64",
1585
            Usize => "usize",
1586 1587 1588 1589 1590 1591 1592 1593 1594
            U8 => "u8",
            U16 => "u16",
            U32 => "u32",
            U64 => "u64",
            F32 => "f32",
            F64 => "f64",
            Str => "str",
            Bool => "bool",
            Char => "char",
1595
            Array => "array",
1596 1597
            Slice => "slice",
            PrimitiveTuple => "tuple",
1598
            PrimitiveRawPointer => "pointer",
1599 1600 1601 1602
        }
    }

    pub fn to_url_str(&self) -> &'static str {
1603
        self.to_string()
1604 1605 1606 1607 1608
    }

    /// Creates a rustdoc-specific node id for primitive types.
    ///
    /// These node ids are generally never used by the AST itself.
1609 1610 1611
    pub fn to_def_index(&self) -> DefIndex {
        let x = u32::MAX - 1 - (*self as u32);
        DefIndex::new(x as usize)
1612 1613 1614
    }
}

1615
impl Clean<Type> for hir::Ty {
1616
    fn clean(&self, cx: &DocContext) -> Type {
1617
        use rustc::hir::*;
1618
        match self.node {
1619
            TyPtr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
1620
            TyRptr(ref l, ref m) =>
1621 1622
                BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx),
                             type_: box m.ty.clean(cx)},
1623
            TyVec(ref ty) => Vector(box ty.clean(cx)),
1624 1625
            TyFixedLengthVec(ref ty, ref e) =>
                FixedVector(box ty.clean(cx), pprust::expr_to_string(e)),
1626
            TyTup(ref tys) => Tuple(tys.clean(cx)),
1627
            TyPath(None, ref p) => {
1628
                resolve_type(cx, p.clean(cx), self.id)
N
Niko Matsakis 已提交
1629
            }
1630
            TyPath(Some(ref qself), ref p) => {
1631 1632 1633 1634 1635 1636 1637
                let mut segments: Vec<_> = p.segments.clone().into();
                segments.pop();
                let trait_path = hir::Path {
                    span: p.span,
                    global: p.global,
                    segments: segments.into(),
                };
1638
                Type::QPath {
V
Vadim Petrochenkov 已提交
1639
                    name: p.segments.last().unwrap().name.clean(cx),
1640
                    self_type: box qself.ty.clean(cx),
1641
                    trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
1642 1643
                }
            }
N
Niko Matsakis 已提交
1644 1645 1646
            TyObjectSum(ref lhs, ref bounds) => {
                let lhs_ty = lhs.clean(cx);
                match lhs_ty {
1647 1648 1649 1650 1651 1652 1653
                    ResolvedPath { path, typarams: None, did, is_generic } => {
                        ResolvedPath {
                            path: path,
                            typarams: Some(bounds.clean(cx)),
                            did: did,
                            is_generic: is_generic,
                        }
N
Niko Matsakis 已提交
1654 1655 1656 1657 1658
                    }
                    _ => {
                        lhs_ty // shouldn't happen
                    }
                }
1659
            }
1660
            TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
M
mitaa 已提交
1661 1662 1663
            TyPolyTraitRef(ref bounds) => PolyTraitRef(bounds.clean(cx)),
            TyInfer => Infer,
            TyTypeof(..) => panic!("Unimplemented type {:?}", self.node),
1664
        }
C
Corey Richardson 已提交
1665 1666 1667
    }
}

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

1744
            ty::TyProjection(ref data) => data.clean(cx),
1745

1746
            ty::TyParam(ref p) => Generic(p.name.to_string()),
1747

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

1750 1751
            ty::TyInfer(..) => panic!("TyInfer"),
            ty::TyError => panic!("TyError"),
1752 1753 1754 1755
        }
    }
}

1756
impl Clean<Item> for hir::StructField {
1757
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1758
        Item {
1759 1760
            name: Some(self.name).clean(cx),
            attrs: self.attrs.clean(cx),
1761
            source: self.span.clean(cx),
1762
            visibility: self.vis.clean(cx),
1763 1764 1765
            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),
1766
            inner: StructFieldItem(self.ty.clean(cx)),
C
Corey Richardson 已提交
1767 1768 1769 1770
        }
    }
}

A
Ariel Ben-Yehuda 已提交
1771
impl<'tcx> Clean<Item> for ty::FieldDefData<'tcx, 'static> {
1772
    fn clean(&self, cx: &DocContext) -> Item {
A
Ariel Ben-Yehuda 已提交
1773
        // FIXME: possible O(n^2)-ness! Not my fault.
1774
        let attr_map = cx.tcx().sess.cstore.crate_struct_field_attrs(self.did.krate);
1775
        Item {
1776 1777
            name: Some(self.name).clean(cx),
            attrs: attr_map.get(&self.did).unwrap_or(&Vec::new()).clean(cx),
1778
            source: Span::empty(),
1779
            visibility: self.vis.clean(cx),
1780
            stability: get_stability(cx, self.did),
1781
            deprecation: get_deprecation(cx, self.did),
1782
            def_id: self.did,
1783
            inner: StructFieldItem(self.unsubst_ty().clean(cx)),
1784 1785 1786 1787
        }
    }
}

J
Jeffrey Seyfried 已提交
1788 1789 1790 1791 1792
#[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug)]
pub enum Visibility {
    Public,
    Inherited,
}
C
Corey Richardson 已提交
1793

1794
impl Clean<Option<Visibility>> for hir::Visibility {
1795
    fn clean(&self, _: &DocContext) -> Option<Visibility> {
J
Jeffrey Seyfried 已提交
1796
        Some(if *self == hir::Visibility::Public { Public } else { Inherited })
1797 1798 1799 1800 1801
    }
}

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

J
Jorge Aparicio 已提交
1806
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1807
pub struct Struct {
1808 1809 1810 1811
    pub struct_type: doctree::StructType,
    pub generics: Generics,
    pub fields: Vec<Item>,
    pub fields_stripped: bool,
C
Corey Richardson 已提交
1812 1813 1814
}

impl Clean<Item> for doctree::Struct {
1815
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1816
        Item {
1817 1818 1819
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
1820
            def_id: cx.map.local_def_id(self.id),
1821 1822
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
1823
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
1824 1825
            inner: StructItem(Struct {
                struct_type: self.struct_type,
1826 1827
                generics: self.generics.clean(cx),
                fields: self.fields.clean(cx),
S
Steven Fackler 已提交
1828
                fields_stripped: false,
C
Corey Richardson 已提交
1829 1830 1831 1832 1833
            }),
        }
    }
}

1834
/// This is a more limited form of the standard Struct, different in that
C
Corey Richardson 已提交
1835 1836
/// it lacks the things most items have (name, id, parameterization). Found
/// only as a variant in an enum.
J
Jorge Aparicio 已提交
1837
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1838
pub struct VariantStruct {
1839 1840 1841
    pub struct_type: doctree::StructType,
    pub fields: Vec<Item>,
    pub fields_stripped: bool,
C
Corey Richardson 已提交
1842 1843
}

1844
impl Clean<VariantStruct> for ::rustc::hir::VariantData {
1845
    fn clean(&self, cx: &DocContext) -> VariantStruct {
C
Corey Richardson 已提交
1846 1847
        VariantStruct {
            struct_type: doctree::struct_type_from_def(self),
1848
            fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
S
Steven Fackler 已提交
1849
            fields_stripped: false,
C
Corey Richardson 已提交
1850 1851 1852 1853
        }
    }
}

J
Jorge Aparicio 已提交
1854
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1855
pub struct Enum {
1856 1857 1858
    pub variants: Vec<Item>,
    pub generics: Generics,
    pub variants_stripped: bool,
C
Corey Richardson 已提交
1859 1860 1861
}

impl Clean<Item> for doctree::Enum {
1862
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1863
        Item {
1864 1865 1866
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
1867
            def_id: cx.map.local_def_id(self.id),
1868 1869
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
1870
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
1871
            inner: EnumItem(Enum {
1872 1873
                variants: self.variants.clean(cx),
                generics: self.generics.clean(cx),
S
Steven Fackler 已提交
1874
                variants_stripped: false,
C
Corey Richardson 已提交
1875 1876 1877 1878 1879
            }),
        }
    }
}

J
Jorge Aparicio 已提交
1880
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1881
pub struct Variant {
1882
    pub kind: VariantKind,
C
Corey Richardson 已提交
1883 1884 1885
}

impl Clean<Item> for doctree::Variant {
1886
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1887
        Item {
1888 1889 1890
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
1891
            visibility: None,
1892
            stability: self.stab.clean(cx),
1893
            deprecation: self.depr.clean(cx),
1894
            def_id: cx.map.local_def_id(self.def.id()),
C
Corey Richardson 已提交
1895
            inner: VariantItem(Variant {
1896
                kind: struct_def_to_variant_kind(&self.def, cx),
C
Corey Richardson 已提交
1897 1898 1899 1900 1901
            }),
        }
    }
}

A
Ariel Ben-Yehuda 已提交
1902
impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
1903
    fn clean(&self, cx: &DocContext) -> Item {
1904 1905 1906 1907 1908 1909
        let kind = match self.kind() {
            ty::VariantKind::Unit => CLikeVariant,
            ty::VariantKind::Tuple => {
                TupleVariant(
                    self.fields.iter().map(|f| f.unsubst_ty().clean(cx)).collect()
                )
1910
            }
1911
            ty::VariantKind::Struct => {
1912 1913 1914
                StructVariant(VariantStruct {
                    struct_type: doctree::Plain,
                    fields_stripped: false,
1915
                    fields: self.fields.iter().map(|field| {
1916 1917
                        Item {
                            source: Span::empty(),
1918
                            name: Some(field.name.clean(cx)),
1919
                            attrs: cx.tcx().get_attrs(field.did).clean(cx),
1920
                            visibility: field.vis.clean(cx),
1921 1922 1923
                            def_id: field.did,
                            stability: get_stability(cx, field.did),
                            deprecation: get_deprecation(cx, field.did),
1924
                            inner: StructFieldItem(field.unsubst_ty().clean(cx))
1925 1926 1927 1928 1929 1930
                        }
                    }).collect()
                })
            }
        };
        Item {
1931
            name: Some(self.name.clean(cx)),
1932
            attrs: inline::load_attrs(cx, cx.tcx(), self.did),
1933
            source: Span::empty(),
J
Jeffrey Seyfried 已提交
1934
            visibility: Some(Inherited),
1935
            def_id: self.did,
1936
            inner: VariantItem(Variant { kind: kind }),
1937
            stability: get_stability(cx, self.did),
1938
            deprecation: get_deprecation(cx, self.did),
1939 1940 1941 1942
        }
    }
}

J
Jorge Aparicio 已提交
1943
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1944 1945
pub enum VariantKind {
    CLikeVariant,
1946
    TupleVariant(Vec<Type>),
C
Corey Richardson 已提交
1947 1948 1949
    StructVariant(VariantStruct),
}

1950
fn struct_def_to_variant_kind(struct_def: &hir::VariantData, cx: &DocContext) -> VariantKind {
1951
    if struct_def.is_struct() {
1952
        StructVariant(struct_def.clean(cx))
1953
    } else if struct_def.is_unit() {
1954 1955
        CLikeVariant
    } else {
1956
        TupleVariant(struct_def.fields().iter().map(|x| x.ty.clean(cx)).collect())
1957 1958 1959
    }
}

J
Jorge Aparicio 已提交
1960
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1961
pub struct Span {
1962
    pub filename: String,
1963 1964 1965 1966
    pub loline: usize,
    pub locol: usize,
    pub hiline: usize,
    pub hicol: usize,
1967 1968
}

1969 1970 1971
impl Span {
    fn empty() -> Span {
        Span {
1972
            filename: "".to_string(),
1973 1974 1975 1976 1977 1978
            loline: 0, locol: 0,
            hiline: 0, hicol: 0,
        }
    }
}

1979
impl Clean<Span> for syntax::codemap::Span {
1980
    fn clean(&self, cx: &DocContext) -> Span {
1981 1982 1983 1984
        if *self == DUMMY_SP {
            return Span::empty();
        }

1985
        let cm = cx.sess().codemap();
1986 1987 1988 1989
        let filename = cm.span_to_filename(*self);
        let lo = cm.lookup_char_pos(self.lo);
        let hi = cm.lookup_char_pos(self.hi);
        Span {
1990
            filename: filename.to_string(),
1991
            loline: lo.line,
1992
            locol: lo.col.to_usize(),
1993
            hiline: hi.line,
1994
            hicol: hi.col.to_usize(),
1995
        }
C
Corey Richardson 已提交
1996 1997 1998
    }
}

J
Jorge Aparicio 已提交
1999
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
2000
pub struct Path {
2001 2002
    pub global: bool,
    pub segments: Vec<PathSegment>,
C
Corey Richardson 已提交
2003 2004
}

2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018
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()
                }
            }]
        }
    }
2019 2020 2021 2022

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

2025
impl Clean<Path> for hir::Path {
2026
    fn clean(&self, cx: &DocContext) -> Path {
C
Corey Richardson 已提交
2027
        Path {
2028
            global: self.global,
2029
            segments: self.segments.clean(cx),
2030 2031 2032 2033
        }
    }
}

J
Jorge Aparicio 已提交
2034
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2035 2036 2037 2038
pub enum PathParameters {
    AngleBracketed {
        lifetimes: Vec<Lifetime>,
        types: Vec<Type>,
2039
        bindings: Vec<TypeBinding>
2040 2041 2042 2043 2044
    },
    Parenthesized {
        inputs: Vec<Type>,
        output: Option<Type>
    }
2045 2046
}

2047
impl Clean<PathParameters> for hir::PathParameters {
2048 2049
    fn clean(&self, cx: &DocContext) -> PathParameters {
        match *self {
2050
            hir::AngleBracketedParameters(ref data) => {
2051 2052
                PathParameters::AngleBracketed {
                    lifetimes: data.lifetimes.clean(cx),
2053 2054
                    types: data.types.clean(cx),
                    bindings: data.bindings.clean(cx)
2055
                }
2056 2057
            }

2058
            hir::ParenthesizedParameters(ref data) => {
2059 2060 2061 2062
                PathParameters::Parenthesized {
                    inputs: data.inputs.clean(cx),
                    output: data.output.clean(cx)
                }
2063
            }
2064 2065 2066
        }
    }
}
2067

J
Jorge Aparicio 已提交
2068
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2069 2070 2071 2072 2073
pub struct PathSegment {
    pub name: String,
    pub params: PathParameters
}

2074
impl Clean<PathSegment> for hir::PathSegment {
2075
    fn clean(&self, cx: &DocContext) -> PathSegment {
2076
        PathSegment {
V
Vadim Petrochenkov 已提交
2077
            name: self.name.clean(cx),
2078
            params: self.parameters.clean(cx)
C
Corey Richardson 已提交
2079 2080 2081 2082
        }
    }
}

2083
fn path_to_string(p: &hir::Path) -> String {
2084
    let mut s = String::new();
C
Corey Richardson 已提交
2085
    let mut first = true;
V
Vadim Petrochenkov 已提交
2086
    for i in p.segments.iter().map(|x| x.name.as_str()) {
C
Corey Richardson 已提交
2087 2088 2089 2090 2091
        if !first || p.global {
            s.push_str("::");
        } else {
            first = false;
        }
G
GuillaumeGomez 已提交
2092
        s.push_str(&i);
C
Corey Richardson 已提交
2093
    }
2094
    s
C
Corey Richardson 已提交
2095 2096
}

2097
impl Clean<String> for ast::Name {
2098
    fn clean(&self, _: &DocContext) -> String {
2099
        self.to_string()
2100 2101 2102
    }
}

J
Jorge Aparicio 已提交
2103
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
2104
pub struct Typedef {
2105 2106
    pub type_: Type,
    pub generics: Generics,
C
Corey Richardson 已提交
2107 2108 2109
}

impl Clean<Item> for doctree::Typedef {
2110
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
2111
        Item {
2112 2113 2114
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2115
            def_id: cx.map.local_def_id(self.id.clone()),
2116 2117
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
2118
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
2119
            inner: TypedefItem(Typedef {
2120 2121
                type_: self.ty.clean(cx),
                generics: self.gen.clean(cx),
2122
            }, false),
C
Corey Richardson 已提交
2123 2124 2125 2126
        }
    }
}

J
Jorge Aparicio 已提交
2127
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
2128
pub struct BareFunctionDecl {
2129
    pub unsafety: hir::Unsafety,
2130 2131
    pub generics: Generics,
    pub decl: FnDecl,
2132
    pub abi: Abi,
C
Corey Richardson 已提交
2133 2134
}

2135
impl Clean<BareFunctionDecl> for hir::BareFnTy {
2136
    fn clean(&self, cx: &DocContext) -> BareFunctionDecl {
C
Corey Richardson 已提交
2137
        BareFunctionDecl {
N
Niko Matsakis 已提交
2138
            unsafety: self.unsafety,
C
Corey Richardson 已提交
2139
            generics: Generics {
2140
                lifetimes: self.lifetimes.clean(cx),
2141
                type_params: Vec::new(),
2142
                where_predicates: Vec::new()
C
Corey Richardson 已提交
2143
            },
2144
            decl: self.decl.clean(cx),
2145
            abi: self.abi,
C
Corey Richardson 已提交
2146 2147 2148 2149
        }
    }
}

J
Jorge Aparicio 已提交
2150
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
2151
pub struct Static {
2152 2153
    pub type_: Type,
    pub mutability: Mutability,
C
Corey Richardson 已提交
2154 2155 2156
    /// 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.
2157
    pub expr: String,
C
Corey Richardson 已提交
2158 2159 2160
}

impl Clean<Item> for doctree::Static {
2161
    fn clean(&self, cx: &DocContext) -> Item {
2162
        debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
C
Corey Richardson 已提交
2163
        Item {
2164 2165 2166
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2167
            def_id: cx.map.local_def_id(self.id),
2168 2169
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
2170
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
2171
            inner: StaticItem(Static {
2172 2173
                type_: self.type_.clean(cx),
                mutability: self.mutability.clean(cx),
2174
                expr: pprust::expr_to_string(&self.expr),
C
Corey Richardson 已提交
2175 2176 2177 2178 2179
            }),
        }
    }
}

J
Jorge Aparicio 已提交
2180
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191
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),
2192
            def_id: cx.map.local_def_id(self.id),
2193 2194
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
2195
            deprecation: self.depr.clean(cx),
2196 2197
            inner: ConstantItem(Constant {
                type_: self.type_.clean(cx),
2198
                expr: pprust::expr_to_string(&self.expr),
2199 2200 2201 2202 2203
            }),
        }
    }
}

J
Jorge Aparicio 已提交
2204
#[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Copy)]
C
Corey Richardson 已提交
2205 2206 2207 2208 2209
pub enum Mutability {
    Mutable,
    Immutable,
}

2210
impl Clean<Mutability> for hir::Mutability {
2211
    fn clean(&self, _: &DocContext) -> Mutability {
C
Corey Richardson 已提交
2212
        match self {
2213 2214
            &hir::MutMutable => Mutable,
            &hir::MutImmutable => Immutable,
C
Corey Richardson 已提交
2215 2216 2217 2218
        }
    }
}

J
Jorge Aparicio 已提交
2219
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Copy, Debug)]
2220 2221 2222 2223 2224
pub enum ImplPolarity {
    Positive,
    Negative,
}

2225
impl Clean<ImplPolarity> for hir::ImplPolarity {
2226 2227
    fn clean(&self, _: &DocContext) -> ImplPolarity {
        match self {
2228 2229
            &hir::ImplPolarity::Positive => ImplPolarity::Positive,
            &hir::ImplPolarity::Negative => ImplPolarity::Negative,
2230 2231 2232 2233
        }
    }
}

J
Jorge Aparicio 已提交
2234
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
2235
pub struct Impl {
2236
    pub unsafety: hir::Unsafety,
2237
    pub generics: Generics,
2238
    pub provided_trait_methods: HashSet<String>,
2239 2240
    pub trait_: Option<Type>,
    pub for_: Type,
2241
    pub items: Vec<Item>,
2242
    pub derived: bool,
2243
    pub polarity: Option<ImplPolarity>,
C
Corey Richardson 已提交
2244 2245
}

2246
fn detect_derived<M: AttrMetaMethods>(attrs: &[M]) -> bool {
2247
    attr::contains_name(attrs, "automatically_derived")
2248 2249
}

2250 2251 2252 2253 2254 2255 2256 2257
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.
2258 2259
        if trait_.def_id() == cx.deref_trait_did.get() {
            build_deref_target_impls(cx, &items, &mut ret);
2260 2261
        }

2262 2263 2264 2265 2266 2267 2268 2269 2270
        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());

2271
        ret.push(Item {
C
Corey Richardson 已提交
2272
            name: None,
2273 2274
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2275
            def_id: cx.map.local_def_id(self.id),
2276 2277
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
2278
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
2279
            inner: ImplItem(Impl {
2280
                unsafety: self.unsafety,
2281
                generics: self.generics.clean(cx),
2282
                provided_trait_methods: provided,
2283
                trait_: trait_,
2284
                for_: self.for_.clean(cx),
2285
                items: items,
2286
                derived: detect_derived(&self.attrs),
2287
                polarity: Some(self.polarity.clean(cx)),
C
Corey Richardson 已提交
2288
            }),
2289
        });
M
mitaa 已提交
2290
        ret
2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303
    }
}

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 {
2304
            TypedefItem(ref t, true) => &t.type_,
2305 2306 2307
            _ => continue,
        };
        let primitive = match *target {
N
Niko Matsakis 已提交
2308
            ResolvedPath { did, .. } if did.is_local() => continue,
2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339
            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 已提交
2340
            if !did.is_local() {
2341 2342
                inline::build_impl(cx, tcx, did, ret);
            }
C
Corey Richardson 已提交
2343 2344 2345 2346
        }
    }
}

2347 2348
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct DefaultImpl {
2349
    pub unsafety: hir::Unsafety,
2350 2351 2352 2353 2354 2355 2356 2357 2358
    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),
2359
            def_id: cx.map.local_def_id(self.id),
J
Jeffrey Seyfried 已提交
2360
            visibility: Some(Public),
2361
            stability: None,
2362
            deprecation: None,
2363 2364 2365 2366 2367 2368 2369 2370
            inner: DefaultImplItem(DefaultImpl {
                unsafety: self.unsafety,
                trait_: self.trait_.clean(cx),
            }),
        }
    }
}

2371 2372 2373 2374 2375 2376
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 已提交
2377
            def_id: DefId { krate: self.cnum, index: CRATE_DEF_INDEX },
2378 2379
            visibility: self.vis.clean(cx),
            stability: None,
2380
            deprecation: None,
2381 2382 2383
            inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
        }
    }
C
Corey Richardson 已提交
2384 2385
}

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

J
Jorge Aparicio 已提交
2452
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2453
pub enum Import {
2454
    // use source as str;
2455
    SimpleImport(String, ImportSource),
A
Alex Crichton 已提交
2456 2457 2458
    // use source::*;
    GlobImport(ImportSource),
    // use source::{a, b, c};
2459
    ImportList(ImportSource, Vec<ViewListIdent>),
A
Alex Crichton 已提交
2460 2461
}

J
Jorge Aparicio 已提交
2462
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
A
Alex Crichton 已提交
2463
pub struct ImportSource {
2464
    pub path: Path,
N
Niko Matsakis 已提交
2465
    pub did: Option<DefId>,
C
Corey Richardson 已提交
2466 2467
}

J
Jorge Aparicio 已提交
2468
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
A
Alex Crichton 已提交
2469
pub struct ViewListIdent {
2470
    pub name: String,
2471
    pub rename: Option<String>,
N
Niko Matsakis 已提交
2472
    pub source: Option<DefId>,
A
Alex Crichton 已提交
2473
}
C
Corey Richardson 已提交
2474

2475
impl Clean<ViewListIdent> for hir::PathListItem {
2476
    fn clean(&self, cx: &DocContext) -> ViewListIdent {
J
Jakub Wieczorek 已提交
2477
        match self.node {
2478
            hir::PathListIdent { id, name, rename } => ViewListIdent {
2479
                name: name.clean(cx),
2480
                rename: rename.map(|r| r.clean(cx)),
2481
                source: resolve_def(cx, id)
J
Jakub Wieczorek 已提交
2482
            },
2483
            hir::PathListMod { id, rename } => ViewListIdent {
2484
                name: "self".to_string(),
2485
                rename: rename.map(|r| r.clean(cx)),
2486
                source: resolve_def(cx, id)
J
Jakub Wieczorek 已提交
2487
            }
A
Alex Crichton 已提交
2488
        }
C
Corey Richardson 已提交
2489 2490 2491
    }
}

2492
impl Clean<Vec<Item>> for hir::ForeignMod {
2493
    fn clean(&self, cx: &DocContext) -> Vec<Item> {
2494 2495
        let mut items = self.items.clean(cx);
        for item in &mut items {
M
mitaa 已提交
2496 2497
            if let ForeignFunctionItem(ref mut f) = item.inner {
                f.abi = self.abi;
2498 2499 2500
            }
        }
        items
2501 2502 2503
    }
}

2504
impl Clean<Item> for hir::ForeignItem {
2505
    fn clean(&self, cx: &DocContext) -> Item {
2506
        let inner = match self.node {
2507
            hir::ForeignItemFn(ref decl, ref generics) => {
2508
                ForeignFunctionItem(Function {
2509 2510
                    decl: decl.clean(cx),
                    generics: generics.clean(cx),
2511
                    unsafety: hir::Unsafety::Unsafe,
2512
                    abi: Abi::Rust,
2513
                    constness: hir::Constness::NotConst,
2514 2515
                })
            }
2516
            hir::ForeignItemStatic(ref ty, mutbl) => {
2517
                ForeignStaticItem(Static {
2518
                    type_: ty.clean(cx),
2519
                    mutability: if mutbl {Mutable} else {Immutable},
2520
                    expr: "".to_string(),
2521 2522 2523 2524
                })
            }
        };
        Item {
V
Vadim Petrochenkov 已提交
2525
            name: Some(self.name.clean(cx)),
2526 2527
            attrs: self.attrs.clean(cx),
            source: self.span.clean(cx),
2528
            def_id: cx.map.local_def_id(self.id),
2529
            visibility: self.vis.clean(cx),
2530
            stability: get_stability(cx, cx.map.local_def_id(self.id)),
2531
            deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
2532 2533 2534 2535 2536
            inner: inner,
        }
    }
}

C
Corey Richardson 已提交
2537 2538 2539
// Utilities

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

2543
impl ToSource for syntax::codemap::Span {
2544
    fn to_src(&self, cx: &DocContext) -> String {
2545
        debug!("converting span {:?} to snippet", self.clean(cx));
2546
        let sn = match cx.sess().codemap().span_to_snippet(*self) {
2547 2548
            Ok(x) => x.to_string(),
            Err(_) => "".to_string()
C
Corey Richardson 已提交
2549
        };
2550
        debug!("got snippet {}", sn);
C
Corey Richardson 已提交
2551 2552 2553 2554
        sn
    }
}

2555
fn lit_to_string(lit: &ast::Lit) -> String {
C
Corey Richardson 已提交
2556
    match lit.node {
2557 2558 2559
        ast::LitKind::Str(ref st, _) => st.to_string(),
        ast::LitKind::ByteStr(ref data) => format!("{:?}", data),
        ast::LitKind::Byte(b) => {
2560
            let mut res = String::from("b'");
2561
            for c in (b as char).escape_default() {
2562
                res.push(c);
2563
            }
2564
            res.push('\'');
2565 2566
            res
        },
2567 2568 2569 2570 2571
        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 已提交
2572 2573 2574
    }
}

2575
fn name_from_pat(p: &hir::Pat) -> String {
2576
    use rustc::hir::*;
2577
    debug!("Trying to get a name from pattern: {:?}", p);
2578

C
Corey Richardson 已提交
2579
    match p.node {
2580
        PatKind::Wild => "_".to_string(),
2581
        PatKind::Binding(_, ref p, _) => p.node.to_string(),
2582
        PatKind::TupleStruct(ref p, _, _) | PatKind::Path(ref p) => path_to_string(p),
2583
        PatKind::QPath(..) => panic!("tried to get argument name from PatKind::QPath, \
2584
                                which is not allowed in function arguments"),
2585
        PatKind::Struct(ref name, ref fields, etc) => {
2586
            format!("{} {{ {}{} }}", path_to_string(name),
2587
                fields.iter().map(|&Spanned { node: ref fp, .. }|
2588
                                  format!("{}: {}", fp.name, name_from_pat(&*fp.pat)))
2589
                             .collect::<Vec<String>>().join(", "),
2590 2591 2592
                if etc { ", ..." } else { "" }
            )
        },
2593
        PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
2594
                                            .collect::<Vec<String>>().join(", ")),
2595 2596 2597 2598
        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, \
2599
                  which is silly in function arguments");
2600
            "()".to_string()
2601
        },
2602
        PatKind::Range(..) => panic!("tried to get argument name from PatKind::Range, \
2603
                              which is not allowed in function arguments"),
2604
        PatKind::Vec(ref begin, ref mid, ref end) => {
2605 2606 2607
            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));
2608
            format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
2609
        },
C
Corey Richardson 已提交
2610 2611 2612 2613
    }
}

/// Given a Type, resolve it using the def_map
N
Niko Matsakis 已提交
2614 2615
fn resolve_type(cx: &DocContext,
                path: Path,
2616
                id: ast::NodeId) -> Type {
2617
    debug!("resolve_type({:?},{:?})", path, id);
2618 2619
    let tcx = match cx.tcx_opt() {
        Some(tcx) => tcx,
2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631
        // 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
            };
        }
2632
    };
M
mitaa 已提交
2633
    let def = tcx.def_map.borrow().get(&id).expect("unresolved id not in defmap").full_def();
2634 2635
    debug!("resolve_type: def={:?}", def);

2636
    let is_generic = match def {
2637
        Def::PrimTy(p) => match p {
2638 2639 2640
            hir::TyStr => return Primitive(Str),
            hir::TyBool => return Primitive(Bool),
            hir::TyChar => return Primitive(Char),
2641 2642 2643 2644 2645 2646 2647 2648 2649 2650
            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),
2651 2652
            hir::TyFloat(ast::FloatTy::F32) => return Primitive(F32),
            hir::TyFloat(ast::FloatTy::F64) => return Primitive(F64),
C
Corey Richardson 已提交
2653
        },
2654
        Def::SelfTy(..) if path.segments.len() == 1 => {
2655
            return Generic(keywords::SelfType.name().to_string());
2656
        }
2657
        Def::SelfTy(..) | Def::TyParam(..) => true,
2658
        _ => false,
2659
    };
2660
    let did = register_def(&*cx, def);
2661
    ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
2662 2663
}

2664
fn register_def(cx: &DocContext, def: Def) -> DefId {
2665 2666
    debug!("register_def({:?})", def);

2667
    let (did, kind) = match def {
2668 2669 2670 2671 2672 2673 2674 2675 2676
        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),
2677
        Def::SelfTy(_, Some(impl_id)) => return cx.map.local_def_id(impl_id),
2678
        _ => return def.def_id()
C
Corey Richardson 已提交
2679
    };
N
Niko Matsakis 已提交
2680
    if did.is_local() { return did }
2681 2682 2683
    let tcx = match cx.tcx_opt() {
        Some(tcx) => tcx,
        None => return did
2684
    };
2685
    inline::record_extern_fqn(cx, did, kind);
2686 2687
    if let TypeTrait = kind {
        let t = inline::build_external_trait(cx, tcx, did);
M
mitaa 已提交
2688
        cx.external_traits.borrow_mut().insert(did, t);
2689
    }
M
mitaa 已提交
2690
    did
C
Corey Richardson 已提交
2691
}
A
Alex Crichton 已提交
2692

2693
fn resolve_use_source(cx: &DocContext, path: Path, id: ast::NodeId) -> ImportSource {
A
Alex Crichton 已提交
2694 2695
    ImportSource {
        path: path,
2696
        did: resolve_def(cx, id),
A
Alex Crichton 已提交
2697 2698 2699
    }
}

N
Niko Matsakis 已提交
2700
fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option<DefId> {
2701
    cx.tcx_opt().and_then(|tcx| {
2702
        tcx.def_map.borrow().get(&id).map(|d| register_def(cx, d.full_def()))
2703
    })
A
Alex Crichton 已提交
2704
}
2705

J
Jorge Aparicio 已提交
2706
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2707
pub struct Macro {
2708
    pub source: String,
2709
    pub imported_from: Option<String>,
2710 2711 2712
}

impl Clean<Item> for doctree::Macro {
2713
    fn clean(&self, cx: &DocContext) -> Item {
2714
        let name = format!("{}!", self.name.clean(cx));
2715
        Item {
2716
            name: Some(name.clone()),
2717 2718
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
J
Jeffrey Seyfried 已提交
2719
            visibility: Some(Public),
2720
            stability: self.stab.clean(cx),
2721
            deprecation: self.depr.clean(cx),
2722
            def_id: cx.map.local_def_id(self.id),
2723
            inner: MacroItem(Macro {
2724 2725
                source: format!("macro_rules! {} {{\n{}}}",
                    name.trim_right_matches('!'), self.matchers.iter().map(|span|
J
;  
Jonas Schievink 已提交
2726
                        format!("    {} => {{ ... }};\n", span.to_src(cx))).collect::<String>()),
2727
                imported_from: self.imported_from.clean(cx),
2728 2729 2730 2731
            }),
        }
    }
}
2732

J
Jorge Aparicio 已提交
2733
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2734
pub struct Stability {
V
Vadim Petrochenkov 已提交
2735
    pub level: stability::StabilityLevel,
2736 2737
    pub feature: String,
    pub since: String,
2738
    pub deprecated_since: String,
2739 2740
    pub reason: String,
    pub issue: Option<u32>
2741 2742
}

2743 2744 2745 2746 2747 2748
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Deprecation {
    pub since: String,
    pub note: String,
}

2749
impl Clean<Stability> for attr::Stability {
2750 2751
    fn clean(&self, _: &DocContext) -> Stability {
        Stability {
V
Vadim Petrochenkov 已提交
2752
            level: stability::StabilityLevel::from_attr_level(&self.level),
2753
            feature: self.feature.to_string(),
V
Vadim Petrochenkov 已提交
2754 2755 2756 2757
            since: match self.level {
                attr::Stable {ref since} => since.to_string(),
                _ => "".to_string(),
            },
2758 2759
            deprecated_since: match self.rustc_depr {
                Some(attr::RustcDeprecation {ref since, ..}) => since.to_string(),
V
Vadim Petrochenkov 已提交
2760 2761
                _=> "".to_string(),
            },
2762
            reason: {
M
mitaa 已提交
2763 2764 2765 2766
                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(),
2767
                }
V
Vadim Petrochenkov 已提交
2768 2769 2770 2771 2772
            },
            issue: match self.level {
                attr::Unstable {issue, ..} => Some(issue),
                _ => None,
            }
2773 2774 2775 2776 2777
        }
    }
}

impl<'a> Clean<Stability> for &'a attr::Stability {
V
Vadim Petrochenkov 已提交
2778 2779
    fn clean(&self, dc: &DocContext) -> Stability {
        (**self).clean(dc)
2780 2781
    }
}
A
Alex Crichton 已提交
2782

2783 2784 2785 2786 2787 2788 2789 2790 2791
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()),
        }
    }
}

2792 2793 2794 2795 2796 2797 2798 2799 2800 2801
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,
2802
            deprecation: None,
2803 2804 2805 2806
        }
    }
}

2807
impl<'tcx> Clean<Item> for ty::AssociatedType<'tcx> {
2808
    fn clean(&self, cx: &DocContext) -> Item {
2809
        let my_name = self.name.clean(cx);
2810 2811 2812 2813 2814 2815

        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.
2816 2817
            let def = cx.tcx().lookup_trait_def(did);
            let predicates = cx.tcx().lookup_predicates(did);
2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840
            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![]
        };
2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851

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

2852 2853
        Item {
            source: DUMMY_SP.clean(cx),
2854
            name: Some(self.name.clean(cx)),
2855
            attrs: inline::load_attrs(cx, cx.tcx(), self.def_id),
2856
            inner: AssociatedTypeItem(bounds, self.ty.clean(cx)),
2857
            visibility: self.vis.clean(cx),
2858
            def_id: self.def_id,
2859 2860
            stability: cx.tcx().lookup_stability(self.def_id).clean(cx),
            deprecation: cx.tcx().lookup_deprecation(self.def_id).clean(cx),
2861 2862 2863 2864
        }
    }
}

2865 2866
impl<'a> Clean<Typedef> for (ty::TypeScheme<'a>, ty::GenericPredicates<'a>,
                             ParamSpace) {
2867
    fn clean(&self, cx: &DocContext) -> Typedef {
2868
        let (ref ty_scheme, ref predicates, ps) = *self;
2869 2870
        Typedef {
            type_: ty_scheme.ty.clean(cx),
2871
            generics: (&ty_scheme.generics, predicates, ps).clean(cx)
2872 2873 2874 2875
        }
    }
}

N
Niko Matsakis 已提交
2876
fn lang_struct(cx: &DocContext, did: Option<DefId>,
2877
               t: ty::Ty, name: &str,
A
Alex Crichton 已提交
2878 2879 2880
               fallback: fn(Box<Type>) -> Type) -> Type {
    let did = match did {
        Some(did) => did,
2881
        None => return fallback(box t.clean(cx)),
A
Alex Crichton 已提交
2882
    };
M
mitaa 已提交
2883
    inline::record_extern_fqn(cx, did, TypeStruct);
A
Alex Crichton 已提交
2884 2885 2886 2887 2888 2889 2890
    ResolvedPath {
        typarams: None,
        did: did,
        path: Path {
            global: false,
            segments: vec![PathSegment {
                name: name.to_string(),
2891 2892 2893
                params: PathParameters::AngleBracketed {
                    lifetimes: vec![],
                    types: vec![t.clean(cx)],
2894
                    bindings: vec![]
2895
                }
A
Alex Crichton 已提交
2896 2897
            }],
        },
2898
        is_generic: false,
A
Alex Crichton 已提交
2899 2900
    }
}
2901 2902

/// An equality constraint on an associated type, e.g. `A=Bar` in `Foo<A=Bar>`
J
Jorge Aparicio 已提交
2903
#[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Debug)]
2904 2905 2906 2907 2908
pub struct TypeBinding {
    pub name: String,
    pub ty: Type
}

2909
impl Clean<TypeBinding> for hir::TypeBinding {
2910 2911
    fn clean(&self, cx: &DocContext) -> TypeBinding {
        TypeBinding {
2912
            name: self.name.clean(cx),
2913 2914 2915 2916
            ty: self.ty.clean(cx)
        }
    }
}