mod.rs 94.7 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 19
pub use self::Type::*;
pub use self::PrimitiveType::*;
pub use self::TypeKind::*;
pub use self::StructField::*;
pub use self::VariantKind::*;
pub use self::Mutability::*;
20
pub use self::Import::*;
S
Steven Fackler 已提交
21 22 23 24 25 26
pub use self::ItemEnum::*;
pub use self::Attribute::*;
pub use self::TyParamBound::*;
pub use self::SelfTy::*;
pub use self::FunctionRetTy::*;

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, special_idents};
35
use syntax::ptr::P;
C
Corey Richardson 已提交
36

37
use rustc_trans::back::link;
A
Ariel Ben-Yehuda 已提交
38
use rustc::middle::cstore::{self, CrateStore};
39
use rustc::middle::def::Def;
40
use rustc::middle::def_id::{DefId, DefIndex};
41
use rustc::middle::subst::{self, ParamSpace, VecPerParamSpace};
42
use rustc::middle::ty;
43
use rustc::middle::stability;
44

45 46
use rustc_front::hir;

47 48
use std::collections::HashMap;
use std::path::PathBuf;
49
use std::rc::Rc;
50
use std::u32;
51

52
use core::DocContext;
C
Corey Richardson 已提交
53 54 55
use doctree;
use visit_ast;

56 57
/// A stable identifier to the particular version of JSON output.
/// Increment this when the `Crate` and related structures change.
58
pub const SCHEMA_VERSION: &'static str = "0.8.3";
59

60
mod inline;
61
mod simplify;
62

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

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

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

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

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

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

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

C
Corey Richardson 已提交
100
impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
101
    fn clean(&self, cx: &DocContext) -> Option<U> {
C
Corey Richardson 已提交
102 103
        match self {
            &None => None,
104
            &Some(ref v) => Some(v.clean(cx))
C
Corey Richardson 已提交
105 106 107 108
        }
    }
}

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

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

J
Jorge Aparicio 已提交
121
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
122
pub struct Crate {
123
    pub name: String,
A
Alex Crichton 已提交
124
    pub src: PathBuf,
125 126
    pub module: Option<Item>,
    pub externs: Vec<(ast::CrateNum, ExternalCrate)>,
127
    pub primitives: Vec<PrimitiveType>,
N
Niko Matsakis 已提交
128
    pub external_traits: HashMap<DefId, Trait>,
C
Corey Richardson 已提交
129 130
}

A
Ariel Ben-Yehuda 已提交
131 132
struct CrateNum(ast::CrateNum);

133 134
impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
    fn clean(&self, cx: &DocContext) -> Crate {
135 136
        use rustc::session::config::Input;

137 138 139 140
        if let Some(t) = cx.tcx_opt() {
            cx.deref_trait_did.set(t.lang_items.deref_trait());
        }

141
        let mut externs = Vec::new();
A
Ariel Ben-Yehuda 已提交
142 143 144
        for cnum in cx.sess().cstore.crates() {
            externs.push((cnum, CrateNum(cnum).clean(cx)));
        }
145
        externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
C
Corey Richardson 已提交
146

147
        // Figure out the name of this crate
148
        let input = &cx.input;
149
        let name = link::find_crate_name(None, &self.attrs, input);
150

151
        // Clean the crate, translating the entire libsyntax AST to one that is
152
        // understood by rustdoc.
153
        let mut module = self.module.clean(cx);
154 155 156

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

203 204
        let src = match cx.input {
            Input::File(ref path) => path.clone(),
A
Aaron Turon 已提交
205
            Input::Str(_) => PathBuf::new() // FIXME: this is wrong
206 207
        };

C
Corey Richardson 已提交
208
        Crate {
209
            name: name.to_string(),
210
            src: src,
211
            module: Some(module),
212
            externs: externs,
213
            primitives: primitives,
214 215
            external_traits: cx.external_traits.borrow_mut().take()
                               .unwrap_or(HashMap::new()),
216 217 218 219
        }
    }
}

J
Jorge Aparicio 已提交
220
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
221
pub struct ExternalCrate {
222
    pub name: String,
223
    pub attrs: Vec<Attribute>,
224
    pub primitives: Vec<PrimitiveType>,
225 226
}

A
Ariel Ben-Yehuda 已提交
227
impl Clean<ExternalCrate> for CrateNum {
228
    fn clean(&self, cx: &DocContext) -> ExternalCrate {
229
        let mut primitives = Vec::new();
230
        cx.tcx_opt().map(|tcx| {
A
Ariel Ben-Yehuda 已提交
231 232
            for item in tcx.sess.cstore.crate_top_level_items(self.0) {
                let did = match item.def {
233
                    cstore::DlDef(Def::Mod(did)) => did,
A
Ariel Ben-Yehuda 已提交
234
                    _ => continue
235
                };
236
                let attrs = inline::load_attrs(cx, tcx, did);
237
                PrimitiveType::find(&attrs).map(|prim| primitives.push(prim));
A
Ariel Ben-Yehuda 已提交
238
            }
239
        });
240
        ExternalCrate {
A
Ariel Ben-Yehuda 已提交
241 242
            name: cx.sess().cstore.crate_name(self.0),
            attrs: cx.sess().cstore.crate_attrs(self.0).clean(cx),
243
            primitives: primitives,
C
Corey Richardson 已提交
244 245 246 247 248 249 250
        }
    }
}

/// 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 已提交
251
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
252 253
pub struct Item {
    /// Stringified span
254
    pub source: Span,
C
Corey Richardson 已提交
255
    /// Not everything has a name. E.g., impls
256
    pub name: Option<String>,
257 258 259
    pub attrs: Vec<Attribute> ,
    pub inner: ItemEnum,
    pub visibility: Option<Visibility>,
N
Niko Matsakis 已提交
260
    pub def_id: DefId,
261
    pub stability: Option<Stability>,
262
    pub deprecation: Option<Deprecation>,
C
Corey Richardson 已提交
263 264
}

265 266 267 268
impl Item {
    /// Finds the `doc` attribute as a List and returns the list of attributes
    /// nested inside.
    pub fn doc_list<'a>(&'a self) -> Option<&'a [Attribute]> {
269
        for attr in &self.attrs {
270
            match *attr {
271
                List(ref x, ref list) if "doc" == *x => {
272
                    return Some(list);
273
                }
274 275 276 277 278 279 280 281 282
                _ => {}
            }
        }
        return None;
    }

    /// Finds the `doc` attribute as a NameValue and returns the corresponding
    /// value found.
    pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
283
        for attr in &self.attrs {
284
            match *attr {
285
                NameValue(ref x, ref v) if "doc" == *x => {
286
                    return Some(v);
287
                }
288 289 290 291 292 293
                _ => {}
            }
        }
        return None;
    }

294 295
    pub fn is_hidden_from_doc(&self) -> bool {
        match self.doc_list() {
296 297
            Some(l) => {
                for innerattr in l {
298
                    match *innerattr {
299
                        Word(ref s) if "hidden" == *s => {
300 301
                            return true
                        }
302 303 304 305 306 307 308 309 310
                        _ => (),
                    }
                }
            },
            None => ()
        }
        return false;
    }

311
    pub fn is_mod(&self) -> bool {
A
Alex Crichton 已提交
312
        match self.inner { ModuleItem(..) => true, _ => false }
313 314
    }
    pub fn is_trait(&self) -> bool {
A
Alex Crichton 已提交
315
        match self.inner { TraitItem(..) => true, _ => false }
316 317
    }
    pub fn is_struct(&self) -> bool {
A
Alex Crichton 已提交
318
        match self.inner { StructItem(..) => true, _ => false }
319 320
    }
    pub fn is_enum(&self) -> bool {
A
Alex Crichton 已提交
321
        match self.inner { EnumItem(..) => true, _ => false }
322 323
    }
    pub fn is_fn(&self) -> bool {
A
Alex Crichton 已提交
324
        match self.inner { FunctionItem(..) => true, _ => false }
325
    }
326 327 328 329 330

    pub fn stability_class(&self) -> String {
        match self.stability {
            Some(ref s) => {
                let mut base = match s.level {
V
Vadim Petrochenkov 已提交
331 332
                    stability::Unstable => "unstable".to_string(),
                    stability::Stable => String::new(),
333
                };
334
                if !s.deprecated_since.is_empty() {
335 336 337 338 339 340 341
                    base.push_str(" deprecated");
                }
                base
            }
            _ => String::new(),
        }
    }
342 343 344 345 346 347 348 349

    pub fn stable_since(&self) -> Option<&str> {
        if let Some(ref s) = self.stability {
            return Some(&s.since[..]);
        }

        None
    }
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 370 371
    MethodItem(Method),
    StructFieldItem(StructField),
    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),
C
Corey Richardson 已提交
381 382
}

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

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

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

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

J
Jorge Aparicio 已提交
444
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
445
pub enum Attribute {
446 447 448
    Word(String),
    List(String, Vec<Attribute> ),
    NameValue(String, String)
C
Corey Richardson 已提交
449 450
}

451
impl Clean<Attribute> for ast::MetaItem {
452
    fn clean(&self, cx: &DocContext) -> Attribute {
C
Corey Richardson 已提交
453
        match self.node {
454 455
            ast::MetaItemKind::Word(ref s) => Word(s.to_string()),
            ast::MetaItemKind::List(ref s, ref l) => {
G
GuillaumeGomez 已提交
456
                List(s.to_string(), l.clean(cx))
457
            }
458
            ast::MetaItemKind::NameValue(ref s, ref v) => {
G
GuillaumeGomez 已提交
459
                NameValue(s.to_string(), lit_to_string(v))
460
            }
C
Corey Richardson 已提交
461 462 463 464
        }
    }
}

465
impl Clean<Attribute> for ast::Attribute {
466
    fn clean(&self, cx: &DocContext) -> Attribute {
467
        self.with_desugared_doc(|a| a.node.value.clean(cx))
C
Corey Richardson 已提交
468 469 470
    }
}

471
// This is a rough approximation that gets us what we want.
472
impl attr::AttrMetaMethods for Attribute {
473
    fn name(&self) -> InternedString {
474
        match *self {
475
            Word(ref n) | List(ref n, _) | NameValue(ref n, _) => {
476
                token::intern_and_get_ident(n)
477
            }
478 479 480
        }
    }

481
    fn value_str(&self) -> Option<InternedString> {
482
        match *self {
483
            NameValue(_, ref v) => {
484
                Some(token::intern_and_get_ident(v))
485
            }
486 487 488
            _ => None,
        }
    }
489
    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<ast::MetaItem>]> { None }
490
    fn span(&self) -> codemap::Span { unimplemented!() }
491
}
492 493 494
impl<'a> attr::AttrMetaMethods for &'a Attribute {
    fn name(&self) -> InternedString { (**self).name() }
    fn value_str(&self) -> Option<InternedString> { (**self).value_str() }
495
    fn meta_item_list(&self) -> Option<&[P<ast::MetaItem>]> { None }
496
    fn span(&self) -> codemap::Span { unimplemented!() }
497
}
498

J
Jorge Aparicio 已提交
499
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
500
pub struct TyParam {
501
    pub name: String,
N
Niko Matsakis 已提交
502
    pub did: DefId,
503
    pub bounds: Vec<TyParamBound>,
504
    pub default: Option<Type>,
505
}
C
Corey Richardson 已提交
506

507
impl Clean<TyParam> for hir::TyParam {
508
    fn clean(&self, cx: &DocContext) -> TyParam {
C
Corey Richardson 已提交
509
        TyParam {
510
            name: self.name.clean(cx),
511
            did: cx.map.local_def_id(self.id),
512
            bounds: self.bounds.clean(cx),
513
            default: self.default.clean(cx),
C
Corey Richardson 已提交
514 515 516 517
        }
    }
}

518
impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> {
519 520
    fn clean(&self, cx: &DocContext) -> TyParam {
        cx.external_typarams.borrow_mut().as_mut().unwrap()
521
          .insert(self.def_id, self.name.clean(cx));
522
        TyParam {
523
            name: self.name.clean(cx),
524
            did: self.def_id,
525
            bounds: vec![], // these are filled in from the where-clauses
526
            default: self.default.clean(cx),
527 528 529 530
        }
    }
}

J
Jorge Aparicio 已提交
531
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
532
pub enum TyParamBound {
533
    RegionBound(Lifetime),
534
    TraitBound(PolyTrait, hir::TraitBoundModifier)
C
Corey Richardson 已提交
535 536
}

537 538
impl TyParamBound {
    fn maybe_sized(cx: &DocContext) -> TyParamBound {
539
        use rustc_front::hir::TraitBoundModifier as TBM;
540
        let mut sized_bound = ty::BoundSized.clean(cx);
541 542 543 544 545 546 547
        if let TyParamBound::TraitBound(_, ref mut tbm) = sized_bound {
            *tbm = TBM::Maybe
        };
        sized_bound
    }

    fn is_sized_bound(&self, cx: &DocContext) -> bool {
548
        use rustc_front::hir::TraitBoundModifier as TBM;
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
        if let Some(tcx) = cx.tcx_opt() {
            let sized_did = match tcx.lang_items.sized_trait() {
                Some(did) => did,
                None => return false
            };
            if let TyParamBound::TraitBound(PolyTrait {
                trait_: Type::ResolvedPath { did, .. }, ..
            }, TBM::None) = *self {
                if did == sized_did {
                    return true
                }
            }
        }
        false
    }
}

566
impl Clean<TyParamBound> for hir::TyParamBound {
567
    fn clean(&self, cx: &DocContext) -> TyParamBound {
C
Corey Richardson 已提交
568
        match *self {
569 570
            hir::RegionTyParamBound(lt) => RegionBound(lt.clean(cx)),
            hir::TraitTyParamBound(ref t, modifier) => TraitBound(t.clean(cx), modifier),
C
Corey Richardson 已提交
571 572 573 574
        }
    }
}

575 576 577 578
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)));
579
        for bb in &self.builtin_bounds {
580
            tp_bounds.push(bb.clean(cx));
581
        }
N
Niko Matsakis 已提交
582

583
        let mut bindings = vec![];
584
        for &ty::Binder(ref pb) in &self.projection_bounds {
585 586 587 588 589
            bindings.push(TypeBinding {
                name: pb.projection_ty.item_name.clean(cx),
                ty: pb.ty.clean(cx)
            });
        }
N
Niko Matsakis 已提交
590

591
        (tp_bounds, bindings)
592 593 594
    }
}

N
Niko Matsakis 已提交
595
fn external_path_params(cx: &DocContext, trait_did: Option<DefId>,
596
                        bindings: Vec<TypeBinding>, substs: &subst::Substs) -> PathParameters {
597
    let lifetimes = substs.regions().get_slice(subst::TypeSpace)
598
                    .iter()
599
                    .filter_map(|v| v.clean(cx))
600
                    .collect();
601
    let types = substs.types.get_slice(subst::TypeSpace).to_vec();
602 603 604 605

    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() => {
606
            assert_eq!(types.len(), 1);
607
            let inputs = match types[0].sty {
608
                ty::TyTuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
609 610 611
                _ => {
                    return PathParameters::AngleBracketed {
                        lifetimes: lifetimes,
612
                        types: types.clean(cx),
613
                        bindings: bindings
614 615 616
                    }
                }
            };
617 618 619
            let output = None;
            // FIXME(#20299) return type comes from a projection now
            // match types[1].sty {
620
            //     ty::TyTuple(ref v) if v.is_empty() => None, // -> ()
621 622
            //     _ => Some(types[1].clean(cx))
            // };
623 624 625 626 627 628 629 630 631
            PathParameters::Parenthesized {
                inputs: inputs,
                output: output
            }
        },
        (_, _) => {
            PathParameters::AngleBracketed {
                lifetimes: lifetimes,
                types: types.clean(cx),
632
                bindings: bindings
633 634 635 636 637 638 639
            }
        }
    }
}

// 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 已提交
640
fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>,
641
                 bindings: Vec<TypeBinding>, substs: &subst::Substs) -> Path {
642 643 644
    Path {
        global: false,
        segments: vec![PathSegment {
645
            name: name.to_string(),
646
            params: external_path_params(cx, trait_did, bindings, substs)
647
        }],
648 649 650 651
    }
}

impl Clean<TyParamBound> for ty::BuiltinBound {
652 653 654
    fn clean(&self, cx: &DocContext) -> TyParamBound {
        let tcx = match cx.tcx_opt() {
            Some(tcx) => tcx,
655
            None => return RegionBound(Lifetime::statik())
656
        };
657
        let empty = subst::Substs::empty();
658 659
        let (did, path) = match *self {
            ty::BoundSend =>
660
                (tcx.lang_items.send_trait().unwrap(),
661
                 external_path(cx, "Send", None, vec![], &empty)),
662
            ty::BoundSized =>
663
                (tcx.lang_items.sized_trait().unwrap(),
664
                 external_path(cx, "Sized", None, vec![], &empty)),
665
            ty::BoundCopy =>
666
                (tcx.lang_items.copy_trait().unwrap(),
667
                 external_path(cx, "Copy", None, vec![], &empty)),
A
Alex Crichton 已提交
668 669
            ty::BoundSync =>
                (tcx.lang_items.sync_trait().unwrap(),
670
                 external_path(cx, "Sync", None, vec![], &empty)),
671
        };
M
mitaa 已提交
672
        inline::record_extern_fqn(cx, did, TypeTrait);
673 674 675 676 677
        TraitBound(PolyTrait {
            trait_: ResolvedPath {
                path: path,
                typarams: None,
                did: did,
678
                is_generic: false,
679 680
            },
            lifetimes: vec![]
681
        }, hir::TraitBoundModifier::None)
682 683 684
    }
}

685
impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
686 687 688
    fn clean(&self, cx: &DocContext) -> TyParamBound {
        let tcx = match cx.tcx_opt() {
            Some(tcx) => tcx,
689
            None => return RegionBound(Lifetime::statik())
690
        };
M
mitaa 已提交
691 692
        inline::record_extern_fqn(cx, self.def_id, TypeTrait);
        let path = external_path(cx, &tcx.item_name(self.def_id).as_str(),
693
                                 Some(self.def_id), vec![], self.substs);
694

695
        debug!("ty::TraitRef\n  substs.types(TypeSpace): {:?}\n",
696 697 698 699
               self.substs.types.get_slice(ParamSpace::TypeSpace));

        // collect any late bound regions
        let mut late_bounds = vec![];
700
        for &ty_s in self.substs.types.get_slice(ParamSpace::TypeSpace) {
701
            if let ty::TyTuple(ref ts) = ty_s.sty {
702
                for &ty_s in ts {
703 704
                    if let ty::TyRef(ref reg, _) = ty_s.sty {
                        if let &ty::Region::ReLateBound(_, _) = *reg {
705
                            debug!("  hit an ReLateBound {:?}", reg);
706 707 708 709 710 711 712 713 714 715
                            if let Some(lt) = reg.clean(cx) {
                                late_bounds.push(lt)
                            }
                        }
                    }
                }
            }
        }

        TraitBound(PolyTrait {
716 717 718 719 720 721
            trait_: ResolvedPath {
                path: path,
                typarams: None,
                did: self.def_id,
                is_generic: false,
            },
722
            lifetimes: late_bounds
723
        }, hir::TraitBoundModifier::None)
724 725 726
    }
}

727
impl<'tcx> Clean<Option<Vec<TyParamBound>>> for subst::Substs<'tcx> {
728
    fn clean(&self, cx: &DocContext) -> Option<Vec<TyParamBound>> {
729
        let mut v = Vec::new();
730
        v.extend(self.regions().iter().filter_map(|r| r.clean(cx)).map(RegionBound));
731 732 733
        v.extend(self.types.iter().map(|t| TraitBound(PolyTrait {
            trait_: t.clean(cx),
            lifetimes: vec![]
734
        }, hir::TraitBoundModifier::None)));
735
        if !v.is_empty() {Some(v)} else {None}
736 737 738
    }
}

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

742 743 744
impl Lifetime {
    pub fn get_ref<'a>(&'a self) -> &'a str {
        let Lifetime(ref s) = *self;
745
        let s: &'a str = s;
746 747
        return s;
    }
748 749 750 751

    pub fn statik() -> Lifetime {
        Lifetime("'static".to_string())
    }
752 753
}

754
impl Clean<Lifetime> for hir::Lifetime {
755
    fn clean(&self, _: &DocContext) -> Lifetime {
756
        Lifetime(self.name.to_string())
C
Corey Richardson 已提交
757 758 759
    }
}

760
impl Clean<Lifetime> for hir::LifetimeDef {
761
    fn clean(&self, _: &DocContext) -> Lifetime {
762
        Lifetime(self.lifetime.name.to_string())
763 764 765
    }
}

766
impl Clean<Lifetime> for ty::RegionParameterDef {
767
    fn clean(&self, _: &DocContext) -> Lifetime {
768
        Lifetime(self.name.to_string())
769 770 771 772
    }
}

impl Clean<Option<Lifetime>> for ty::Region {
773
    fn clean(&self, cx: &DocContext) -> Option<Lifetime> {
774
        match *self {
775
            ty::ReStatic => Some(Lifetime::statik()),
776
            ty::ReLateBound(_, ty::BrNamed(_, name)) =>
777
                Some(Lifetime(name.to_string())),
N
Niko Matsakis 已提交
778
            ty::ReEarlyBound(ref data) => Some(Lifetime(data.name.clean(cx))),
779 780 781 782

            ty::ReLateBound(..) |
            ty::ReFree(..) |
            ty::ReScope(..) |
783 784
            ty::ReVar(..) |
            ty::ReSkolemized(..) |
V
Vadim Petrochenkov 已提交
785
            ty::ReEmpty => None
786 787 788 789
        }
    }
}

J
Jorge Aparicio 已提交
790
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
791 792 793
pub enum WherePredicate {
    BoundPredicate { ty: Type, bounds: Vec<TyParamBound> },
    RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>},
794
    EqPredicate { lhs: Type, rhs: Type }
795 796
}

797
impl Clean<WherePredicate> for hir::WherePredicate {
798
    fn clean(&self, cx: &DocContext) -> WherePredicate {
N
Nick Cameron 已提交
799
        match *self {
800
            hir::WherePredicate::BoundPredicate(ref wbp) => {
801
                WherePredicate::BoundPredicate {
802
                    ty: wbp.bounded_ty.clean(cx),
N
Nick Cameron 已提交
803 804 805
                    bounds: wbp.bounds.clean(cx)
                }
            }
806

807
            hir::WherePredicate::RegionPredicate(ref wrp) => {
808 809 810 811 812 813
                WherePredicate::RegionPredicate {
                    lifetime: wrp.lifetime.clean(cx),
                    bounds: wrp.bounds.clean(cx)
                }
            }

814
            hir::WherePredicate::EqPredicate(_) => {
815
                unimplemented!() // FIXME(#20041)
N
Nick Cameron 已提交
816
            }
817 818 819 820
        }
    }
}

821 822 823 824 825 826 827 828 829
impl<'a> Clean<WherePredicate> for ty::Predicate<'a> {
    fn clean(&self, cx: &DocContext) -> WherePredicate {
        use rustc::middle::ty::Predicate;

        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),
830 831 832
            Predicate::Projection(ref pred) => pred.clean(cx),
            Predicate::WellFormed(_) => panic!("not user writable"),
            Predicate::ObjectSafe(_) => panic!("not user writable"),
833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889
        }
    }
}

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_,
890 891 892
            TyParamBound::RegionBound(_) => {
                panic!("cleaning a trait got a region")
            }
893 894 895 896 897 898 899 900 901
        };
        Type::QPath {
            name: self.item_name.clean(cx),
            self_type: box self.trait_ref.self_ty().clean(cx),
            trait_: box trait_
        }
    }
}

902
// maybe use a Generic enum and use Vec<Generic>?
J
Jorge Aparicio 已提交
903
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
904
pub struct Generics {
905 906
    pub lifetimes: Vec<Lifetime>,
    pub type_params: Vec<TyParam>,
907
    pub where_predicates: Vec<WherePredicate>
908
}
C
Corey Richardson 已提交
909

910
impl Clean<Generics> for hir::Generics {
911
    fn clean(&self, cx: &DocContext) -> Generics {
C
Corey Richardson 已提交
912
        Generics {
913 914
            lifetimes: self.lifetimes.clean(cx),
            type_params: self.ty_params.clean(cx),
915
            where_predicates: self.where_clause.predicates.clean(cx)
C
Corey Richardson 已提交
916 917 918 919
        }
    }
}

920 921 922
impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
                                    &'a ty::GenericPredicates<'tcx>,
                                    subst::ParamSpace) {
923
    fn clean(&self, cx: &DocContext) -> Generics {
924 925 926
        use std::collections::HashSet;
        use self::WherePredicate as WP;

927 928
        let (gens, preds, space) = *self;

929 930 931
        // Bounds in the type_params and lifetimes fields are repeated in the
        // predicates field (see rustc_typeck::collect::ty_generics), so remove
        // them.
932
        let stripped_typarams = gens.types.get_slice(space).iter().map(|tp| {
933
            tp.clean(cx)
934 935 936 937 938 939 940
        }).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<_>>();

941 942
        let mut where_predicates = preds.predicates.get_slice(space)
                                                   .to_vec().clean(cx);
943

944
        // Type parameters and have a Sized bound by default unless removed with
945 946
        // ?Sized.  Scan through the predicates and mark any type parameter with
        // a Sized bound, removing the bounds as we find them.
947 948
        //
        // Note that associated types also have a sized bound by default, but we
949
        // don't actually know the set of associated types right here so that's
950
        // handled in cleaning associated types
951
        let mut sized_params = HashSet::new();
952 953 954 955 956 957 958 959 960
        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
                    }
961
                }
962
                _ => true,
963
            }
964
        });
965

966
        // Run through the type parameters again and insert a ?Sized
967
        // unbound for any we didn't find to be Sized.
968
        for tp in &stripped_typarams {
969 970 971
            if !sized_params.contains(&tp.name) {
                where_predicates.push(WP::BoundPredicate {
                    ty: Type::Generic(tp.name.clone()),
972
                    bounds: vec![TyParamBound::maybe_sized(cx)],
973 974 975 976 977 978 979 980
                })
            }
        }

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

981
        Generics {
982
            type_params: simplify::ty_params(stripped_typarams),
983
            lifetimes: stripped_lifetimes,
984
            where_predicates: simplify::where_clauses(cx, where_predicates),
985 986 987 988
        }
    }
}

J
Jorge Aparicio 已提交
989
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
990
pub struct Method {
991 992
    pub generics: Generics,
    pub self_: SelfTy,
993 994
    pub unsafety: hir::Unsafety,
    pub constness: hir::Constness,
995
    pub decl: FnDecl,
996
    pub abi: Abi,
C
Corey Richardson 已提交
997 998
}

999
impl Clean<Method> for hir::MethodSig {
1000
    fn clean(&self, cx: &DocContext) -> Method {
1001 1002
        let all_inputs = &self.decl.inputs;
        let inputs = match self.explicit_self.node {
1003
            hir::SelfStatic => &**all_inputs,
J
Jorge Aparicio 已提交
1004
            _ => &all_inputs[1..]
1005 1006
        };
        let decl = FnDecl {
1007
            inputs: Arguments {
1008
                values: inputs.clean(cx),
1009
            },
1010
            output: self.decl.output.clean(cx),
1011
            variadic: false,
1012
            attrs: Vec::new()
1013
        };
1014
        Method {
1015 1016
            generics: self.generics.clean(cx),
            self_: self.explicit_self.node.clean(cx),
1017 1018
            unsafety: self.unsafety,
            constness: self.constness,
1019
            decl: decl,
1020
            abi: self.abi
C
Corey Richardson 已提交
1021 1022 1023 1024
        }
    }
}

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

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

J
Jorge Aparicio 已提交
1058
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
1059 1060 1061 1062
pub enum SelfTy {
    SelfStatic,
    SelfValue,
    SelfBorrowed(Option<Lifetime>, Mutability),
1063
    SelfExplicit(Type),
C
Corey Richardson 已提交
1064 1065
}

1066
impl Clean<SelfTy> for hir::ExplicitSelf_ {
1067
    fn clean(&self, cx: &DocContext) -> SelfTy {
1068
        match *self {
1069 1070 1071
            hir::SelfStatic => SelfStatic,
            hir::SelfValue(_) => SelfValue,
            hir::SelfRegion(ref lt, ref mt, _) => {
1072
                SelfBorrowed(lt.clean(cx), mt.clean(cx))
1073
            }
1074
            hir::SelfExplicit(ref typ, _) => SelfExplicit(typ.clean(cx)),
C
Corey Richardson 已提交
1075 1076 1077 1078
        }
    }
}

J
Jorge Aparicio 已提交
1079
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1080
pub struct Function {
1081 1082
    pub decl: FnDecl,
    pub generics: Generics,
1083 1084
    pub unsafety: hir::Unsafety,
    pub constness: hir::Constness,
1085
    pub abi: Abi,
C
Corey Richardson 已提交
1086 1087 1088
}

impl Clean<Item> for doctree::Function {
1089
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1090
        Item {
1091 1092 1093 1094 1095
            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),
1096
            deprecation: self.depr.clean(cx),
1097
            def_id: cx.map.local_def_id(self.id),
C
Corey Richardson 已提交
1098
            inner: FunctionItem(Function {
1099 1100
                decl: self.decl.clean(cx),
                generics: self.generics.clean(cx),
N
Niko Matsakis 已提交
1101
                unsafety: self.unsafety,
1102
                constness: self.constness,
1103
                abi: self.abi,
C
Corey Richardson 已提交
1104 1105 1106 1107 1108
            }),
        }
    }
}

J
Jorge Aparicio 已提交
1109
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
1110
pub struct FnDecl {
1111
    pub inputs: Arguments,
1112
    pub output: FunctionRetTy,
1113
    pub variadic: bool,
1114 1115
    pub attrs: Vec<Attribute>,
}
C
Corey Richardson 已提交
1116

J
Jorge Aparicio 已提交
1117
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1118
pub struct Arguments {
1119
    pub values: Vec<Argument>,
1120 1121
}

1122
impl Clean<FnDecl> for hir::FnDecl {
1123
    fn clean(&self, cx: &DocContext) -> FnDecl {
C
Corey Richardson 已提交
1124
        FnDecl {
1125
            inputs: Arguments {
1126
                values: self.inputs.clean(cx),
1127
            },
1128
            output: self.output.clean(cx),
1129
            variadic: self.variadic,
1130
            attrs: Vec::new()
C
Corey Richardson 已提交
1131 1132 1133 1134
        }
    }
}

1135
impl<'tcx> Clean<Type> for ty::FnOutput<'tcx> {
J
Jakub Bukaj 已提交
1136 1137 1138 1139 1140 1141 1142 1143
    fn clean(&self, cx: &DocContext) -> Type {
        match *self {
            ty::FnConverging(ty) => ty.clean(cx),
            ty::FnDiverging => Bottom
        }
    }
}

N
Niko Matsakis 已提交
1144
impl<'a, 'tcx> Clean<FnDecl> for (DefId, &'a ty::PolyFnSig<'tcx>) {
1145
    fn clean(&self, cx: &DocContext) -> FnDecl {
1146
        let (did, sig) = *self;
1147 1148
        let mut names = if let Some(_) = cx.map.as_local_node_id(did) {
            vec![].into_iter()
1149
        } else {
A
Ariel Ben-Yehuda 已提交
1150
            cx.tcx().sess.cstore.method_arg_names(did).into_iter()
1151
        }.peekable();
1152
        if names.peek().map(|s| &**s) == Some("self") {
1153 1154
            let _ = names.next();
        }
1155
        FnDecl {
1156
            output: Return(sig.0.output.clean(cx)),
1157
            attrs: Vec::new(),
1158
            variadic: sig.0.variadic,
1159
            inputs: Arguments {
1160
                values: sig.0.inputs.iter().map(|t| {
1161
                    Argument {
1162
                        type_: t.clean(cx),
1163
                        id: 0,
1164
                        name: names.next().unwrap_or("".to_string()),
1165 1166 1167 1168 1169 1170 1171
                    }
                }).collect(),
            },
        }
    }
}

J
Jorge Aparicio 已提交
1172
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
1173
pub struct Argument {
1174
    pub type_: Type,
1175
    pub name: String,
1176
    pub id: ast::NodeId,
C
Corey Richardson 已提交
1177 1178
}

1179
impl Clean<Argument> for hir::Arg {
1180
    fn clean(&self, cx: &DocContext) -> Argument {
C
Corey Richardson 已提交
1181
        Argument {
1182
            name: name_from_pat(&*self.pat),
1183
            type_: (self.ty.clean(cx)),
C
Corey Richardson 已提交
1184 1185 1186 1187 1188
            id: self.id
        }
    }
}

J
Jorge Aparicio 已提交
1189
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1190 1191
pub enum FunctionRetTy {
    Return(Type),
1192
    DefaultReturn,
1193
    NoReturn
C
Corey Richardson 已提交
1194 1195
}

1196
impl Clean<FunctionRetTy> for hir::FunctionRetTy {
1197
    fn clean(&self, cx: &DocContext) -> FunctionRetTy {
C
Corey Richardson 已提交
1198
        match *self {
1199 1200 1201
            hir::Return(ref typ) => Return(typ.clean(cx)),
            hir::DefaultReturn(..) => DefaultReturn,
            hir::NoReturn(..) => NoReturn
C
Corey Richardson 已提交
1202 1203 1204 1205
        }
    }
}

J
Jorge Aparicio 已提交
1206
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1207
pub struct Trait {
1208
    pub unsafety: hir::Unsafety,
1209
    pub items: Vec<Item>,
1210
    pub generics: Generics,
1211
    pub bounds: Vec<TyParamBound>,
C
Corey Richardson 已提交
1212 1213 1214
}

impl Clean<Item> for doctree::Trait {
1215
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1216
        Item {
1217 1218 1219
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
1220
            def_id: cx.map.local_def_id(self.id),
1221 1222
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
1223
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
1224
            inner: TraitItem(Trait {
1225
                unsafety: self.unsafety,
1226 1227 1228
                items: self.items.clean(cx),
                generics: self.generics.clean(cx),
                bounds: self.bounds.clean(cx),
C
Corey Richardson 已提交
1229 1230 1231 1232 1233
            }),
        }
    }
}

1234
impl Clean<Type> for hir::TraitRef {
1235
    fn clean(&self, cx: &DocContext) -> Type {
N
Niko Matsakis 已提交
1236
        resolve_type(cx, self.path.clean(cx), self.ref_id)
C
Corey Richardson 已提交
1237 1238 1239
    }
}

1240
impl Clean<PolyTrait> for hir::PolyTraitRef {
1241 1242 1243 1244 1245
    fn clean(&self, cx: &DocContext) -> PolyTrait {
        PolyTrait {
            trait_: self.trait_ref.clean(cx),
            lifetimes: self.bound_lifetimes.clean(cx)
        }
N
Niko Matsakis 已提交
1246 1247 1248
    }
}

1249
impl Clean<Item> for hir::TraitItem {
1250 1251
    fn clean(&self, cx: &DocContext) -> Item {
        let inner = match self.node {
1252
            hir::ConstTraitItem(ref ty, ref default) => {
1253 1254 1255 1256
                AssociatedConstItem(ty.clean(cx),
                                    default.as_ref().map(|expr|
                                                         expr.span.to_src(cx)))
            }
1257
            hir::MethodTraitItem(ref sig, Some(_)) => {
1258 1259
                MethodItem(sig.clean(cx))
            }
1260
            hir::MethodTraitItem(ref sig, None) => {
1261 1262
                TyMethodItem(sig.clean(cx))
            }
1263
            hir::TypeTraitItem(ref bounds, ref default) => {
1264 1265 1266 1267
                AssociatedTypeItem(bounds.clean(cx), default.clean(cx))
            }
        };
        Item {
V
Vadim Petrochenkov 已提交
1268
            name: Some(self.name.clean(cx)),
1269 1270
            attrs: self.attrs.clean(cx),
            source: self.span.clean(cx),
1271
            def_id: cx.map.local_def_id(self.id),
1272
            visibility: None,
1273
            stability: get_stability(cx, cx.map.local_def_id(self.id)),
1274
            deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
1275
            inner: inner
1276 1277 1278 1279
        }
    }
}

1280
impl Clean<Item> for hir::ImplItem {
1281 1282
    fn clean(&self, cx: &DocContext) -> Item {
        let inner = match self.node {
1283
            hir::ImplItemKind::Const(ref ty, ref expr) => {
1284 1285
                AssociatedConstItem(ty.clean(cx),
                                    Some(expr.span.to_src(cx)))
1286
            }
1287
            hir::ImplItemKind::Method(ref sig, _) => {
1288 1289
                MethodItem(sig.clean(cx))
            }
1290
            hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef {
1291 1292 1293 1294 1295 1296
                type_: ty.clean(cx),
                generics: Generics {
                    lifetimes: Vec::new(),
                    type_params: Vec::new(),
                    where_predicates: Vec::new()
                },
1297
            }, true),
1298 1299
        };
        Item {
V
Vadim Petrochenkov 已提交
1300
            name: Some(self.name.clean(cx)),
1301 1302
            source: self.span.clean(cx),
            attrs: self.attrs.clean(cx),
1303
            def_id: cx.map.local_def_id(self.id),
1304
            visibility: self.vis.clean(cx),
1305
            stability: get_stability(cx, cx.map.local_def_id(self.id)),
1306
            deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
1307
            inner: inner
C
Corey Richardson 已提交
1308 1309 1310 1311
        }
    }
}

1312
impl<'tcx> Clean<Item> for ty::Method<'tcx> {
1313
    fn clean(&self, cx: &DocContext) -> Item {
1314
        let (self_, sig) = match self.explicit_self {
1315 1316
            ty::ExplicitSelfCategory::Static => (hir::SelfStatic.clean(cx),
                                                 self.fty.sig.clone()),
1317
            s => {
1318
                let sig = ty::Binder(ty::FnSig {
J
Jorge Aparicio 已提交
1319
                    inputs: self.fty.sig.0.inputs[1..].to_vec(),
1320 1321
                    ..self.fty.sig.0.clone()
                });
1322
                let s = match s {
1323 1324
                    ty::ExplicitSelfCategory::ByValue => SelfValue,
                    ty::ExplicitSelfCategory::ByReference(..) => {
1325
                        match self.fty.sig.0.inputs[0].sty {
1326
                            ty::TyRef(r, mt) => {
1327
                                SelfBorrowed(r.clean(cx), mt.mutbl.clean(cx))
1328
                            }
A
Alex Crichton 已提交
1329
                            _ => unreachable!(),
1330 1331
                        }
                    }
1332
                    ty::ExplicitSelfCategory::ByBox => {
1333
                        SelfExplicit(self.fty.sig.0.inputs[0].clean(cx))
1334
                    }
1335
                    ty::ExplicitSelfCategory::Static => unreachable!(),
1336 1337 1338 1339
                };
                (s, sig)
            }
        };
1340

1341 1342 1343 1344 1345 1346
        let generics = (&self.generics, &self.predicates,
                        subst::FnSpace).clean(cx);
        let decl = (self.def_id, &sig).clean(cx);
        let provided = match self.container {
            ty::ImplContainer(..) => false,
            ty::TraitContainer(did) => {
1347
                cx.tcx().provided_trait_methods(did).iter().any(|m| {
1348 1349 1350 1351 1352 1353 1354 1355 1356 1357
                    m.def_id == self.def_id
                })
            }
        };
        let inner = if provided {
            MethodItem(Method {
                unsafety: self.fty.unsafety,
                generics: generics,
                self_: self_,
                decl: decl,
N
Niko Matsakis 已提交
1358 1359 1360
                abi: self.fty.abi,

                // trait methods canot (currently, at least) be const
1361
                constness: hir::Constness::NotConst,
1362 1363 1364 1365 1366 1367 1368
            })
        } else {
            TyMethodItem(TyMethod {
                unsafety: self.fty.unsafety,
                generics: generics,
                self_: self_,
                decl: decl,
N
Niko Matsakis 已提交
1369
                abi: self.fty.abi,
1370 1371 1372
            })
        };

1373
        Item {
1374
            name: Some(self.name.clean(cx)),
1375
            visibility: Some(hir::Inherited),
1376
            stability: get_stability(cx, self.def_id),
1377
            deprecation: get_deprecation(cx, self.def_id),
1378
            def_id: self.def_id,
1379
            attrs: inline::load_attrs(cx, cx.tcx(), self.def_id),
1380
            source: Span::empty(),
1381
            inner: inner,
1382
        }
1383 1384 1385
    }
}

1386
impl<'tcx> Clean<Item> for ty::ImplOrTraitItem<'tcx> {
1387
    fn clean(&self, cx: &DocContext) -> Item {
1388
        match *self {
1389
            ty::ConstTraitItem(ref cti) => cti.clean(cx),
1390
            ty::MethodTraitItem(ref mti) => mti.clean(cx),
1391
            ty::TypeTraitItem(ref tti) => tti.clean(cx),
1392 1393 1394 1395
        }
    }
}

1396
/// A trait reference, which may have higher ranked lifetimes.
J
Jorge Aparicio 已提交
1397
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1398 1399 1400 1401 1402
pub struct PolyTrait {
    pub trait_: Type,
    pub lifetimes: Vec<Lifetime>
}

C
Corey Richardson 已提交
1403 1404 1405
/// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
/// type out of the AST/ty::ctxt given one of these, if more information is needed. Most importantly
/// it does not preserve mutability or boxes.
J
Jorge Aparicio 已提交
1406
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
1407
pub enum Type {
1408
    /// structs/enums/traits (most that'd be an hir::TyPath)
1409
    ResolvedPath {
S
Steven Fackler 已提交
1410 1411
        path: Path,
        typarams: Option<Vec<TyParamBound>>,
N
Niko Matsakis 已提交
1412
        did: DefId,
1413 1414
        /// true if is a `T::Name` path for associated types
        is_generic: bool,
1415
    },
1416 1417 1418
    /// For parameterized types, so the consumer of the JSON don't go
    /// looking for types which don't exist anywhere.
    Generic(String),
1419
    /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
1420
    /// arrays, slices, and tuples.
1421
    Primitive(PrimitiveType),
C
Corey Richardson 已提交
1422
    /// extern "ABI" fn
1423
    BareFunction(Box<BareFunctionDecl>),
1424
    Tuple(Vec<Type>),
1425
    Vector(Box<Type>),
1426
    FixedVector(Box<Type>, String),
1427
    /// aka TyBot
C
Corey Richardson 已提交
1428
    Bottom,
1429 1430
    Unique(Box<Type>),
    RawPointer(Mutability, Box<Type>),
1431
    BorrowedRef {
S
Steven Fackler 已提交
1432 1433 1434
        lifetime: Option<Lifetime>,
        mutability: Mutability,
        type_: Box<Type>,
1435
    },
1436 1437

    // <Type as Trait>::Name
T
Tom Jakubowski 已提交
1438 1439 1440 1441 1442
    QPath {
        name: String,
        self_type: Box<Type>,
        trait_: Box<Type>
    },
1443 1444 1445 1446 1447 1448

    // _
    Infer,

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

J
Jorge Aparicio 已提交
1451
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
1452
pub enum PrimitiveType {
1453 1454
    Isize, I8, I16, I32, I64,
    Usize, U8, U16, U32, U64,
1455
    F32, F64,
1456 1457 1458 1459
    Char,
    Bool,
    Str,
    Slice,
1460
    Array,
1461
    PrimitiveTuple,
1462
    PrimitiveRawPointer,
1463 1464
}

J
Jorge Aparicio 已提交
1465
#[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
1466 1467 1468
pub enum TypeKind {
    TypeEnum,
    TypeFunction,
1469
    TypeModule,
1470
    TypeConst,
1471 1472 1473 1474
    TypeStatic,
    TypeStruct,
    TypeTrait,
    TypeVariant,
1475
    TypeTypedef,
1476 1477
}

1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492
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,
        }
    }
}

1493 1494
impl PrimitiveType {
    fn from_str(s: &str) -> Option<PrimitiveType> {
1495
        match s {
1496
            "isize" => Some(Isize),
1497 1498 1499 1500
            "i8" => Some(I8),
            "i16" => Some(I16),
            "i32" => Some(I32),
            "i64" => Some(I64),
1501
            "usize" => Some(Usize),
1502 1503 1504 1505 1506 1507 1508 1509 1510
            "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),
1511
            "array" => Some(Array),
1512 1513
            "slice" => Some(Slice),
            "tuple" => Some(PrimitiveTuple),
1514
            "pointer" => Some(PrimitiveRawPointer),
1515 1516 1517 1518
            _ => None,
        }
    }

1519
    fn find(attrs: &[Attribute]) -> Option<PrimitiveType> {
1520
        for attr in attrs {
1521
            let list = match *attr {
1522
                List(ref k, ref l) if *k == "doc" => l,
1523 1524
                _ => continue,
            };
1525
            for sub_attr in list {
1526 1527
                let value = match *sub_attr {
                    NameValue(ref k, ref v)
1528
                        if *k == "primitive" => v,
1529 1530
                    _ => continue,
                };
1531
                match PrimitiveType::from_str(value) {
1532 1533 1534 1535 1536 1537 1538 1539
                    Some(p) => return Some(p),
                    None => {}
                }
            }
        }
        return None
    }

1540
    pub fn to_string(&self) -> &'static str {
1541
        match *self {
1542
            Isize => "isize",
1543 1544 1545 1546
            I8 => "i8",
            I16 => "i16",
            I32 => "i32",
            I64 => "i64",
1547
            Usize => "usize",
1548 1549 1550 1551 1552 1553 1554 1555 1556
            U8 => "u8",
            U16 => "u16",
            U32 => "u32",
            U64 => "u64",
            F32 => "f32",
            F64 => "f64",
            Str => "str",
            Bool => "bool",
            Char => "char",
1557
            Array => "array",
1558 1559
            Slice => "slice",
            PrimitiveTuple => "tuple",
1560
            PrimitiveRawPointer => "pointer",
1561 1562 1563 1564
        }
    }

    pub fn to_url_str(&self) -> &'static str {
1565
        self.to_string()
1566 1567 1568 1569 1570
    }

    /// Creates a rustdoc-specific node id for primitive types.
    ///
    /// These node ids are generally never used by the AST itself.
1571 1572 1573
    pub fn to_def_index(&self) -> DefIndex {
        let x = u32::MAX - 1 - (*self as u32);
        DefIndex::new(x as usize)
1574 1575 1576
    }
}

1577
impl Clean<Type> for hir::Ty {
1578
    fn clean(&self, cx: &DocContext) -> Type {
1579
        use rustc_front::hir::*;
1580
        match self.node {
1581
            TyPtr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
1582
            TyRptr(ref l, ref m) =>
1583 1584
                BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx),
                             type_: box m.ty.clean(cx)},
1585 1586 1587
            TyVec(ref ty) => Vector(box ty.clean(cx)),
            TyFixedLengthVec(ref ty, ref e) => FixedVector(box ty.clean(cx),
                                                           e.span.to_src(cx)),
1588
            TyTup(ref tys) => Tuple(tys.clean(cx)),
1589
            TyPath(None, ref p) => {
1590
                resolve_type(cx, p.clean(cx), self.id)
N
Niko Matsakis 已提交
1591
            }
1592
            TyPath(Some(ref qself), ref p) => {
1593 1594 1595 1596 1597 1598 1599
                let mut segments: Vec<_> = p.segments.clone().into();
                segments.pop();
                let trait_path = hir::Path {
                    span: p.span,
                    global: p.global,
                    segments: segments.into(),
                };
1600
                Type::QPath {
1601
                    name: p.segments.last().unwrap().identifier.name.clean(cx),
1602
                    self_type: box qself.ty.clean(cx),
1603
                    trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
1604 1605
                }
            }
N
Niko Matsakis 已提交
1606 1607 1608
            TyObjectSum(ref lhs, ref bounds) => {
                let lhs_ty = lhs.clean(cx);
                match lhs_ty {
1609 1610 1611 1612 1613 1614 1615
                    ResolvedPath { path, typarams: None, did, is_generic } => {
                        ResolvedPath {
                            path: path,
                            typarams: Some(bounds.clean(cx)),
                            did: did,
                            is_generic: is_generic,
                        }
N
Niko Matsakis 已提交
1616 1617 1618 1619 1620
                    }
                    _ => {
                        lhs_ty // shouldn't happen
                    }
                }
1621
            }
1622
            TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
1623 1624 1625
            TyPolyTraitRef(ref bounds) => {
                PolyTraitRef(bounds.clean(cx))
            },
V
Vadim Petrochenkov 已提交
1626
            TyInfer => {
1627 1628 1629
                Infer
            },
            TyTypeof(..) => {
1630
                panic!("Unimplemented type {:?}", self.node)
1631
            },
1632
        }
C
Corey Richardson 已提交
1633 1634 1635
    }
}

1636
impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
1637
    fn clean(&self, cx: &DocContext) -> Type {
1638
        match self.sty {
1639 1640
            ty::TyBool => Primitive(Bool),
            ty::TyChar => Primitive(Char),
1641 1642 1643 1644 1645 1646 1647 1648 1649 1650
            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),
1651 1652
            ty::TyFloat(ast::FloatTy::F32) => Primitive(F32),
            ty::TyFloat(ast::FloatTy::F64) => Primitive(F64),
1653 1654
            ty::TyStr => Primitive(Str),
            ty::TyBox(t) => {
1655
                let box_did = cx.tcx_opt().and_then(|tcx| {
A
Alex Crichton 已提交
1656 1657
                    tcx.lang_items.owned_box()
                });
1658
                lang_struct(cx, box_did, t, "Box", Unique)
A
Alex Crichton 已提交
1659
            }
1660 1661 1662
            ty::TySlice(ty) => Vector(box ty.clean(cx)),
            ty::TyArray(ty, i) => FixedVector(box ty.clean(cx),
                                              format!("{}", i)),
1663 1664
            ty::TyRawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
            ty::TyRef(r, mt) => BorrowedRef {
1665 1666 1667
                lifetime: r.clean(cx),
                mutability: mt.mutbl.clean(cx),
                type_: box mt.ty.clean(cx),
1668
            },
1669
            ty::TyBareFn(_, ref fty) => BareFunction(box BareFunctionDecl {
N
Niko Matsakis 已提交
1670
                unsafety: fty.unsafety,
1671
                generics: Generics {
1672 1673 1674
                    lifetimes: Vec::new(),
                    type_params: Vec::new(),
                    where_predicates: Vec::new()
1675
                },
1676
                decl: (cx.map.local_def_id(0), &fty.sig).clean(cx),
1677
                abi: fty.abi.to_string(),
1678
            }),
1679 1680 1681
            ty::TyStruct(def, substs) |
            ty::TyEnum(def, substs) => {
                let did = def.did;
1682
                let kind = match self.sty {
1683
                    ty::TyStruct(..) => TypeStruct,
1684 1685
                    _ => TypeEnum,
                };
M
mitaa 已提交
1686 1687
                inline::record_extern_fqn(cx, did, kind);
                let path = external_path(cx, &cx.tcx().item_name(did).as_str(),
1688
                                         None, vec![], substs);
1689
                ResolvedPath {
1690
                    path: path,
1691 1692
                    typarams: None,
                    did: did,
1693
                    is_generic: false,
1694 1695
                }
            }
1696
            ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => {
1697
                let did = principal.def_id();
M
mitaa 已提交
1698
                inline::record_extern_fqn(cx, did, TypeTrait);
1699
                let (typarams, bindings) = bounds.clean(cx);
M
mitaa 已提交
1700
                let path = external_path(cx, &cx.tcx().item_name(did).as_str(),
1701
                                         Some(did), bindings, principal.substs());
1702 1703
                ResolvedPath {
                    path: path,
1704
                    typarams: Some(typarams),
1705
                    did: did,
1706
                    is_generic: false,
1707 1708
                }
            }
1709
            ty::TyTuple(ref t) => Tuple(t.clean(cx)),
1710

1711
            ty::TyProjection(ref data) => data.clean(cx),
1712

1713
            ty::TyParam(ref p) => Generic(p.name.to_string()),
1714

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

1717 1718
            ty::TyInfer(..) => panic!("TyInfer"),
            ty::TyError => panic!("TyError"),
1719 1720 1721 1722
        }
    }
}

J
Jorge Aparicio 已提交
1723
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1724
pub enum StructField {
1725
    HiddenStructField, // inserted later by strip passes
1726
    TypedStructField(Type),
C
Corey Richardson 已提交
1727 1728
}

1729
impl Clean<Item> for hir::StructField {
1730
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1731
        let (name, vis) = match self.node.kind {
1732 1733
            hir::NamedField(id, vis) => (Some(id), vis),
            hir::UnnamedField(vis) => (None, vis)
C
Corey Richardson 已提交
1734 1735
        };
        Item {
1736 1737 1738
            name: name.clean(cx),
            attrs: self.node.attrs.clean(cx),
            source: self.span.clean(cx),
1739
            visibility: Some(vis),
1740
            stability: get_stability(cx, cx.map.local_def_id(self.node.id)),
1741
            deprecation: get_deprecation(cx, cx.map.local_def_id(self.node.id)),
1742
            def_id: cx.map.local_def_id(self.node.id),
1743
            inner: StructFieldItem(TypedStructField(self.node.ty.clean(cx))),
C
Corey Richardson 已提交
1744 1745 1746 1747
        }
    }
}

A
Ariel Ben-Yehuda 已提交
1748
impl<'tcx> Clean<Item> for ty::FieldDefData<'tcx, 'static> {
1749
    fn clean(&self, cx: &DocContext) -> Item {
1750
        use syntax::parse::token::special_idents::unnamed_field;
A
Ariel Ben-Yehuda 已提交
1751 1752 1753
        // FIXME: possible O(n^2)-ness! Not my fault.
        let attr_map =
            cx.tcx().sess.cstore.crate_struct_field_attrs(self.did.krate);
1754

1755 1756
        let (name, attrs) = if self.name == unnamed_field.name {
            (None, None)
1757
        } else {
1758
            (Some(self.name), Some(attr_map.get(&self.did).unwrap()))
1759
        };
1760

1761
        Item {
1762 1763
            name: name.clean(cx),
            attrs: attrs.unwrap_or(&Vec::new()).clean(cx),
1764 1765
            source: Span::empty(),
            visibility: Some(self.vis),
1766
            stability: get_stability(cx, self.did),
1767
            deprecation: get_deprecation(cx, self.did),
1768 1769
            def_id: self.did,
            inner: StructFieldItem(TypedStructField(self.unsubst_ty().clean(cx))),
1770 1771 1772 1773
        }
    }
}

1774
pub type Visibility = hir::Visibility;
C
Corey Richardson 已提交
1775

1776
impl Clean<Option<Visibility>> for hir::Visibility {
1777
    fn clean(&self, _: &DocContext) -> Option<Visibility> {
C
Corey Richardson 已提交
1778 1779 1780 1781
        Some(*self)
    }
}

J
Jorge Aparicio 已提交
1782
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1783
pub struct Struct {
1784 1785 1786 1787
    pub struct_type: doctree::StructType,
    pub generics: Generics,
    pub fields: Vec<Item>,
    pub fields_stripped: bool,
C
Corey Richardson 已提交
1788 1789 1790
}

impl Clean<Item> for doctree::Struct {
1791
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1792
        Item {
1793 1794 1795
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
1796
            def_id: cx.map.local_def_id(self.id),
1797 1798
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
1799
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
1800 1801
            inner: StructItem(Struct {
                struct_type: self.struct_type,
1802 1803
                generics: self.generics.clean(cx),
                fields: self.fields.clean(cx),
S
Steven Fackler 已提交
1804
                fields_stripped: false,
C
Corey Richardson 已提交
1805 1806 1807 1808 1809
            }),
        }
    }
}

1810
/// This is a more limited form of the standard Struct, different in that
C
Corey Richardson 已提交
1811 1812
/// it lacks the things most items have (name, id, parameterization). Found
/// only as a variant in an enum.
J
Jorge Aparicio 已提交
1813
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1814
pub struct VariantStruct {
1815 1816 1817
    pub struct_type: doctree::StructType,
    pub fields: Vec<Item>,
    pub fields_stripped: bool,
C
Corey Richardson 已提交
1818 1819
}

1820
impl Clean<VariantStruct> for ::rustc_front::hir::VariantData {
1821
    fn clean(&self, cx: &DocContext) -> VariantStruct {
C
Corey Richardson 已提交
1822 1823
        VariantStruct {
            struct_type: doctree::struct_type_from_def(self),
1824
            fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
S
Steven Fackler 已提交
1825
            fields_stripped: false,
C
Corey Richardson 已提交
1826 1827 1828 1829
        }
    }
}

J
Jorge Aparicio 已提交
1830
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1831
pub struct Enum {
1832 1833 1834
    pub variants: Vec<Item>,
    pub generics: Generics,
    pub variants_stripped: bool,
C
Corey Richardson 已提交
1835 1836 1837
}

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

J
Jorge Aparicio 已提交
1856
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1857
pub struct Variant {
1858
    pub kind: VariantKind,
C
Corey Richardson 已提交
1859 1860 1861
}

impl Clean<Item> for doctree::Variant {
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
            visibility: None,
1868
            stability: self.stab.clean(cx),
1869
            deprecation: self.depr.clean(cx),
1870
            def_id: cx.map.local_def_id(self.def.id()),
C
Corey Richardson 已提交
1871
            inner: VariantItem(Variant {
1872
                kind: struct_def_to_variant_kind(&self.def, cx),
C
Corey Richardson 已提交
1873 1874 1875 1876 1877
            }),
        }
    }
}

A
Ariel Ben-Yehuda 已提交
1878
impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
1879
    fn clean(&self, cx: &DocContext) -> Item {
1880
        // use syntax::parse::token::special_idents::unnamed_field;
1881 1882 1883 1884 1885 1886
        let kind = match self.kind() {
            ty::VariantKind::Unit => CLikeVariant,
            ty::VariantKind::Tuple => {
                TupleVariant(
                    self.fields.iter().map(|f| f.unsubst_ty().clean(cx)).collect()
                )
1887
            }
1888
            ty::VariantKind::Struct => {
1889 1890 1891
                StructVariant(VariantStruct {
                    struct_type: doctree::Plain,
                    fields_stripped: false,
1892
                    fields: self.fields.iter().map(|field| {
1893 1894
                        Item {
                            source: Span::empty(),
1895
                            name: Some(field.name.clean(cx)),
1896
                            attrs: Vec::new(),
1897
                            visibility: Some(hir::Public),
1898 1899
                            // FIXME: this is not accurate, we need an id for
                            //        the specific field but we're using the id
A
Aaron Turon 已提交
1900 1901 1902 1903 1904
                            //        for the whole variant. Thus we read the
                            //        stability from the whole variant as well.
                            //        Struct variants are experimental and need
                            //        more infrastructure work before we can get
                            //        at the needed information here.
1905 1906
                            def_id: self.did,
                            stability: get_stability(cx, self.did),
1907
                            deprecation: get_deprecation(cx, self.did),
1908
                            inner: StructFieldItem(
1909
                                TypedStructField(field.unsubst_ty().clean(cx))
1910 1911 1912 1913 1914 1915 1916
                            )
                        }
                    }).collect()
                })
            }
        };
        Item {
1917
            name: Some(self.name.clean(cx)),
1918
            attrs: inline::load_attrs(cx, cx.tcx(), self.did),
1919
            source: Span::empty(),
1920
            visibility: Some(hir::Public),
1921
            def_id: self.did,
1922
            inner: VariantItem(Variant { kind: kind }),
1923
            stability: get_stability(cx, self.did),
1924
            deprecation: get_deprecation(cx, self.did),
1925 1926 1927 1928
        }
    }
}

J
Jorge Aparicio 已提交
1929
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1930 1931
pub enum VariantKind {
    CLikeVariant,
1932
    TupleVariant(Vec<Type>),
C
Corey Richardson 已提交
1933 1934 1935
    StructVariant(VariantStruct),
}

1936
fn struct_def_to_variant_kind(struct_def: &hir::VariantData, cx: &DocContext) -> VariantKind {
1937
    if struct_def.is_struct() {
1938
        StructVariant(struct_def.clean(cx))
1939
    } else if struct_def.is_unit() {
1940 1941
        CLikeVariant
    } else {
1942
        TupleVariant(struct_def.fields().iter().map(|x| x.node.ty.clean(cx)).collect())
1943 1944 1945
    }
}

J
Jorge Aparicio 已提交
1946
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1947
pub struct Span {
1948
    pub filename: String,
1949 1950 1951 1952
    pub loline: usize,
    pub locol: usize,
    pub hiline: usize,
    pub hicol: usize,
1953 1954
}

1955 1956 1957
impl Span {
    fn empty() -> Span {
        Span {
1958
            filename: "".to_string(),
1959 1960 1961 1962 1963 1964
            loline: 0, locol: 0,
            hiline: 0, hicol: 0,
        }
    }
}

1965
impl Clean<Span> for syntax::codemap::Span {
1966
    fn clean(&self, cx: &DocContext) -> Span {
1967 1968 1969 1970
        if *self == DUMMY_SP {
            return Span::empty();
        }

1971
        let cm = cx.sess().codemap();
1972 1973 1974 1975
        let filename = cm.span_to_filename(*self);
        let lo = cm.lookup_char_pos(self.lo);
        let hi = cm.lookup_char_pos(self.hi);
        Span {
1976
            filename: filename.to_string(),
1977
            loline: lo.line,
1978
            locol: lo.col.to_usize(),
1979
            hiline: hi.line,
1980
            hicol: hi.col.to_usize(),
1981
        }
C
Corey Richardson 已提交
1982 1983 1984
    }
}

J
Jorge Aparicio 已提交
1985
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
1986
pub struct Path {
1987 1988
    pub global: bool,
    pub segments: Vec<PathSegment>,
C
Corey Richardson 已提交
1989 1990
}

1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006
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()
                }
            }]
        }
    }
}

2007
impl Clean<Path> for hir::Path {
2008
    fn clean(&self, cx: &DocContext) -> Path {
C
Corey Richardson 已提交
2009
        Path {
2010
            global: self.global,
2011
            segments: self.segments.clean(cx),
2012 2013 2014 2015
        }
    }
}

J
Jorge Aparicio 已提交
2016
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2017 2018 2019 2020
pub enum PathParameters {
    AngleBracketed {
        lifetimes: Vec<Lifetime>,
        types: Vec<Type>,
2021
        bindings: Vec<TypeBinding>
2022 2023 2024 2025 2026
    },
    Parenthesized {
        inputs: Vec<Type>,
        output: Option<Type>
    }
2027 2028
}

2029
impl Clean<PathParameters> for hir::PathParameters {
2030 2031
    fn clean(&self, cx: &DocContext) -> PathParameters {
        match *self {
2032
            hir::AngleBracketedParameters(ref data) => {
2033 2034
                PathParameters::AngleBracketed {
                    lifetimes: data.lifetimes.clean(cx),
2035 2036
                    types: data.types.clean(cx),
                    bindings: data.bindings.clean(cx)
2037
                }
2038 2039
            }

2040
            hir::ParenthesizedParameters(ref data) => {
2041 2042 2043 2044
                PathParameters::Parenthesized {
                    inputs: data.inputs.clean(cx),
                    output: data.output.clean(cx)
                }
2045
            }
2046 2047 2048
        }
    }
}
2049

J
Jorge Aparicio 已提交
2050
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2051 2052 2053 2054 2055
pub struct PathSegment {
    pub name: String,
    pub params: PathParameters
}

2056
impl Clean<PathSegment> for hir::PathSegment {
2057
    fn clean(&self, cx: &DocContext) -> PathSegment {
2058
        PathSegment {
2059
            name: self.identifier.name.clean(cx),
2060
            params: self.parameters.clean(cx)
C
Corey Richardson 已提交
2061 2062 2063 2064
        }
    }
}

2065
fn path_to_string(p: &hir::Path) -> String {
2066
    let mut s = String::new();
C
Corey Richardson 已提交
2067
    let mut first = true;
2068
    for i in p.segments.iter().map(|x| x.identifier.name.as_str()) {
C
Corey Richardson 已提交
2069 2070 2071 2072 2073
        if !first || p.global {
            s.push_str("::");
        } else {
            first = false;
        }
G
GuillaumeGomez 已提交
2074
        s.push_str(&i);
C
Corey Richardson 已提交
2075
    }
2076
    s
C
Corey Richardson 已提交
2077 2078
}

2079
impl Clean<String> for ast::Name {
2080
    fn clean(&self, _: &DocContext) -> String {
2081
        self.to_string()
2082 2083 2084
    }
}

J
Jorge Aparicio 已提交
2085
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
2086
pub struct Typedef {
2087 2088
    pub type_: Type,
    pub generics: Generics,
C
Corey Richardson 已提交
2089 2090 2091
}

impl Clean<Item> for doctree::Typedef {
2092
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
2093
        Item {
2094 2095 2096
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2097
            def_id: cx.map.local_def_id(self.id.clone()),
2098 2099
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
2100
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
2101
            inner: TypedefItem(Typedef {
2102 2103
                type_: self.ty.clean(cx),
                generics: self.gen.clean(cx),
2104
            }, false),
C
Corey Richardson 已提交
2105 2106 2107 2108
        }
    }
}

J
Jorge Aparicio 已提交
2109
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
2110
pub struct BareFunctionDecl {
2111
    pub unsafety: hir::Unsafety,
2112 2113
    pub generics: Generics,
    pub decl: FnDecl,
2114
    pub abi: String,
C
Corey Richardson 已提交
2115 2116
}

2117
impl Clean<BareFunctionDecl> for hir::BareFnTy {
2118
    fn clean(&self, cx: &DocContext) -> BareFunctionDecl {
C
Corey Richardson 已提交
2119
        BareFunctionDecl {
N
Niko Matsakis 已提交
2120
            unsafety: self.unsafety,
C
Corey Richardson 已提交
2121
            generics: Generics {
2122
                lifetimes: self.lifetimes.clean(cx),
2123
                type_params: Vec::new(),
2124
                where_predicates: Vec::new()
C
Corey Richardson 已提交
2125
            },
2126
            decl: self.decl.clean(cx),
2127
            abi: self.abi.to_string(),
C
Corey Richardson 已提交
2128 2129 2130 2131
        }
    }
}

J
Jorge Aparicio 已提交
2132
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
2133
pub struct Static {
2134 2135
    pub type_: Type,
    pub mutability: Mutability,
C
Corey Richardson 已提交
2136 2137 2138
    /// 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.
2139
    pub expr: String,
C
Corey Richardson 已提交
2140 2141 2142
}

impl Clean<Item> for doctree::Static {
2143
    fn clean(&self, cx: &DocContext) -> Item {
2144
        debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
C
Corey Richardson 已提交
2145
        Item {
2146 2147 2148
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2149
            def_id: cx.map.local_def_id(self.id),
2150 2151
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
2152
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
2153
            inner: StaticItem(Static {
2154 2155 2156
                type_: self.type_.clean(cx),
                mutability: self.mutability.clean(cx),
                expr: self.expr.span.to_src(cx),
C
Corey Richardson 已提交
2157 2158 2159 2160 2161
            }),
        }
    }
}

J
Jorge Aparicio 已提交
2162
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173
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),
2174
            def_id: cx.map.local_def_id(self.id),
2175 2176
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
2177
            deprecation: self.depr.clean(cx),
2178 2179 2180 2181 2182 2183 2184 2185
            inner: ConstantItem(Constant {
                type_: self.type_.clean(cx),
                expr: self.expr.span.to_src(cx),
            }),
        }
    }
}

J
Jorge Aparicio 已提交
2186
#[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Copy)]
C
Corey Richardson 已提交
2187 2188 2189 2190 2191
pub enum Mutability {
    Mutable,
    Immutable,
}

2192
impl Clean<Mutability> for hir::Mutability {
2193
    fn clean(&self, _: &DocContext) -> Mutability {
C
Corey Richardson 已提交
2194
        match self {
2195 2196
            &hir::MutMutable => Mutable,
            &hir::MutImmutable => Immutable,
C
Corey Richardson 已提交
2197 2198 2199 2200
        }
    }
}

J
Jorge Aparicio 已提交
2201
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Copy, Debug)]
2202 2203 2204 2205 2206
pub enum ImplPolarity {
    Positive,
    Negative,
}

2207
impl Clean<ImplPolarity> for hir::ImplPolarity {
2208 2209
    fn clean(&self, _: &DocContext) -> ImplPolarity {
        match self {
2210 2211
            &hir::ImplPolarity::Positive => ImplPolarity::Positive,
            &hir::ImplPolarity::Negative => ImplPolarity::Negative,
2212 2213 2214 2215
        }
    }
}

J
Jorge Aparicio 已提交
2216
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
2217
pub struct Impl {
2218
    pub unsafety: hir::Unsafety,
2219 2220 2221
    pub generics: Generics,
    pub trait_: Option<Type>,
    pub for_: Type,
2222
    pub items: Vec<Item>,
2223
    pub derived: bool,
2224
    pub polarity: Option<ImplPolarity>,
C
Corey Richardson 已提交
2225 2226
}

2227
fn detect_derived<M: AttrMetaMethods>(attrs: &[M]) -> bool {
2228
    attr::contains_name(attrs, "automatically_derived")
2229 2230
}

2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245
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.
        if let Some(ResolvedPath { did, .. }) = trait_ {
            if Some(did) == cx.deref_trait_did.get() {
                build_deref_target_impls(cx, &items, &mut ret);
            }
        }

        ret.push(Item {
C
Corey Richardson 已提交
2246
            name: None,
2247 2248
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2249
            def_id: cx.map.local_def_id(self.id),
2250 2251
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
2252
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
2253
            inner: ImplItem(Impl {
2254
                unsafety: self.unsafety,
2255
                generics: self.generics.clean(cx),
2256
                trait_: trait_,
2257
                for_: self.for_.clean(cx),
2258
                items: items,
2259
                derived: detect_derived(&self.attrs),
2260
                polarity: Some(self.polarity.clean(cx)),
C
Corey Richardson 已提交
2261
            }),
2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276
        });
        return ret;
    }
}

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 {
2277
            TypedefItem(ref t, true) => &t.type_,
2278 2279 2280
            _ => continue,
        };
        let primitive = match *target {
N
Niko Matsakis 已提交
2281
            ResolvedPath { did, .. } if did.is_local() => continue,
2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312
            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 已提交
2313
            if !did.is_local() {
2314 2315
                inline::build_impl(cx, tcx, did, ret);
            }
C
Corey Richardson 已提交
2316 2317 2318 2319
        }
    }
}

2320 2321
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct DefaultImpl {
2322
    pub unsafety: hir::Unsafety,
2323 2324 2325 2326 2327 2328 2329 2330 2331
    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),
2332
            def_id: cx.map.local_def_id(self.id),
2333
            visibility: Some(hir::Public),
2334
            stability: None,
2335
            deprecation: None,
2336 2337 2338 2339 2340 2341 2342 2343
            inner: DefaultImplItem(DefaultImpl {
                unsafety: self.unsafety,
                trait_: self.trait_.clean(cx),
            }),
        }
    }
}

2344 2345 2346 2347 2348 2349
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),
2350
            def_id: cx.map.local_def_id(0),
2351 2352
            visibility: self.vis.clean(cx),
            stability: None,
2353
            deprecation: None,
2354 2355 2356
            inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
        }
    }
C
Corey Richardson 已提交
2357 2358
}

2359
impl Clean<Vec<Item>> for doctree::Import {
2360
    fn clean(&self, cx: &DocContext) -> Vec<Item> {
J
Joseph Crail 已提交
2361
        // We consider inlining the documentation of `pub use` statements, but we
2362 2363
        // forcefully don't inline if this is not public or if the
        // #[doc(no_inline)] attribute is present.
2364
        let denied = self.vis != hir::Public || self.attrs.iter().any(|a| {
2365
            &a.name()[..] == "doc" && match a.meta_item_list() {
2366
                Some(l) => attr::contains_name(l, "no_inline"),
2367 2368 2369
                None => false,
            }
        });
2370
        let (mut ret, inner) = match self.node {
2371
            hir::ViewPathGlob(ref p) => {
2372
                (vec![], GlobImport(resolve_use_source(cx, p.clean(cx), self.id)))
2373
            }
2374
            hir::ViewPathList(ref p, ref list) => {
2375 2376 2377 2378 2379 2380
                // 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![];
2381
                    for path in list {
2382
                        match inline::try_inline(cx, path.node.id(), path.node.rename()) {
2383
                            Some(items) => {
2384
                                ret.extend(items);
2385 2386 2387
                            }
                            None => {
                                remaining.push(path.clean(cx));
2388 2389 2390
                            }
                        }
                    }
2391 2392 2393
                    remaining
                } else {
                    list.clean(cx)
P
Patrick Walton 已提交
2394
                };
2395 2396 2397 2398 2399
                if remaining.is_empty() {
                    return ret;
                }
                (ret, ImportList(resolve_use_source(cx, p.clean(cx), self.id),
                                 remaining))
P
Patrick Walton 已提交
2400
            }
2401
            hir::ViewPathSimple(name, ref p) => {
2402
                if !denied {
2403
                    match inline::try_inline(cx, self.id, Some(name)) {
2404 2405 2406 2407
                        Some(items) => return items,
                        None => {}
                    }
                }
2408
                (vec![], SimpleImport(name.clean(cx),
2409
                                      resolve_use_source(cx, p.clean(cx), self.id)))
2410
            }
2411 2412 2413 2414 2415
        };
        ret.push(Item {
            name: None,
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2416
            def_id: cx.map.local_def_id(0),
2417 2418
            visibility: self.vis.clean(cx),
            stability: None,
2419
            deprecation: None,
2420 2421 2422
            inner: ImportItem(inner)
        });
        ret
C
Corey Richardson 已提交
2423 2424 2425
    }
}

J
Jorge Aparicio 已提交
2426
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2427
pub enum Import {
2428
    // use source as str;
2429
    SimpleImport(String, ImportSource),
A
Alex Crichton 已提交
2430 2431 2432
    // use source::*;
    GlobImport(ImportSource),
    // use source::{a, b, c};
2433
    ImportList(ImportSource, Vec<ViewListIdent>),
A
Alex Crichton 已提交
2434 2435
}

J
Jorge Aparicio 已提交
2436
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
A
Alex Crichton 已提交
2437
pub struct ImportSource {
2438
    pub path: Path,
N
Niko Matsakis 已提交
2439
    pub did: Option<DefId>,
C
Corey Richardson 已提交
2440 2441
}

J
Jorge Aparicio 已提交
2442
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
A
Alex Crichton 已提交
2443
pub struct ViewListIdent {
2444
    pub name: String,
2445
    pub rename: Option<String>,
N
Niko Matsakis 已提交
2446
    pub source: Option<DefId>,
A
Alex Crichton 已提交
2447
}
C
Corey Richardson 已提交
2448

2449
impl Clean<ViewListIdent> for hir::PathListItem {
2450
    fn clean(&self, cx: &DocContext) -> ViewListIdent {
J
Jakub Wieczorek 已提交
2451
        match self.node {
2452
            hir::PathListIdent { id, name, rename } => ViewListIdent {
2453
                name: name.clean(cx),
2454
                rename: rename.map(|r| r.clean(cx)),
2455
                source: resolve_def(cx, id)
J
Jakub Wieczorek 已提交
2456
            },
2457
            hir::PathListMod { id, rename } => ViewListIdent {
2458
                name: "self".to_string(),
2459
                rename: rename.map(|r| r.clean(cx)),
2460
                source: resolve_def(cx, id)
J
Jakub Wieczorek 已提交
2461
            }
A
Alex Crichton 已提交
2462
        }
C
Corey Richardson 已提交
2463 2464 2465
    }
}

2466
impl Clean<Vec<Item>> for hir::ForeignMod {
2467
    fn clean(&self, cx: &DocContext) -> Vec<Item> {
2468 2469 2470 2471 2472 2473 2474 2475
        let mut items = self.items.clean(cx);
        for item in &mut items {
            match item.inner {
                ForeignFunctionItem(ref mut f) => f.abi = self.abi,
                _ => {}
            }
        }
        items
2476 2477 2478
    }
}

2479
impl Clean<Item> for hir::ForeignItem {
2480
    fn clean(&self, cx: &DocContext) -> Item {
2481
        let inner = match self.node {
2482
            hir::ForeignItemFn(ref decl, ref generics) => {
2483
                ForeignFunctionItem(Function {
2484 2485
                    decl: decl.clean(cx),
                    generics: generics.clean(cx),
2486
                    unsafety: hir::Unsafety::Unsafe,
2487
                    abi: Abi::Rust,
2488
                    constness: hir::Constness::NotConst,
2489 2490
                })
            }
2491
            hir::ForeignItemStatic(ref ty, mutbl) => {
2492
                ForeignStaticItem(Static {
2493
                    type_: ty.clean(cx),
2494
                    mutability: if mutbl {Mutable} else {Immutable},
2495
                    expr: "".to_string(),
2496 2497 2498 2499
                })
            }
        };
        Item {
V
Vadim Petrochenkov 已提交
2500
            name: Some(self.name.clean(cx)),
2501 2502
            attrs: self.attrs.clean(cx),
            source: self.span.clean(cx),
2503
            def_id: cx.map.local_def_id(self.id),
2504
            visibility: self.vis.clean(cx),
2505
            stability: get_stability(cx, cx.map.local_def_id(self.id)),
2506
            deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
2507 2508 2509 2510 2511
            inner: inner,
        }
    }
}

C
Corey Richardson 已提交
2512 2513 2514
// Utilities

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

2518
impl ToSource for syntax::codemap::Span {
2519
    fn to_src(&self, cx: &DocContext) -> String {
2520
        debug!("converting span {:?} to snippet", self.clean(cx));
2521
        let sn = match cx.sess().codemap().span_to_snippet(*self) {
2522 2523
            Ok(x) => x.to_string(),
            Err(_) => "".to_string()
C
Corey Richardson 已提交
2524
        };
2525
        debug!("got snippet {}", sn);
C
Corey Richardson 已提交
2526 2527 2528 2529
        sn
    }
}

2530
fn lit_to_string(lit: &ast::Lit) -> String {
C
Corey Richardson 已提交
2531
    match lit.node {
2532 2533 2534
        ast::LitKind::Str(ref st, _) => st.to_string(),
        ast::LitKind::ByteStr(ref data) => format!("{:?}", data),
        ast::LitKind::Byte(b) => {
2535
            let mut res = String::from("b'");
2536
            for c in (b as char).escape_default() {
2537
                res.push(c);
2538
            }
2539
            res.push('\'');
2540 2541
            res
        },
2542 2543 2544 2545 2546
        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 已提交
2547 2548 2549
    }
}

2550 2551
fn name_from_pat(p: &hir::Pat) -> String {
    use rustc_front::hir::*;
2552
    debug!("Trying to get a name from pattern: {:?}", p);
2553

C
Corey Richardson 已提交
2554
    match p.node {
V
Vadim Petrochenkov 已提交
2555
        PatWild => "_".to_string(),
2556
        PatIdent(_, ref p, _) => p.node.to_string(),
2557
        PatEnum(ref p, _) => path_to_string(p),
2558 2559
        PatQPath(..) => panic!("tried to get argument name from PatQPath, \
                                which is not allowed in function arguments"),
2560 2561
        PatStruct(ref name, ref fields, etc) => {
            format!("{} {{ {}{} }}", path_to_string(name),
2562
                fields.iter().map(|&Spanned { node: ref fp, .. }|
2563
                                  format!("{}: {}", fp.name, name_from_pat(&*fp.pat)))
2564
                             .collect::<Vec<String>>().join(", "),
2565 2566 2567 2568
                if etc { ", ..." } else { "" }
            )
        },
        PatTup(ref elts) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
2569
                                            .collect::<Vec<String>>().join(", ")),
2570
        PatBox(ref p) => name_from_pat(&**p),
2571
        PatRegion(ref p, _) => name_from_pat(&**p),
2572 2573 2574
        PatLit(..) => {
            warn!("tried to get argument name from PatLit, \
                  which is silly in function arguments");
2575
            "()".to_string()
2576
        },
S
Steve Klabnik 已提交
2577
        PatRange(..) => panic!("tried to get argument name from PatRange, \
2578
                              which is not allowed in function arguments"),
2579 2580 2581 2582
        PatVec(ref begin, ref mid, ref end) => {
            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));
2583
            format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
2584
        },
C
Corey Richardson 已提交
2585 2586 2587 2588
    }
}

/// Given a Type, resolve it using the def_map
N
Niko Matsakis 已提交
2589 2590
fn resolve_type(cx: &DocContext,
                path: Path,
2591
                id: ast::NodeId) -> Type {
2592
    debug!("resolve_type({:?},{:?})", path, id);
2593 2594
    let tcx = match cx.tcx_opt() {
        Some(tcx) => tcx,
2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606
        // 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
            };
        }
2607
    };
2608
    let def = match tcx.def_map.borrow().get(&id) {
2609
        Some(k) => k.full_def(),
S
Steve Klabnik 已提交
2610
        None => panic!("unresolved id not in defmap")
C
Corey Richardson 已提交
2611 2612
    };

2613 2614
    debug!("resolve_type: def={:?}", def);

2615
    let is_generic = match def {
2616
        Def::PrimTy(p) => match p {
2617 2618 2619
            hir::TyStr => return Primitive(Str),
            hir::TyBool => return Primitive(Bool),
            hir::TyChar => return Primitive(Char),
2620 2621 2622 2623 2624 2625 2626 2627 2628 2629
            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),
2630 2631
            hir::TyFloat(ast::FloatTy::F32) => return Primitive(F32),
            hir::TyFloat(ast::FloatTy::F64) => return Primitive(F64),
C
Corey Richardson 已提交
2632
        },
2633
        Def::SelfTy(..) if path.segments.len() == 1 => {
2634
            return Generic(special_idents::type_self.name.to_string());
2635
        }
2636
        Def::SelfTy(..) | Def::TyParam(..) => true,
2637
        _ => false,
2638
    };
2639
    let did = register_def(&*cx, def);
2640
    ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
2641 2642
}

2643
fn register_def(cx: &DocContext, def: Def) -> DefId {
2644 2645
    debug!("register_def({:?})", def);

2646
    let (did, kind) = match def {
2647 2648 2649 2650 2651 2652 2653 2654 2655 2656
        Def::Fn(i) => (i, TypeFunction),
        Def::TyAlias(i) => (i, TypeTypedef),
        Def::Enum(i) => (i, TypeEnum),
        Def::Trait(i) => (i, TypeTrait),
        Def::Struct(i) => (i, TypeStruct),
        Def::Mod(i) => (i, TypeModule),
        Def::Static(i, _) => (i, TypeStatic),
        Def::Variant(i, _) => (i, TypeEnum),
        Def::SelfTy(Some(def_id), _) => (def_id, TypeTrait),
        Def::SelfTy(_, Some((impl_id, _))) => return cx.map.local_def_id(impl_id),
2657
        _ => return def.def_id()
C
Corey Richardson 已提交
2658
    };
N
Niko Matsakis 已提交
2659
    if did.is_local() { return did }
2660 2661 2662
    let tcx = match cx.tcx_opt() {
        Some(tcx) => tcx,
        None => return did
2663
    };
2664
    inline::record_extern_fqn(cx, did, kind);
2665 2666 2667
    if let TypeTrait = kind {
        let t = inline::build_external_trait(cx, tcx, did);
        cx.external_traits.borrow_mut().as_mut().unwrap().insert(did, t);
2668
    }
2669
    return did;
C
Corey Richardson 已提交
2670
}
A
Alex Crichton 已提交
2671

2672
fn resolve_use_source(cx: &DocContext, path: Path, id: ast::NodeId) -> ImportSource {
A
Alex Crichton 已提交
2673 2674
    ImportSource {
        path: path,
2675
        did: resolve_def(cx, id),
A
Alex Crichton 已提交
2676 2677 2678
    }
}

N
Niko Matsakis 已提交
2679
fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option<DefId> {
2680
    cx.tcx_opt().and_then(|tcx| {
2681
        tcx.def_map.borrow().get(&id).map(|d| register_def(cx, d.full_def()))
2682
    })
A
Alex Crichton 已提交
2683
}
2684

J
Jorge Aparicio 已提交
2685
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2686
pub struct Macro {
2687
    pub source: String,
2688
    pub imported_from: Option<String>,
2689 2690 2691
}

impl Clean<Item> for doctree::Macro {
2692
    fn clean(&self, cx: &DocContext) -> Item {
2693
        let name = format!("{}!", self.name.clean(cx));
2694
        Item {
2695
            name: Some(name.clone()),
2696 2697
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2698
            visibility: hir::Public.clean(cx),
2699
            stability: self.stab.clean(cx),
2700
            deprecation: self.depr.clean(cx),
2701
            def_id: cx.map.local_def_id(self.id),
2702
            inner: MacroItem(Macro {
2703 2704
                source: format!("macro_rules! {} {{\n{}}}",
                    name.trim_right_matches('!'), self.matchers.iter().map(|span|
J
;  
Jonas Schievink 已提交
2705
                        format!("    {} => {{ ... }};\n", span.to_src(cx))).collect::<String>()),
2706
                imported_from: self.imported_from.clean(cx),
2707 2708 2709 2710
            }),
        }
    }
}
2711

J
Jorge Aparicio 已提交
2712
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2713
pub struct Stability {
V
Vadim Petrochenkov 已提交
2714
    pub level: stability::StabilityLevel,
2715 2716
    pub feature: String,
    pub since: String,
2717
    pub deprecated_since: String,
2718 2719
    pub reason: String,
    pub issue: Option<u32>
2720 2721
}

2722 2723 2724 2725 2726 2727
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Deprecation {
    pub since: String,
    pub note: String,
}

2728
impl Clean<Stability> for attr::Stability {
2729 2730
    fn clean(&self, _: &DocContext) -> Stability {
        Stability {
V
Vadim Petrochenkov 已提交
2731
            level: stability::StabilityLevel::from_attr_level(&self.level),
2732
            feature: self.feature.to_string(),
V
Vadim Petrochenkov 已提交
2733 2734 2735 2736
            since: match self.level {
                attr::Stable {ref since} => since.to_string(),
                _ => "".to_string(),
            },
2737 2738
            deprecated_since: match self.rustc_depr {
                Some(attr::RustcDeprecation {ref since, ..}) => since.to_string(),
V
Vadim Petrochenkov 已提交
2739 2740
                _=> "".to_string(),
            },
2741
            reason: {
2742
                if let Some(ref depr) = self.rustc_depr {
2743 2744 2745 2746 2747 2748
                    depr.reason.to_string()
                } else if let attr::Unstable {reason: Some(ref reason), ..} = self.level {
                    reason.to_string()
                } else {
                    "".to_string()
                }
V
Vadim Petrochenkov 已提交
2749 2750 2751 2752 2753
            },
            issue: match self.level {
                attr::Unstable {issue, ..} => Some(issue),
                _ => None,
            }
2754 2755 2756 2757 2758
        }
    }
}

impl<'a> Clean<Stability> for &'a attr::Stability {
V
Vadim Petrochenkov 已提交
2759 2760
    fn clean(&self, dc: &DocContext) -> Stability {
        (**self).clean(dc)
2761 2762
    }
}
A
Alex Crichton 已提交
2763

2764 2765 2766 2767 2768 2769 2770 2771 2772
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()),
        }
    }
}

2773 2774 2775 2776 2777 2778 2779 2780 2781 2782
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,
2783
            deprecation: None,
2784 2785 2786 2787
        }
    }
}

2788
impl<'tcx> Clean<Item> for ty::AssociatedType<'tcx> {
2789
    fn clean(&self, cx: &DocContext) -> Item {
2790
        let my_name = self.name.clean(cx);
2791 2792 2793 2794 2795 2796

        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.
2797 2798
            let def = cx.tcx().lookup_trait_def(did);
            let predicates = cx.tcx().lookup_predicates(did);
2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821
            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![]
        };
2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832

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

2833 2834
        Item {
            source: DUMMY_SP.clean(cx),
2835
            name: Some(self.name.clean(cx)),
2836
            attrs: inline::load_attrs(cx, cx.tcx(), self.def_id),
2837
            inner: AssociatedTypeItem(bounds, self.ty.clean(cx)),
2838
            visibility: self.vis.clean(cx),
2839
            def_id: self.def_id,
2840
            stability: stability::lookup_stability(cx.tcx(), self.def_id).clean(cx),
2841
            deprecation: stability::lookup_deprecation(cx.tcx(), self.def_id).clean(cx),
2842 2843 2844 2845
        }
    }
}

2846 2847
impl<'a> Clean<Typedef> for (ty::TypeScheme<'a>, ty::GenericPredicates<'a>,
                             ParamSpace) {
2848
    fn clean(&self, cx: &DocContext) -> Typedef {
2849
        let (ref ty_scheme, ref predicates, ps) = *self;
2850 2851
        Typedef {
            type_: ty_scheme.ty.clean(cx),
2852
            generics: (&ty_scheme.generics, predicates, ps).clean(cx)
2853 2854 2855 2856
        }
    }
}

N
Niko Matsakis 已提交
2857
fn lang_struct(cx: &DocContext, did: Option<DefId>,
2858
               t: ty::Ty, name: &str,
A
Alex Crichton 已提交
2859 2860 2861
               fallback: fn(Box<Type>) -> Type) -> Type {
    let did = match did {
        Some(did) => did,
2862
        None => return fallback(box t.clean(cx)),
A
Alex Crichton 已提交
2863
    };
M
mitaa 已提交
2864
    inline::record_extern_fqn(cx, did, TypeStruct);
A
Alex Crichton 已提交
2865 2866 2867 2868 2869 2870 2871
    ResolvedPath {
        typarams: None,
        did: did,
        path: Path {
            global: false,
            segments: vec![PathSegment {
                name: name.to_string(),
2872 2873 2874
                params: PathParameters::AngleBracketed {
                    lifetimes: vec![],
                    types: vec![t.clean(cx)],
2875
                    bindings: vec![]
2876
                }
A
Alex Crichton 已提交
2877 2878
            }],
        },
2879
        is_generic: false,
A
Alex Crichton 已提交
2880 2881
    }
}
2882 2883

/// An equality constraint on an associated type, e.g. `A=Bar` in `Foo<A=Bar>`
J
Jorge Aparicio 已提交
2884
#[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Debug)]
2885 2886 2887 2888 2889
pub struct TypeBinding {
    pub name: String,
    pub ty: Type
}

2890
impl Clean<TypeBinding> for hir::TypeBinding {
2891 2892
    fn clean(&self, cx: &DocContext) -> TypeBinding {
        TypeBinding {
2893
            name: self.name.clean(cx),
2894 2895 2896 2897
            ty: self.ty.clean(cx)
        }
    }
}