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

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

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

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

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

44
use rustc::hir;
45

46
use std::collections::{HashMap, HashSet};
47
use std::path::PathBuf;
48
use std::rc::Rc;
49
use std::u32;
50
use std::env::current_dir;
51

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

57
mod inline;
58
mod simplify;
59

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

65 66 67 68
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 已提交
69
pub trait Clean<T> {
70
    fn clean(&self, cx: &DocContext) -> T;
C
Corey Richardson 已提交
71 72
}

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

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

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

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

C
Corey Richardson 已提交
97
impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
98
    fn clean(&self, cx: &DocContext) -> Option<U> {
M
mitaa 已提交
99
        self.as_ref().map(|v| v.clean(cx))
C
Corey Richardson 已提交
100 101 102
    }
}

103 104 105 106 107 108
impl<T, U> Clean<U> for ty::Binder<T> where T: Clean<U> {
    fn clean(&self, cx: &DocContext) -> U {
        self.0.clean(cx)
    }
}

109
impl<T: Clean<U>, U> Clean<Vec<U>> for P<[T]> {
110 111
    fn clean(&self, cx: &DocContext) -> Vec<U> {
        self.iter().map(|x| x.clean(cx)).collect()
C
Corey Richardson 已提交
112 113 114
    }
}

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

A
Ariel Ben-Yehuda 已提交
125 126
struct CrateNum(ast::CrateNum);

127 128
impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
    fn clean(&self, cx: &DocContext) -> Crate {
129 130
        use rustc::session::config::Input;

131 132 133 134
        if let Some(t) = cx.tcx_opt() {
            cx.deref_trait_did.set(t.lang_items.deref_trait());
        }

135
        let mut externs = Vec::new();
A
Ariel Ben-Yehuda 已提交
136 137 138
        for cnum in cx.sess().cstore.crates() {
            externs.push((cnum, CrateNum(cnum).clean(cx)));
        }
139
        externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
C
Corey Richardson 已提交
140

141
        // Figure out the name of this crate
142
        let input = &cx.input;
143
        let name = link::find_crate_name(None, &self.attrs, input);
144

145
        // Clean the crate, translating the entire libsyntax AST to one that is
146
        // understood by rustdoc.
147
        let mut module = self.module.clean(cx);
148 149 150

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

196
        let src = match cx.input {
197 198 199 200 201 202 203
            Input::File(ref path) => {
                if path.is_absolute() {
                    path.clone()
                } else {
                    current_dir().unwrap().join(path)
                }
            },
204
            Input::Str { ref name, .. } => PathBuf::from(name.clone()),
205 206
        };

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

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

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

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

264 265 266 267
impl Item {
    /// Finds the `doc` attribute as a NameValue and returns the corresponding
    /// value found.
    pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
M
mitaa 已提交
268
        self.attrs.value("doc")
269
    }
M
mitaa 已提交
270 271
    pub fn is_crate(&self) -> bool {
        match self.inner {
272 273 274
            StrippedItem(box ModuleItem(Module { is_crate: true, ..})) |
            ModuleItem(Module { is_crate: true, ..}) => true,
            _ => false,
M
mitaa 已提交
275 276
        }
    }
277
    pub fn is_mod(&self) -> bool {
278
        ItemType::from_item(self) == ItemType::Module
279 280
    }
    pub fn is_trait(&self) -> bool {
281
        ItemType::from_item(self) == ItemType::Trait
282 283
    }
    pub fn is_struct(&self) -> bool {
284
        ItemType::from_item(self) == ItemType::Struct
285 286
    }
    pub fn is_enum(&self) -> bool {
287
        ItemType::from_item(self) == ItemType::Module
288 289
    }
    pub fn is_fn(&self) -> bool {
290
        ItemType::from_item(self) == ItemType::Function
291
    }
M
mitaa 已提交
292
    pub fn is_associated_type(&self) -> bool {
293
        ItemType::from_item(self) == ItemType::AssociatedType
M
mitaa 已提交
294 295
    }
    pub fn is_associated_const(&self) -> bool {
296
        ItemType::from_item(self) == ItemType::AssociatedConst
M
mitaa 已提交
297 298
    }
    pub fn is_method(&self) -> bool {
299
        ItemType::from_item(self) == ItemType::Method
M
mitaa 已提交
300 301
    }
    pub fn is_ty_method(&self) -> bool {
302 303 304 305
        ItemType::from_item(self) == ItemType::TyMethod
    }
    pub fn is_stripped(&self) -> bool {
        match self.inner { StrippedItem(..) => true, _ => false }
M
mitaa 已提交
306
    }
307 308 309 310 311 312 313 314 315
    pub fn has_stripped_fields(&self) -> Option<bool> {
        match self.inner {
            StructItem(ref _struct) => Some(_struct.fields_stripped),
            VariantItem(Variant { kind: StructVariant(ref vstruct)} ) => {
                Some(vstruct.fields_stripped)
            },
            _ => None,
        }
    }
316 317

    pub fn stability_class(&self) -> String {
M
mitaa 已提交
318 319 320 321 322 323 324
        self.stability.as_ref().map(|ref s| {
            let mut base = match s.level {
                stability::Unstable => "unstable".to_string(),
                stability::Stable => String::new(),
            };
            if !s.deprecated_since.is_empty() {
                base.push_str(" deprecated");
325
            }
M
mitaa 已提交
326 327
            base
        }).unwrap_or(String::new())
328
    }
329 330

    pub fn stable_since(&self) -> Option<&str> {
M
mitaa 已提交
331
        self.stability.as_ref().map(|s| &s.since[..])
332
    }
333 334
}

J
Jorge Aparicio 已提交
335
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
336
pub enum ItemEnum {
337 338
    ExternCrateItem(String, Option<String>),
    ImportItem(Import),
C
Corey Richardson 已提交
339 340 341 342
    StructItem(Struct),
    EnumItem(Enum),
    FunctionItem(Function),
    ModuleItem(Module),
343
    TypedefItem(Typedef, bool /* is associated type */),
C
Corey Richardson 已提交
344
    StaticItem(Static),
345
    ConstantItem(Constant),
C
Corey Richardson 已提交
346 347
    TraitItem(Trait),
    ImplItem(Impl),
348 349
    /// A method signature only. Used for required methods in traits (ie,
    /// non-default-methods).
C
Corey Richardson 已提交
350
    TyMethodItem(TyMethod),
351
    /// A method with a body.
C
Corey Richardson 已提交
352
    MethodItem(Method),
353
    StructFieldItem(Type),
C
Corey Richardson 已提交
354
    VariantItem(Variant),
355
    /// `fn`s from an extern block
356
    ForeignFunctionItem(Function),
357
    /// `static`s from an extern block
358
    ForeignStaticItem(Static),
359
    MacroItem(Macro),
360
    PrimitiveItem(PrimitiveType),
361
    AssociatedConstItem(Type, Option<String>),
362
    AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
363
    DefaultImplItem(DefaultImpl),
364 365
    /// An item that has been stripped by a rustdoc pass
    StrippedItem(Box<ItemEnum>),
C
Corey Richardson 已提交
366 367
}

J
Jorge Aparicio 已提交
368
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
369
pub struct Module {
370 371
    pub items: Vec<Item>,
    pub is_crate: bool,
C
Corey Richardson 已提交
372 373 374
}

impl Clean<Item> for doctree::Module {
375
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
376
        let name = if self.name.is_some() {
377
            self.name.unwrap().clean(cx)
C
Corey Richardson 已提交
378
        } else {
379
            "".to_string()
C
Corey Richardson 已提交
380
        };
381 382 383

        let mut items: Vec<Item> = vec![];
        items.extend(self.extern_crates.iter().map(|x| x.clean(cx)));
384
        items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
385 386 387
        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)));
388
        items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx)));
389 390 391 392 393
        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)));
394
        items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
395
        items.extend(self.macros.iter().map(|x| x.clean(cx)));
396
        items.extend(self.def_traits.iter().map(|x| x.clean(cx)));
397 398 399

        // determine if we should display the inner contents or
        // the outer `mod` item for the source code.
400
        let whence = {
401
            let cm = cx.sess().codemap();
402 403 404 405 406 407 408 409 410 411 412
            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 已提交
413 414
        Item {
            name: Some(name),
415 416 417 418
            attrs: self.attrs.clean(cx),
            source: whence.clean(cx),
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
419
            deprecation: self.depr.clean(cx),
420
            def_id: cx.map.local_def_id(self.id),
C
Corey Richardson 已提交
421
            inner: ModuleItem(Module {
422
               is_crate: self.is_crate,
423
               items: items
C
Corey Richardson 已提交
424 425 426 427 428
            })
        }
    }
}

M
mitaa 已提交
429 430 431
pub trait Attributes {
    fn has_word(&self, &str) -> bool;
    fn value<'a>(&'a self, &str) -> Option<&'a str>;
432
    fn list<'a>(&'a self, &str) -> &'a [Attribute];
M
mitaa 已提交
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
}

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

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

    /// Finds an attribute as List and returns the list of attributes nested inside.
461
    fn list<'a>(&'a self, name: &str) -> &'a [Attribute] {
M
mitaa 已提交
462 463 464 465 466 467 468 469 470 471 472
        for attr in self {
            if let List(ref x, ref list) = *attr {
                if name == *x {
                    return &list[..];
                }
            }
        }
        &[]
    }
}

J
Jorge Aparicio 已提交
473
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
474
pub enum Attribute {
475
    Word(String),
M
mitaa 已提交
476
    List(String, Vec<Attribute>),
477
    NameValue(String, String)
C
Corey Richardson 已提交
478 479
}

480
impl Clean<Attribute> for ast::MetaItem {
481
    fn clean(&self, cx: &DocContext) -> Attribute {
C
Corey Richardson 已提交
482
        match self.node {
483 484
            ast::MetaItemKind::Word(ref s) => Word(s.to_string()),
            ast::MetaItemKind::List(ref s, ref l) => {
G
GuillaumeGomez 已提交
485
                List(s.to_string(), l.clean(cx))
486
            }
487
            ast::MetaItemKind::NameValue(ref s, ref v) => {
G
GuillaumeGomez 已提交
488
                NameValue(s.to_string(), lit_to_string(v))
489
            }
C
Corey Richardson 已提交
490 491 492 493
        }
    }
}

494
impl Clean<Attribute> for ast::Attribute {
495
    fn clean(&self, cx: &DocContext) -> Attribute {
496
        self.with_desugared_doc(|a| a.node.value.clean(cx))
C
Corey Richardson 已提交
497 498 499
    }
}

500
// This is a rough approximation that gets us what we want.
501
impl attr::AttrMetaMethods for Attribute {
502
    fn name(&self) -> InternedString {
503
        match *self {
504
            Word(ref n) | List(ref n, _) | NameValue(ref n, _) => {
505
                token::intern_and_get_ident(n)
506
            }
507 508 509
        }
    }

510
    fn value_str(&self) -> Option<InternedString> {
511
        match *self {
512
            NameValue(_, ref v) => {
513
                Some(token::intern_and_get_ident(v))
514
            }
515 516 517
            _ => None,
        }
    }
518
    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<ast::MetaItem>]> { None }
519
    fn span(&self) -> codemap::Span { unimplemented!() }
520 521
}

J
Jorge Aparicio 已提交
522
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
523
pub struct TyParam {
524
    pub name: String,
N
Niko Matsakis 已提交
525
    pub did: DefId,
526
    pub bounds: Vec<TyParamBound>,
527
    pub default: Option<Type>,
528
}
C
Corey Richardson 已提交
529

530
impl Clean<TyParam> for hir::TyParam {
531
    fn clean(&self, cx: &DocContext) -> TyParam {
C
Corey Richardson 已提交
532
        TyParam {
533
            name: self.name.clean(cx),
534
            did: cx.map.local_def_id(self.id),
535
            bounds: self.bounds.clean(cx),
536
            default: self.default.clean(cx),
C
Corey Richardson 已提交
537 538 539 540
        }
    }
}

541
impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> {
542 543
    fn clean(&self, cx: &DocContext) -> TyParam {
        cx.external_typarams.borrow_mut().as_mut().unwrap()
544
          .insert(self.def_id, self.name.clean(cx));
545
        TyParam {
546
            name: self.name.clean(cx),
547
            did: self.def_id,
548
            bounds: vec![], // these are filled in from the where-clauses
549
            default: self.default.clean(cx),
550 551 552 553
        }
    }
}

J
Jorge Aparicio 已提交
554
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
555
pub enum TyParamBound {
556
    RegionBound(Lifetime),
557
    TraitBound(PolyTrait, hir::TraitBoundModifier)
C
Corey Richardson 已提交
558 559
}

560 561
impl TyParamBound {
    fn maybe_sized(cx: &DocContext) -> TyParamBound {
562
        use rustc::hir::TraitBoundModifier as TBM;
563
        let mut sized_bound = ty::BoundSized.clean(cx);
564 565 566 567 568 569 570
        if let TyParamBound::TraitBound(_, ref mut tbm) = sized_bound {
            *tbm = TBM::Maybe
        };
        sized_bound
    }

    fn is_sized_bound(&self, cx: &DocContext) -> bool {
571
        use rustc::hir::TraitBoundModifier as TBM;
572
        if let Some(tcx) = cx.tcx_opt() {
573 574 575
            if let TyParamBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
                if trait_.def_id() == tcx.lang_items.sized_trait() {
                    return true;
576 577 578 579 580 581 582
                }
            }
        }
        false
    }
}

583
impl Clean<TyParamBound> for hir::TyParamBound {
584
    fn clean(&self, cx: &DocContext) -> TyParamBound {
C
Corey Richardson 已提交
585
        match *self {
586 587
            hir::RegionTyParamBound(lt) => RegionBound(lt.clean(cx)),
            hir::TraitTyParamBound(ref t, modifier) => TraitBound(t.clean(cx), modifier),
C
Corey Richardson 已提交
588 589 590 591
        }
    }
}

592 593 594 595
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)));
596
        for bb in &self.builtin_bounds {
597
            tp_bounds.push(bb.clean(cx));
598
        }
N
Niko Matsakis 已提交
599

600
        let mut bindings = vec![];
601
        for &ty::Binder(ref pb) in &self.projection_bounds {
602 603 604 605 606
            bindings.push(TypeBinding {
                name: pb.projection_ty.item_name.clean(cx),
                ty: pb.ty.clean(cx)
            });
        }
N
Niko Matsakis 已提交
607

608
        (tp_bounds, bindings)
609 610 611
    }
}

N
Niko Matsakis 已提交
612
fn external_path_params(cx: &DocContext, trait_did: Option<DefId>,
613
                        bindings: Vec<TypeBinding>, substs: &subst::Substs) -> PathParameters {
614
    let lifetimes = substs.regions.get_slice(subst::TypeSpace)
615
                    .iter()
616
                    .filter_map(|v| v.clean(cx))
617
                    .collect();
618
    let types = substs.types.get_slice(subst::TypeSpace).to_vec();
619 620 621 622

    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() => {
623
            assert_eq!(types.len(), 1);
624
            let inputs = match types[0].sty {
625
                ty::TyTuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
626 627 628
                _ => {
                    return PathParameters::AngleBracketed {
                        lifetimes: lifetimes,
629
                        types: types.clean(cx),
630
                        bindings: bindings
631 632 633
                    }
                }
            };
634 635 636
            let output = None;
            // FIXME(#20299) return type comes from a projection now
            // match types[1].sty {
637
            //     ty::TyTuple(ref v) if v.is_empty() => None, // -> ()
638 639
            //     _ => Some(types[1].clean(cx))
            // };
640 641 642 643 644 645 646 647 648
            PathParameters::Parenthesized {
                inputs: inputs,
                output: output
            }
        },
        (_, _) => {
            PathParameters::AngleBracketed {
                lifetimes: lifetimes,
                types: types.clean(cx),
649
                bindings: bindings
650 651 652 653 654 655 656
            }
        }
    }
}

// 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 已提交
657
fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>,
658
                 bindings: Vec<TypeBinding>, substs: &subst::Substs) -> Path {
659 660 661
    Path {
        global: false,
        segments: vec![PathSegment {
662
            name: name.to_string(),
663
            params: external_path_params(cx, trait_did, bindings, substs)
664
        }],
665 666 667 668
    }
}

impl Clean<TyParamBound> for ty::BuiltinBound {
669 670 671
    fn clean(&self, cx: &DocContext) -> TyParamBound {
        let tcx = match cx.tcx_opt() {
            Some(tcx) => tcx,
672
            None => return RegionBound(Lifetime::statik())
673
        };
674
        let empty = subst::Substs::empty();
675 676
        let (did, path) = match *self {
            ty::BoundSend =>
677
                (tcx.lang_items.send_trait().unwrap(),
678
                 external_path(cx, "Send", None, vec![], &empty)),
679
            ty::BoundSized =>
680
                (tcx.lang_items.sized_trait().unwrap(),
681
                 external_path(cx, "Sized", None, vec![], &empty)),
682
            ty::BoundCopy =>
683
                (tcx.lang_items.copy_trait().unwrap(),
684
                 external_path(cx, "Copy", None, vec![], &empty)),
A
Alex Crichton 已提交
685 686
            ty::BoundSync =>
                (tcx.lang_items.sync_trait().unwrap(),
687
                 external_path(cx, "Sync", None, vec![], &empty)),
688
        };
M
mitaa 已提交
689
        inline::record_extern_fqn(cx, did, TypeTrait);
690 691 692 693 694
        TraitBound(PolyTrait {
            trait_: ResolvedPath {
                path: path,
                typarams: None,
                did: did,
695
                is_generic: false,
696 697
            },
            lifetimes: vec![]
698
        }, hir::TraitBoundModifier::None)
699 700 701
    }
}

702
impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
703 704 705
    fn clean(&self, cx: &DocContext) -> TyParamBound {
        let tcx = match cx.tcx_opt() {
            Some(tcx) => tcx,
706
            None => return RegionBound(Lifetime::statik())
707
        };
M
mitaa 已提交
708 709
        inline::record_extern_fqn(cx, self.def_id, TypeTrait);
        let path = external_path(cx, &tcx.item_name(self.def_id).as_str(),
710
                                 Some(self.def_id), vec![], self.substs);
711

712
        debug!("ty::TraitRef\n  substs.types(TypeSpace): {:?}\n",
713 714 715 716
               self.substs.types.get_slice(ParamSpace::TypeSpace));

        // collect any late bound regions
        let mut late_bounds = vec![];
717
        for &ty_s in self.substs.types.get_slice(ParamSpace::TypeSpace) {
718
            if let ty::TyTuple(ref ts) = ty_s.sty {
719
                for &ty_s in ts {
720 721
                    if let ty::TyRef(ref reg, _) = ty_s.sty {
                        if let &ty::Region::ReLateBound(_, _) = *reg {
722
                            debug!("  hit an ReLateBound {:?}", reg);
723
                            if let Some(lt) = reg.clean(cx) {
M
mitaa 已提交
724
                                late_bounds.push(lt);
725 726 727 728 729 730 731
                            }
                        }
                    }
                }
            }
        }

732 733 734 735 736 737 738 739 740
        TraitBound(
            PolyTrait {
                trait_: ResolvedPath {
                    path: path,
                    typarams: None,
                    did: self.def_id,
                    is_generic: false,
                },
                lifetimes: late_bounds,
741
            },
742 743
            hir::TraitBoundModifier::None
        )
744 745 746
    }
}

747
impl<'tcx> Clean<Option<Vec<TyParamBound>>> for subst::Substs<'tcx> {
748
    fn clean(&self, cx: &DocContext) -> Option<Vec<TyParamBound>> {
749
        let mut v = Vec::new();
750
        v.extend(self.regions.iter().filter_map(|r| r.clean(cx)).map(RegionBound));
751 752 753
        v.extend(self.types.iter().map(|t| TraitBound(PolyTrait {
            trait_: t.clean(cx),
            lifetimes: vec![]
754
        }, hir::TraitBoundModifier::None)));
755
        if !v.is_empty() {Some(v)} else {None}
756 757 758
    }
}

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

762 763 764
impl Lifetime {
    pub fn get_ref<'a>(&'a self) -> &'a str {
        let Lifetime(ref s) = *self;
765
        let s: &'a str = s;
766 767
        return s;
    }
768 769 770 771

    pub fn statik() -> Lifetime {
        Lifetime("'static".to_string())
    }
772 773
}

774
impl Clean<Lifetime> for hir::Lifetime {
775
    fn clean(&self, _: &DocContext) -> Lifetime {
776
        Lifetime(self.name.to_string())
C
Corey Richardson 已提交
777 778 779
    }
}

780
impl Clean<Lifetime> for hir::LifetimeDef {
781
    fn clean(&self, _: &DocContext) -> Lifetime {
782
        Lifetime(self.lifetime.name.to_string())
783 784 785
    }
}

786
impl Clean<Lifetime> for ty::RegionParameterDef {
787
    fn clean(&self, _: &DocContext) -> Lifetime {
788
        Lifetime(self.name.to_string())
789 790 791 792
    }
}

impl Clean<Option<Lifetime>> for ty::Region {
793
    fn clean(&self, cx: &DocContext) -> Option<Lifetime> {
794
        match *self {
795
            ty::ReStatic => Some(Lifetime::statik()),
M
mitaa 已提交
796
            ty::ReLateBound(_, ty::BrNamed(_, name)) => Some(Lifetime(name.to_string())),
N
Niko Matsakis 已提交
797
            ty::ReEarlyBound(ref data) => Some(Lifetime(data.name.clean(cx))),
798 799 800 801

            ty::ReLateBound(..) |
            ty::ReFree(..) |
            ty::ReScope(..) |
802 803
            ty::ReVar(..) |
            ty::ReSkolemized(..) |
V
Vadim Petrochenkov 已提交
804
            ty::ReEmpty => None
805 806 807 808
        }
    }
}

J
Jorge Aparicio 已提交
809
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
810 811 812
pub enum WherePredicate {
    BoundPredicate { ty: Type, bounds: Vec<TyParamBound> },
    RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>},
813
    EqPredicate { lhs: Type, rhs: Type }
814 815
}

816
impl Clean<WherePredicate> for hir::WherePredicate {
817
    fn clean(&self, cx: &DocContext) -> WherePredicate {
N
Nick Cameron 已提交
818
        match *self {
819
            hir::WherePredicate::BoundPredicate(ref wbp) => {
820
                WherePredicate::BoundPredicate {
821
                    ty: wbp.bounded_ty.clean(cx),
N
Nick Cameron 已提交
822 823 824
                    bounds: wbp.bounds.clean(cx)
                }
            }
825

826
            hir::WherePredicate::RegionPredicate(ref wrp) => {
827 828 829 830 831 832
                WherePredicate::RegionPredicate {
                    lifetime: wrp.lifetime.clean(cx),
                    bounds: wrp.bounds.clean(cx)
                }
            }

833
            hir::WherePredicate::EqPredicate(_) => {
834
                unimplemented!() // FIXME(#20041)
N
Nick Cameron 已提交
835
            }
836 837 838 839
        }
    }
}

840 841
impl<'a> Clean<WherePredicate> for ty::Predicate<'a> {
    fn clean(&self, cx: &DocContext) -> WherePredicate {
842
        use rustc::ty::Predicate;
843 844 845 846 847 848

        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),
849 850 851
            Predicate::Projection(ref pred) => pred.clean(cx),
            Predicate::WellFormed(_) => panic!("not user writable"),
            Predicate::ObjectSafe(_) => panic!("not user writable"),
852
            Predicate::ClosureKind(..) => panic!("not user writable"),
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 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909
        }
    }
}

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_,
910 911 912
            TyParamBound::RegionBound(_) => {
                panic!("cleaning a trait got a region")
            }
913 914 915 916 917 918 919 920 921
        };
        Type::QPath {
            name: self.item_name.clean(cx),
            self_type: box self.trait_ref.self_ty().clean(cx),
            trait_: box trait_
        }
    }
}

922
// maybe use a Generic enum and use Vec<Generic>?
J
Jorge Aparicio 已提交
923
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
924
pub struct Generics {
925 926
    pub lifetimes: Vec<Lifetime>,
    pub type_params: Vec<TyParam>,
927
    pub where_predicates: Vec<WherePredicate>
928
}
C
Corey Richardson 已提交
929

930
impl Clean<Generics> for hir::Generics {
931
    fn clean(&self, cx: &DocContext) -> Generics {
C
Corey Richardson 已提交
932
        Generics {
933 934
            lifetimes: self.lifetimes.clean(cx),
            type_params: self.ty_params.clean(cx),
935
            where_predicates: self.where_clause.predicates.clean(cx)
C
Corey Richardson 已提交
936 937 938 939
        }
    }
}

940 941 942
impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
                                    &'a ty::GenericPredicates<'tcx>,
                                    subst::ParamSpace) {
943
    fn clean(&self, cx: &DocContext) -> Generics {
944 945
        use self::WherePredicate as WP;

946 947
        let (gens, preds, space) = *self;

948 949 950
        // Bounds in the type_params and lifetimes fields are repeated in the
        // predicates field (see rustc_typeck::collect::ty_generics), so remove
        // them.
951
        let stripped_typarams = gens.types.get_slice(space).iter().map(|tp| {
952
            tp.clean(cx)
953 954 955 956 957 958 959
        }).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<_>>();

960 961
        let mut where_predicates = preds.predicates.get_slice(space)
                                                   .to_vec().clean(cx);
962

963
        // Type parameters and have a Sized bound by default unless removed with
964 965
        // ?Sized.  Scan through the predicates and mark any type parameter with
        // a Sized bound, removing the bounds as we find them.
966 967
        //
        // Note that associated types also have a sized bound by default, but we
968
        // don't actually know the set of associated types right here so that's
969
        // handled in cleaning associated types
970
        let mut sized_params = HashSet::new();
971 972 973 974 975 976 977 978 979
        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
                    }
980
                }
981
                _ => true,
982
            }
983
        });
984

985
        // Run through the type parameters again and insert a ?Sized
986
        // unbound for any we didn't find to be Sized.
987
        for tp in &stripped_typarams {
988 989 990
            if !sized_params.contains(&tp.name) {
                where_predicates.push(WP::BoundPredicate {
                    ty: Type::Generic(tp.name.clone()),
991
                    bounds: vec![TyParamBound::maybe_sized(cx)],
992 993 994 995 996 997 998 999
                })
            }
        }

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

1000
        Generics {
1001
            type_params: simplify::ty_params(stripped_typarams),
1002
            lifetimes: stripped_lifetimes,
1003
            where_predicates: simplify::where_clauses(cx, where_predicates),
1004 1005 1006 1007
        }
    }
}

J
Jorge Aparicio 已提交
1008
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1009
pub struct Method {
1010 1011
    pub generics: Generics,
    pub self_: SelfTy,
1012 1013
    pub unsafety: hir::Unsafety,
    pub constness: hir::Constness,
1014
    pub decl: FnDecl,
1015
    pub abi: Abi,
C
Corey Richardson 已提交
1016 1017
}

1018
impl Clean<Method> for hir::MethodSig {
1019
    fn clean(&self, cx: &DocContext) -> Method {
1020 1021
        let all_inputs = &self.decl.inputs;
        let inputs = match self.explicit_self.node {
1022
            hir::SelfStatic => &**all_inputs,
J
Jorge Aparicio 已提交
1023
            _ => &all_inputs[1..]
1024 1025
        };
        let decl = FnDecl {
1026
            inputs: Arguments {
1027
                values: inputs.clean(cx),
1028
            },
1029
            output: self.decl.output.clean(cx),
1030
            variadic: false,
1031
            attrs: Vec::new()
1032
        };
1033
        Method {
1034 1035
            generics: self.generics.clean(cx),
            self_: self.explicit_self.node.clean(cx),
1036 1037
            unsafety: self.unsafety,
            constness: self.constness,
1038
            decl: decl,
1039
            abi: self.abi
C
Corey Richardson 已提交
1040 1041 1042 1043
        }
    }
}

J
Jorge Aparicio 已提交
1044
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1045
pub struct TyMethod {
1046
    pub unsafety: hir::Unsafety,
1047 1048 1049
    pub decl: FnDecl,
    pub generics: Generics,
    pub self_: SelfTy,
1050
    pub abi: Abi,
C
Corey Richardson 已提交
1051 1052
}

1053
impl Clean<TyMethod> for hir::MethodSig {
1054
    fn clean(&self, cx: &DocContext) -> TyMethod {
1055
        let inputs = match self.explicit_self.node {
1056
            hir::SelfStatic => &*self.decl.inputs,
J
Jorge Aparicio 已提交
1057
            _ => &self.decl.inputs[1..]
1058 1059
        };
        let decl = FnDecl {
1060
            inputs: Arguments {
1061
                values: inputs.clean(cx),
1062
            },
1063
            output: self.decl.output.clean(cx),
1064
            variadic: false,
1065
            attrs: Vec::new()
1066
        };
1067 1068 1069 1070 1071 1072
        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 已提交
1073 1074 1075 1076
        }
    }
}

J
Jorge Aparicio 已提交
1077
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
1078 1079 1080 1081
pub enum SelfTy {
    SelfStatic,
    SelfValue,
    SelfBorrowed(Option<Lifetime>, Mutability),
1082
    SelfExplicit(Type),
C
Corey Richardson 已提交
1083 1084
}

1085
impl Clean<SelfTy> for hir::ExplicitSelf_ {
1086
    fn clean(&self, cx: &DocContext) -> SelfTy {
1087
        match *self {
1088 1089 1090
            hir::SelfStatic => SelfStatic,
            hir::SelfValue(_) => SelfValue,
            hir::SelfRegion(ref lt, ref mt, _) => {
1091
                SelfBorrowed(lt.clean(cx), mt.clean(cx))
1092
            }
1093
            hir::SelfExplicit(ref typ, _) => SelfExplicit(typ.clean(cx)),
C
Corey Richardson 已提交
1094 1095 1096 1097
        }
    }
}

J
Jorge Aparicio 已提交
1098
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1099
pub struct Function {
1100 1101
    pub decl: FnDecl,
    pub generics: Generics,
1102 1103
    pub unsafety: hir::Unsafety,
    pub constness: hir::Constness,
1104
    pub abi: Abi,
C
Corey Richardson 已提交
1105 1106 1107
}

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

J
Jorge Aparicio 已提交
1128
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
C
Corey Richardson 已提交
1129
pub struct FnDecl {
1130
    pub inputs: Arguments,
1131
    pub output: FunctionRetTy,
1132
    pub variadic: bool,
1133 1134
    pub attrs: Vec<Attribute>,
}
C
Corey Richardson 已提交
1135

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

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

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

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

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

1198
impl Clean<Argument> for hir::Arg {
1199
    fn clean(&self, cx: &DocContext) -> Argument {
C
Corey Richardson 已提交
1200
        Argument {
1201
            name: name_from_pat(&*self.pat),
1202
            type_: (self.ty.clean(cx)),
C
Corey Richardson 已提交
1203 1204 1205 1206 1207
            id: self.id
        }
    }
}

J
Jorge Aparicio 已提交
1208
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1209 1210
pub enum FunctionRetTy {
    Return(Type),
1211
    DefaultReturn,
1212
    NoReturn
C
Corey Richardson 已提交
1213 1214
}

1215
impl Clean<FunctionRetTy> for hir::FunctionRetTy {
1216
    fn clean(&self, cx: &DocContext) -> FunctionRetTy {
C
Corey Richardson 已提交
1217
        match *self {
1218 1219 1220
            hir::Return(ref typ) => Return(typ.clean(cx)),
            hir::DefaultReturn(..) => DefaultReturn,
            hir::NoReturn(..) => NoReturn
C
Corey Richardson 已提交
1221 1222 1223 1224
        }
    }
}

J
Jorge Aparicio 已提交
1225
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1226
pub struct Trait {
1227
    pub unsafety: hir::Unsafety,
1228
    pub items: Vec<Item>,
1229
    pub generics: Generics,
1230
    pub bounds: Vec<TyParamBound>,
C
Corey Richardson 已提交
1231 1232 1233
}

impl Clean<Item> for doctree::Trait {
1234
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1235
        Item {
1236 1237 1238
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
1239
            def_id: cx.map.local_def_id(self.id),
1240 1241
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
1242
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
1243
            inner: TraitItem(Trait {
1244
                unsafety: self.unsafety,
1245 1246 1247
                items: self.items.clean(cx),
                generics: self.generics.clean(cx),
                bounds: self.bounds.clean(cx),
C
Corey Richardson 已提交
1248 1249 1250 1251 1252
            }),
        }
    }
}

1253
impl Clean<Type> for hir::TraitRef {
1254
    fn clean(&self, cx: &DocContext) -> Type {
N
Niko Matsakis 已提交
1255
        resolve_type(cx, self.path.clean(cx), self.ref_id)
C
Corey Richardson 已提交
1256 1257 1258
    }
}

1259
impl Clean<PolyTrait> for hir::PolyTraitRef {
1260 1261 1262 1263 1264
    fn clean(&self, cx: &DocContext) -> PolyTrait {
        PolyTrait {
            trait_: self.trait_ref.clean(cx),
            lifetimes: self.bound_lifetimes.clean(cx)
        }
N
Niko Matsakis 已提交
1265 1266 1267
    }
}

1268
impl Clean<Item> for hir::TraitItem {
1269 1270
    fn clean(&self, cx: &DocContext) -> Item {
        let inner = match self.node {
1271
            hir::ConstTraitItem(ref ty, ref default) => {
1272 1273 1274 1275
                AssociatedConstItem(ty.clean(cx),
                                    default.as_ref().map(|expr|
                                                         expr.span.to_src(cx)))
            }
1276
            hir::MethodTraitItem(ref sig, Some(_)) => {
1277 1278
                MethodItem(sig.clean(cx))
            }
1279
            hir::MethodTraitItem(ref sig, None) => {
1280 1281
                TyMethodItem(sig.clean(cx))
            }
1282
            hir::TypeTraitItem(ref bounds, ref default) => {
1283 1284 1285 1286
                AssociatedTypeItem(bounds.clean(cx), default.clean(cx))
            }
        };
        Item {
V
Vadim Petrochenkov 已提交
1287
            name: Some(self.name.clean(cx)),
1288 1289
            attrs: self.attrs.clean(cx),
            source: self.span.clean(cx),
1290
            def_id: cx.map.local_def_id(self.id),
1291
            visibility: None,
1292
            stability: get_stability(cx, cx.map.local_def_id(self.id)),
1293
            deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
1294
            inner: inner
1295 1296 1297 1298
        }
    }
}

1299
impl Clean<Item> for hir::ImplItem {
1300 1301
    fn clean(&self, cx: &DocContext) -> Item {
        let inner = match self.node {
1302
            hir::ImplItemKind::Const(ref ty, ref expr) => {
1303 1304
                AssociatedConstItem(ty.clean(cx),
                                    Some(expr.span.to_src(cx)))
1305
            }
1306
            hir::ImplItemKind::Method(ref sig, _) => {
1307 1308
                MethodItem(sig.clean(cx))
            }
1309
            hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef {
1310 1311 1312 1313 1314 1315
                type_: ty.clean(cx),
                generics: Generics {
                    lifetimes: Vec::new(),
                    type_params: Vec::new(),
                    where_predicates: Vec::new()
                },
1316
            }, true),
1317 1318
        };
        Item {
V
Vadim Petrochenkov 已提交
1319
            name: Some(self.name.clean(cx)),
1320 1321
            source: self.span.clean(cx),
            attrs: self.attrs.clean(cx),
1322
            def_id: cx.map.local_def_id(self.id),
1323
            visibility: self.vis.clean(cx),
1324
            stability: get_stability(cx, cx.map.local_def_id(self.id)),
1325
            deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
1326
            inner: inner
C
Corey Richardson 已提交
1327 1328 1329 1330
        }
    }
}

1331
impl<'tcx> Clean<Item> for ty::Method<'tcx> {
1332
    fn clean(&self, cx: &DocContext) -> Item {
1333
        let (self_, sig) = match self.explicit_self {
1334 1335
            ty::ExplicitSelfCategory::Static => (hir::SelfStatic.clean(cx),
                                                 self.fty.sig.clone()),
1336
            s => {
1337
                let sig = ty::Binder(ty::FnSig {
J
Jorge Aparicio 已提交
1338
                    inputs: self.fty.sig.0.inputs[1..].to_vec(),
1339 1340
                    ..self.fty.sig.0.clone()
                });
1341
                let s = match s {
1342 1343
                    ty::ExplicitSelfCategory::ByValue => SelfValue,
                    ty::ExplicitSelfCategory::ByReference(..) => {
1344
                        match self.fty.sig.0.inputs[0].sty {
1345
                            ty::TyRef(r, mt) => {
1346
                                SelfBorrowed(r.clean(cx), mt.mutbl.clean(cx))
1347
                            }
A
Alex Crichton 已提交
1348
                            _ => unreachable!(),
1349 1350
                        }
                    }
1351
                    ty::ExplicitSelfCategory::ByBox => {
1352
                        SelfExplicit(self.fty.sig.0.inputs[0].clean(cx))
1353
                    }
1354
                    ty::ExplicitSelfCategory::Static => unreachable!(),
1355 1356 1357 1358
                };
                (s, sig)
            }
        };
1359

1360 1361 1362 1363 1364 1365
        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) => {
1366
                cx.tcx().provided_trait_methods(did).iter().any(|m| {
1367 1368 1369 1370 1371 1372 1373 1374 1375 1376
                    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 已提交
1377 1378 1379
                abi: self.fty.abi,

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

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

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

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

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

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

    // _
    Infer,

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

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

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

1497 1498 1499 1500 1501 1502 1503 1504 1505 1506
pub trait GetDefId {
    fn def_id(&self) -> Option<DefId>;
}

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

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

1522
impl GetDefId for Type {
1523 1524 1525 1526 1527 1528
    fn def_id(&self) -> Option<DefId> {
        match *self {
            ResolvedPath { did, .. } => Some(did),
            _ => None,
        }
    }
1529 1530
}

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

1557
    fn find(attrs: &[Attribute]) -> Option<PrimitiveType> {
1558
        for attr in attrs.list("doc") {
M
mitaa 已提交
1559 1560 1561 1562 1563
            if let NameValue(ref k, ref v) = *attr {
                if "primitive" == *k {
                    if let ret@Some(..) = PrimitiveType::from_str(v) {
                        return ret;
                    }
1564 1565 1566
                }
            }
        }
M
mitaa 已提交
1567
        None
1568 1569
    }

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

    pub fn to_url_str(&self) -> &'static str {
1595
        self.to_string()
1596 1597 1598 1599 1600
    }

    /// Creates a rustdoc-specific node id for primitive types.
    ///
    /// These node ids are generally never used by the AST itself.
1601 1602 1603
    pub fn to_def_index(&self) -> DefIndex {
        let x = u32::MAX - 1 - (*self as u32);
        DefIndex::new(x as usize)
1604 1605 1606
    }
}

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

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

1736
            ty::TyProjection(ref data) => data.clean(cx),
1737

1738
            ty::TyParam(ref p) => Generic(p.name.to_string()),
1739

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

1742 1743
            ty::TyInfer(..) => panic!("TyInfer"),
            ty::TyError => panic!("TyError"),
1744 1745 1746 1747
        }
    }
}

1748
impl Clean<Item> for hir::StructField {
1749
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1750
        Item {
1751 1752
            name: Some(self.name).clean(cx),
            attrs: self.attrs.clean(cx),
1753
            source: self.span.clean(cx),
1754
            visibility: self.vis.clean(cx),
1755 1756 1757
            stability: get_stability(cx, cx.map.local_def_id(self.id)),
            deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
            def_id: cx.map.local_def_id(self.id),
1758
            inner: StructFieldItem(self.ty.clean(cx)),
C
Corey Richardson 已提交
1759 1760 1761 1762
        }
    }
}

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

1780
pub type Visibility = hir::Visibility;
C
Corey Richardson 已提交
1781

1782
impl Clean<Option<Visibility>> for hir::Visibility {
1783
    fn clean(&self, _: &DocContext) -> Option<Visibility> {
1784 1785 1786 1787 1788 1789 1790
        Some(self.clone())
    }
}

impl Clean<Option<Visibility>> for ty::Visibility {
    fn clean(&self, _: &DocContext) -> Option<Visibility> {
        Some(if *self == ty::Visibility::Public { hir::Public } else { hir::Inherited })
C
Corey Richardson 已提交
1791 1792 1793
    }
}

J
Jorge Aparicio 已提交
1794
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1795
pub struct Struct {
1796 1797 1798 1799
    pub struct_type: doctree::StructType,
    pub generics: Generics,
    pub fields: Vec<Item>,
    pub fields_stripped: bool,
C
Corey Richardson 已提交
1800 1801 1802
}

impl Clean<Item> for doctree::Struct {
1803
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1804
        Item {
1805 1806 1807
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
1808
            def_id: cx.map.local_def_id(self.id),
1809 1810
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
1811
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
1812 1813
            inner: StructItem(Struct {
                struct_type: self.struct_type,
1814 1815
                generics: self.generics.clean(cx),
                fields: self.fields.clean(cx),
S
Steven Fackler 已提交
1816
                fields_stripped: false,
C
Corey Richardson 已提交
1817 1818 1819 1820 1821
            }),
        }
    }
}

1822
/// This is a more limited form of the standard Struct, different in that
C
Corey Richardson 已提交
1823 1824
/// it lacks the things most items have (name, id, parameterization). Found
/// only as a variant in an enum.
J
Jorge Aparicio 已提交
1825
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1826
pub struct VariantStruct {
1827 1828 1829
    pub struct_type: doctree::StructType,
    pub fields: Vec<Item>,
    pub fields_stripped: bool,
C
Corey Richardson 已提交
1830 1831
}

1832
impl Clean<VariantStruct> for ::rustc::hir::VariantData {
1833
    fn clean(&self, cx: &DocContext) -> VariantStruct {
C
Corey Richardson 已提交
1834 1835
        VariantStruct {
            struct_type: doctree::struct_type_from_def(self),
1836
            fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
S
Steven Fackler 已提交
1837
            fields_stripped: false,
C
Corey Richardson 已提交
1838 1839 1840 1841
        }
    }
}

J
Jorge Aparicio 已提交
1842
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1843
pub struct Enum {
1844 1845 1846
    pub variants: Vec<Item>,
    pub generics: Generics,
    pub variants_stripped: bool,
C
Corey Richardson 已提交
1847 1848 1849
}

impl Clean<Item> for doctree::Enum {
1850
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1851
        Item {
1852 1853 1854
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
1855
            def_id: cx.map.local_def_id(self.id),
1856 1857
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
1858
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
1859
            inner: EnumItem(Enum {
1860 1861
                variants: self.variants.clean(cx),
                generics: self.generics.clean(cx),
S
Steven Fackler 已提交
1862
                variants_stripped: false,
C
Corey Richardson 已提交
1863 1864 1865 1866 1867
            }),
        }
    }
}

J
Jorge Aparicio 已提交
1868
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1869
pub struct Variant {
1870
    pub kind: VariantKind,
C
Corey Richardson 已提交
1871 1872 1873
}

impl Clean<Item> for doctree::Variant {
1874
    fn clean(&self, cx: &DocContext) -> Item {
C
Corey Richardson 已提交
1875
        Item {
1876 1877 1878
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
1879
            visibility: None,
1880
            stability: self.stab.clean(cx),
1881
            deprecation: self.depr.clean(cx),
1882
            def_id: cx.map.local_def_id(self.def.id()),
C
Corey Richardson 已提交
1883
            inner: VariantItem(Variant {
1884
                kind: struct_def_to_variant_kind(&self.def, cx),
C
Corey Richardson 已提交
1885 1886 1887 1888 1889
            }),
        }
    }
}

A
Ariel Ben-Yehuda 已提交
1890
impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
1891
    fn clean(&self, cx: &DocContext) -> Item {
1892 1893 1894 1895 1896 1897
        let kind = match self.kind() {
            ty::VariantKind::Unit => CLikeVariant,
            ty::VariantKind::Tuple => {
                TupleVariant(
                    self.fields.iter().map(|f| f.unsubst_ty().clean(cx)).collect()
                )
1898
            }
1899
            ty::VariantKind::Struct => {
1900 1901 1902
                StructVariant(VariantStruct {
                    struct_type: doctree::Plain,
                    fields_stripped: false,
1903
                    fields: self.fields.iter().map(|field| {
1904 1905
                        Item {
                            source: Span::empty(),
1906
                            name: Some(field.name.clean(cx)),
1907
                            attrs: cx.tcx().get_attrs(field.did).clean(cx),
1908
                            visibility: field.vis.clean(cx),
1909 1910 1911
                            def_id: field.did,
                            stability: get_stability(cx, field.did),
                            deprecation: get_deprecation(cx, field.did),
1912
                            inner: StructFieldItem(field.unsubst_ty().clean(cx))
1913 1914 1915 1916 1917 1918
                        }
                    }).collect()
                })
            }
        };
        Item {
1919
            name: Some(self.name.clean(cx)),
1920
            attrs: inline::load_attrs(cx, cx.tcx(), self.did),
1921
            source: Span::empty(),
1922
            visibility: Some(hir::Inherited),
1923
            def_id: self.did,
1924
            inner: VariantItem(Variant { kind: kind }),
1925
            stability: get_stability(cx, self.did),
1926
            deprecation: get_deprecation(cx, self.did),
1927 1928 1929 1930
        }
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2230
fn detect_derived<M: AttrMetaMethods>(attrs: &[M]) -> bool {
2231
    attr::contains_name(attrs, "automatically_derived")
2232 2233
}

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

2246 2247 2248 2249 2250 2251 2252 2253 2254
        let provided = trait_.def_id().and_then(|did| {
            cx.tcx_opt().map(|tcx| {
                tcx.provided_trait_methods(did)
                   .into_iter()
                   .map(|meth| meth.name.to_string())
                   .collect()
            })
        }).unwrap_or(HashSet::new());

2255
        ret.push(Item {
C
Corey Richardson 已提交
2256
            name: None,
2257 2258
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2259
            def_id: cx.map.local_def_id(self.id),
2260 2261
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
2262
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
2263
            inner: ImplItem(Impl {
2264
                unsafety: self.unsafety,
2265
                generics: self.generics.clean(cx),
2266
                provided_trait_methods: provided,
2267
                trait_: trait_,
2268
                for_: self.for_.clean(cx),
2269
                items: items,
2270
                derived: detect_derived(&self.attrs),
2271
                polarity: Some(self.polarity.clean(cx)),
C
Corey Richardson 已提交
2272
            }),
2273
        });
M
mitaa 已提交
2274
        ret
2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287
    }
}

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 {
2288
            TypedefItem(ref t, true) => &t.type_,
2289 2290 2291
            _ => continue,
        };
        let primitive = match *target {
N
Niko Matsakis 已提交
2292
            ResolvedPath { did, .. } if did.is_local() => continue,
2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323
            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 已提交
2324
            if !did.is_local() {
2325 2326
                inline::build_impl(cx, tcx, did, ret);
            }
C
Corey Richardson 已提交
2327 2328 2329 2330
        }
    }
}

2331 2332
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct DefaultImpl {
2333
    pub unsafety: hir::Unsafety,
2334 2335 2336 2337 2338 2339 2340 2341 2342
    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),
2343
            def_id: cx.map.local_def_id(self.id),
2344
            visibility: Some(hir::Public),
2345
            stability: None,
2346
            deprecation: None,
2347 2348 2349 2350 2351 2352 2353 2354
            inner: DefaultImplItem(DefaultImpl {
                unsafety: self.unsafety,
                trait_: self.trait_.clean(cx),
            }),
        }
    }
}

2355 2356 2357 2358 2359 2360
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),
2361
            def_id: cx.map.local_def_id(0),
2362 2363
            visibility: self.vis.clean(cx),
            stability: None,
2364
            deprecation: None,
2365 2366 2367
            inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
        }
    }
C
Corey Richardson 已提交
2368 2369
}

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

J
Jorge Aparicio 已提交
2436
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2437
pub enum Import {
2438
    // use source as str;
2439
    SimpleImport(String, ImportSource),
A
Alex Crichton 已提交
2440 2441 2442
    // use source::*;
    GlobImport(ImportSource),
    // use source::{a, b, c};
2443
    ImportList(ImportSource, Vec<ViewListIdent>),
A
Alex Crichton 已提交
2444 2445
}

J
Jorge Aparicio 已提交
2446
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
A
Alex Crichton 已提交
2447
pub struct ImportSource {
2448
    pub path: Path,
N
Niko Matsakis 已提交
2449
    pub did: Option<DefId>,
C
Corey Richardson 已提交
2450 2451
}

J
Jorge Aparicio 已提交
2452
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
A
Alex Crichton 已提交
2453
pub struct ViewListIdent {
2454
    pub name: String,
2455
    pub rename: Option<String>,
N
Niko Matsakis 已提交
2456
    pub source: Option<DefId>,
A
Alex Crichton 已提交
2457
}
C
Corey Richardson 已提交
2458

2459
impl Clean<ViewListIdent> for hir::PathListItem {
2460
    fn clean(&self, cx: &DocContext) -> ViewListIdent {
J
Jakub Wieczorek 已提交
2461
        match self.node {
2462
            hir::PathListIdent { id, name, rename } => ViewListIdent {
2463
                name: name.clean(cx),
2464
                rename: rename.map(|r| r.clean(cx)),
2465
                source: resolve_def(cx, id)
J
Jakub Wieczorek 已提交
2466
            },
2467
            hir::PathListMod { id, rename } => ViewListIdent {
2468
                name: "self".to_string(),
2469
                rename: rename.map(|r| r.clean(cx)),
2470
                source: resolve_def(cx, id)
J
Jakub Wieczorek 已提交
2471
            }
A
Alex Crichton 已提交
2472
        }
C
Corey Richardson 已提交
2473 2474 2475
    }
}

2476
impl Clean<Vec<Item>> for hir::ForeignMod {
2477
    fn clean(&self, cx: &DocContext) -> Vec<Item> {
2478 2479
        let mut items = self.items.clean(cx);
        for item in &mut items {
M
mitaa 已提交
2480 2481
            if let ForeignFunctionItem(ref mut f) = item.inner {
                f.abi = self.abi;
2482 2483 2484
            }
        }
        items
2485 2486 2487
    }
}

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

C
Corey Richardson 已提交
2521 2522 2523
// Utilities

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

2527
impl ToSource for syntax::codemap::Span {
2528
    fn to_src(&self, cx: &DocContext) -> String {
2529
        debug!("converting span {:?} to snippet", self.clean(cx));
2530
        let sn = match cx.sess().codemap().span_to_snippet(*self) {
2531 2532
            Ok(x) => x.to_string(),
            Err(_) => "".to_string()
C
Corey Richardson 已提交
2533
        };
2534
        debug!("got snippet {}", sn);
C
Corey Richardson 已提交
2535 2536 2537 2538
        sn
    }
}

2539
fn lit_to_string(lit: &ast::Lit) -> String {
C
Corey Richardson 已提交
2540
    match lit.node {
2541 2542 2543
        ast::LitKind::Str(ref st, _) => st.to_string(),
        ast::LitKind::ByteStr(ref data) => format!("{:?}", data),
        ast::LitKind::Byte(b) => {
2544
            let mut res = String::from("b'");
2545
            for c in (b as char).escape_default() {
2546
                res.push(c);
2547
            }
2548
            res.push('\'');
2549 2550
            res
        },
2551 2552 2553 2554 2555
        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 已提交
2556 2557 2558
    }
}

2559
fn name_from_pat(p: &hir::Pat) -> String {
2560
    use rustc::hir::*;
2561
    debug!("Trying to get a name from pattern: {:?}", p);
2562

C
Corey Richardson 已提交
2563
    match p.node {
2564 2565
        PatKind::Wild => "_".to_string(),
        PatKind::Ident(_, ref p, _) => p.node.to_string(),
2566
        PatKind::TupleStruct(ref p, _) | PatKind::Path(ref p) => path_to_string(p),
2567
        PatKind::QPath(..) => panic!("tried to get argument name from PatKind::QPath, \
2568
                                which is not allowed in function arguments"),
2569
        PatKind::Struct(ref name, ref fields, etc) => {
2570
            format!("{} {{ {}{} }}", path_to_string(name),
2571
                fields.iter().map(|&Spanned { node: ref fp, .. }|
2572
                                  format!("{}: {}", fp.name, name_from_pat(&*fp.pat)))
2573
                             .collect::<Vec<String>>().join(", "),
2574 2575 2576
                if etc { ", ..." } else { "" }
            )
        },
2577
        PatKind::Tup(ref elts) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
2578
                                            .collect::<Vec<String>>().join(", ")),
2579 2580 2581 2582
        PatKind::Box(ref p) => name_from_pat(&**p),
        PatKind::Ref(ref p, _) => name_from_pat(&**p),
        PatKind::Lit(..) => {
            warn!("tried to get argument name from PatKind::Lit, \
2583
                  which is silly in function arguments");
2584
            "()".to_string()
2585
        },
2586
        PatKind::Range(..) => panic!("tried to get argument name from PatKind::Range, \
2587
                              which is not allowed in function arguments"),
2588
        PatKind::Vec(ref begin, ref mid, ref end) => {
2589 2590 2591
            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));
2592
            format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
2593
        },
C
Corey Richardson 已提交
2594 2595 2596 2597
    }
}

/// Given a Type, resolve it using the def_map
N
Niko Matsakis 已提交
2598 2599
fn resolve_type(cx: &DocContext,
                path: Path,
2600
                id: ast::NodeId) -> Type {
2601
    debug!("resolve_type({:?},{:?})", path, id);
2602 2603
    let tcx = match cx.tcx_opt() {
        Some(tcx) => tcx,
2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615
        // 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
            };
        }
2616
    };
M
mitaa 已提交
2617
    let def = tcx.def_map.borrow().get(&id).expect("unresolved id not in defmap").full_def();
2618 2619
    debug!("resolve_type: def={:?}", def);

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

2648
fn register_def(cx: &DocContext, def: Def) -> DefId {
2649 2650
    debug!("register_def({:?})", def);

2651
    let (did, kind) = match def {
2652 2653 2654 2655 2656 2657 2658 2659 2660 2661
        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),
2662
        _ => return def.def_id()
C
Corey Richardson 已提交
2663
    };
N
Niko Matsakis 已提交
2664
    if did.is_local() { return did }
2665 2666 2667
    let tcx = match cx.tcx_opt() {
        Some(tcx) => tcx,
        None => return did
2668
    };
2669
    inline::record_extern_fqn(cx, did, kind);
2670 2671 2672
    if let TypeTrait = kind {
        let t = inline::build_external_trait(cx, tcx, did);
        cx.external_traits.borrow_mut().as_mut().unwrap().insert(did, t);
2673
    }
M
mitaa 已提交
2674
    did
C
Corey Richardson 已提交
2675
}
A
Alex Crichton 已提交
2676

2677
fn resolve_use_source(cx: &DocContext, path: Path, id: ast::NodeId) -> ImportSource {
A
Alex Crichton 已提交
2678 2679
    ImportSource {
        path: path,
2680
        did: resolve_def(cx, id),
A
Alex Crichton 已提交
2681 2682 2683
    }
}

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

J
Jorge Aparicio 已提交
2690
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2691
pub struct Macro {
2692
    pub source: String,
2693
    pub imported_from: Option<String>,
2694 2695 2696
}

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

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

2727 2728 2729 2730 2731 2732
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Deprecation {
    pub since: String,
    pub note: String,
}

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

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

2767 2768 2769 2770 2771 2772 2773 2774 2775
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()),
        }
    }
}

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

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

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

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

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

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

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

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

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