mod.rs 157.9 KB
Newer Older
1 2
// ignore-tidy-filelength

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

6 7 8 9 10
pub mod inline;
pub mod cfg;
mod simplify;
mod auto_trait;
mod blanket_impl;
S
Steven Fackler 已提交
11

12 13
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use rustc_data_structures::sync::Lrc;
14
use rustc_target::spec::abi::Abi;
15 16
use rustc_typeck::hir_ty_to_ty;
use rustc::infer::region_constraints::{RegionConstraintData, Constraint};
17
use rustc::middle::resolve_lifetime as rl;
18
use rustc::middle::lang_items;
19
use rustc::middle::stability;
O
Oliver Scherer 已提交
20
use rustc::mir::interpret::{GlobalId, ConstValue};
V
varkor 已提交
21
use rustc::hir::{self, HirVec};
22
use rustc::hir::def::{self, Res, DefKind, CtorKind};
23
use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
24
use rustc::ty::subst::{InternalSubsts, SubstsRef, UnpackedKind};
25
use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind};
26
use rustc::ty::fold::TypeFolder;
27
use rustc::ty::layout::VariantIdx;
28
use rustc::util::nodemap::{FxHashMap, FxHashSet};
29 30 31 32 33 34
use syntax::ast::{self, AttrStyle, Ident};
use syntax::attr;
use syntax::ext::base::MacroKind;
use syntax::source_map::{dummy_spanned, Spanned};
use syntax::ptr::P;
use syntax::symbol::keywords::{self, Keyword};
35
use syntax::symbol::{Symbol, sym};
36
use syntax::symbol::InternedString;
37
use syntax_pos::{self, Pos, FileName};
38

39 40
use std::collections::hash_map::Entry;
use std::fmt;
41
use std::hash::{Hash, Hasher};
42
use std::default::Default;
M
Manish Goregaokar 已提交
43
use std::{mem, slice, vec};
44
use std::iter::{FromIterator, once};
45
use std::rc::Rc;
G
Guillaume Gomez 已提交
46
use std::str::FromStr;
47
use std::cell::RefCell;
M
mitaa 已提交
48
use std::sync::Arc;
49
use std::u32;
50

51 52
use parking_lot::ReentrantMutex;

53 54 55 56 57 58
use crate::core::{self, DocContext};
use crate::doctree;
use crate::visit_ast;
use crate::html::render::{cache, ExternalLocation};
use crate::html::item_type::ItemType;

C
Corey Richardson 已提交
59

K
kennytm 已提交
60
use self::cfg::Cfg;
61
use self::auto_trait::AutoTraitFinder;
G
Guillaume Gomez 已提交
62
use self::blanket_impl::BlanketImplFinder;
63

64 65 66 67 68 69 70
pub use self::Type::*;
pub use self::Mutability::*;
pub use self::ItemEnum::*;
pub use self::SelfTy::*;
pub use self::FunctionRetTy::*;
pub use self::Visibility::{Public, Inherited};

71
thread_local!(pub static MAX_DEF_ID: RefCell<FxHashMap<CrateNum, DefId>> = Default::default());
72 73

const FN_OUTPUT_NAME: &'static str = "Output";
K
kennytm 已提交
74

75
// extract the stability index for a node from tcx, if possible
76
fn get_stability(cx: &DocContext<'_>, def_id: DefId) -> Option<Stability> {
77
    cx.tcx.lookup_stability(def_id).clean(cx)
78 79
}

80
fn get_deprecation(cx: &DocContext<'_>, def_id: DefId) -> Option<Deprecation> {
81
    cx.tcx.lookup_deprecation(def_id).clean(cx)
82 83
}

C
Corey Richardson 已提交
84
pub trait Clean<T> {
85
    fn clean(&self, cx: &DocContext<'_>) -> T;
C
Corey Richardson 已提交
86 87
}

88
impl<T: Clean<U>, U> Clean<Vec<U>> for [T] {
89
    fn clean(&self, cx: &DocContext<'_>) -> Vec<U> {
90
        self.iter().map(|x| x.clean(cx)).collect()
91 92 93
    }
}

94
impl<T: Clean<U>, U, V: Idx> Clean<IndexVec<V, U>> for IndexVec<V, T> {
95
    fn clean(&self, cx: &DocContext<'_>) -> IndexVec<V, U> {
96 97 98 99
        self.iter().map(|x| x.clean(cx)).collect()
    }
}

100
impl<T: Clean<U>, U> Clean<U> for P<T> {
101
    fn clean(&self, cx: &DocContext<'_>) -> U {
102
        (**self).clean(cx)
C
Corey Richardson 已提交
103 104 105
    }
}

106
impl<T: Clean<U>, U> Clean<U> for Rc<T> {
107
    fn clean(&self, cx: &DocContext<'_>) -> U {
108
        (**self).clean(cx)
109 110 111
    }
}

C
Corey Richardson 已提交
112
impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
113
    fn clean(&self, cx: &DocContext<'_>) -> Option<U> {
M
mitaa 已提交
114
        self.as_ref().map(|v| v.clean(cx))
C
Corey Richardson 已提交
115 116 117
    }
}

118
impl<T, U> Clean<U> for ty::Binder<T> where T: Clean<U> {
119
    fn clean(&self, cx: &DocContext<'_>) -> U {
120
        self.skip_binder().clean(cx)
121 122 123
    }
}

124
impl<T: Clean<U>, U> Clean<Vec<U>> for P<[T]> {
125
    fn clean(&self, cx: &DocContext<'_>) -> Vec<U> {
126
        self.iter().map(|x| x.clean(cx)).collect()
C
Corey Richardson 已提交
127 128 129
    }
}

M
mitaa 已提交
130
#[derive(Clone, Debug)]
C
Corey Richardson 已提交
131
pub struct Crate {
132
    pub name: String,
133
    pub version: Option<String>,
134
    pub src: FileName,
135
    pub module: Option<Item>,
136 137
    pub externs: Vec<(CrateNum, ExternalCrate)>,
    pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
M
mitaa 已提交
138 139
    // These are later on moved into `CACHEKEY`, leaving the map empty.
    // Only here so that they can be filtered through the rustdoc passes.
140
    pub external_traits: Arc<ReentrantMutex<RefCell<FxHashMap<DefId, Trait>>>>,
141
    pub masked_crates: FxHashSet<CrateNum>,
C
Corey Richardson 已提交
142 143
}

144 145
impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
    fn clean(&self, cx: &DocContext<'_>) -> Crate {
146
        use crate::visit_lib::LibEmbargoVisitor;
147

148 149
        {
            let mut r = cx.renderinfo.borrow_mut();
150 151 152
            r.deref_trait_did = cx.tcx.lang_items().deref_trait();
            r.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait();
            r.owned_box_did = cx.tcx.lang_items().owned_box();
153 154
        }

155
        let mut externs = Vec::new();
156
        for &cnum in cx.tcx.crates().iter() {
157
            externs.push((cnum, cnum.clean(cx)));
158 159
            // Analyze doc-reachability for extern items
            LibEmbargoVisitor::new(cx).visit_lib(cnum);
A
Ariel Ben-Yehuda 已提交
160
        }
161
        externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
C
Corey Richardson 已提交
162

163
        // Clean the crate, translating the entire libsyntax AST to one that is
164
        // understood by rustdoc.
165
        let mut module = self.module.clean(cx);
166
        let mut masked_crates = FxHashSet::default();
167 168 169 170

        match module.inner {
            ModuleItem(ref module) => {
                for it in &module.items {
A
Andy Russell 已提交
171 172 173
                    // `compiler_builtins` should be masked too, but we can't apply
                    // `#[doc(masked)]` to the injected `extern crate` because it's unstable.
                    if it.is_extern_crate()
174
                        && (it.attrs.has_doc_flag(sym::masked)
A
Andy Russell 已提交
175 176
                            || self.cx.tcx.is_compiler_builtins(it.def_id.krate))
                    {
177 178 179 180 181 182
                        masked_crates.insert(it.def_id.krate);
                    }
                }
            }
            _ => unreachable!(),
        }
183

G
Guillaume Gomez 已提交
184
        let ExternalCrate { name, src, primitives, keywords, .. } = LOCAL_CRATE.clean(cx);
185 186 187 188 189
        {
            let m = match module.inner {
                ModuleItem(ref mut m) => m,
                _ => unreachable!(),
            };
190 191
            m.items.extend(primitives.iter().map(|&(def_id, prim, ref attrs)| {
                Item {
192 193
                    source: Span::empty(),
                    name: Some(prim.to_url_str().to_string()),
194
                    attrs: attrs.clone(),
J
Jeffrey Seyfried 已提交
195
                    visibility: Some(Public),
196 197
                    stability: get_stability(cx, def_id),
                    deprecation: get_deprecation(cx, def_id),
198
                    def_id,
199
                    inner: PrimitiveItem(prim),
200
                }
201
            }));
G
Guillaume Gomez 已提交
202
            m.items.extend(keywords.into_iter().map(|(def_id, kw, attrs)| {
G
Guillaume Gomez 已提交
203 204 205
                Item {
                    source: Span::empty(),
                    name: Some(kw.clone()),
G
Guillaume Gomez 已提交
206
                    attrs: attrs,
G
Guillaume Gomez 已提交
207 208 209 210
                    visibility: Some(Public),
                    stability: get_stability(cx, def_id),
                    deprecation: get_deprecation(cx, def_id),
                    def_id,
G
Guillaume Gomez 已提交
211
                    inner: KeywordItem(kw),
G
Guillaume Gomez 已提交
212 213
                }
            }));
214
        }
215

C
Corey Richardson 已提交
216
        Crate {
217
            name,
218
            version: None,
219
            src,
220
            module: Some(module),
221 222
            externs,
            primitives,
223
            external_traits: cx.external_traits.clone(),
224
            masked_crates,
225 226 227 228
        }
    }
}

J
Jorge Aparicio 已提交
229
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
230
pub struct ExternalCrate {
231
    pub name: String,
232
    pub src: FileName,
233
    pub attrs: Attributes,
234
    pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
G
Guillaume Gomez 已提交
235
    pub keywords: Vec<(DefId, String, Attributes)>,
236 237
}

A
Ariel Ben-Yehuda 已提交
238
impl Clean<ExternalCrate> for CrateNum {
239
    fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate {
240 241
        let root = DefId { krate: *self, index: CRATE_DEF_INDEX };
        let krate_span = cx.tcx.def_span(root);
D
Donato Sciarra 已提交
242
        let krate_src = cx.sess().source_map().span_to_filename(krate_span);
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260

        // Collect all inner modules which are tagged as implementations of
        // primitives.
        //
        // 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
        // item tagged with `#[doc(primitive)]` then we would also have to
        // 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.
261 262
        let as_primitive = |res: Res| {
            if let Res::Def(DefKind::Mod, def_id) = res {
263 264
                let attrs = cx.tcx.get_attrs(def_id).clean(cx);
                let mut prim = None;
265
                for attr in attrs.lists(sym::doc) {
266
                    if let Some(v) = attr.value_str() {
267
                        if attr.check_name(sym::primitive) {
268 269 270 271
                            prim = PrimitiveType::from_str(&v.as_str());
                            if prim.is_some() {
                                break;
                            }
272
                            // FIXME: should warn on unknown primitives?
273 274 275 276 277 278 279 280
                        }
                    }
                }
                return prim.map(|p| (def_id, p, attrs));
            }
            None
        };
        let primitives = if root.is_local() {
281
            cx.tcx.hir().krate().module.item_ids.iter().filter_map(|&id| {
282
                let item = cx.tcx.hir().expect_item_by_hir_id(id.id);
283
                match item.node {
C
csmoe 已提交
284
                    hir::ItemKind::Mod(_) => {
285
                        as_primitive(Res::Def(
286 287 288
                            DefKind::Mod,
                            cx.tcx.hir().local_def_id_from_hir_id(id.id),
                        ))
289
                    }
C
csmoe 已提交
290
                    hir::ItemKind::Use(ref path, hir::UseKind::Single)
291
                    if item.vis.node.is_pub() => {
292
                        as_primitive(path.res).map(|(_, prim, attrs)| {
293
                            // Pretend the primitive is local.
294
                            (cx.tcx.hir().local_def_id_from_hir_id(id.id), prim, attrs)
295 296 297 298 299 300
                        })
                    }
                    _ => None
                }
            }).collect()
        } else {
301
            cx.tcx.item_children(root).iter().map(|item| item.res)
302 303 304
              .filter_map(as_primitive).collect()
        };

305 306
        let as_keyword = |res: Res| {
            if let Res::Def(DefKind::Mod, def_id) = res {
G
Guillaume Gomez 已提交
307 308
                let attrs = cx.tcx.get_attrs(def_id).clean(cx);
                let mut keyword = None;
309
                for attr in attrs.lists(sym::doc) {
G
Guillaume Gomez 已提交
310
                    if let Some(v) = attr.value_str() {
311
                        if attr.check_name(sym::keyword) {
G
Guillaume Gomez 已提交
312 313 314 315 316 317 318 319 320 321 322 323 324 325
                            keyword = Keyword::from_str(&v.as_str()).ok()
                                                                    .map(|x| x.name().to_string());
                            if keyword.is_some() {
                                break
                            }
                            // FIXME: should warn on unknown keywords?
                        }
                    }
                }
                return keyword.map(|p| (def_id, p, attrs));
            }
            None
        };
        let keywords = if root.is_local() {
326
            cx.tcx.hir().krate().module.item_ids.iter().filter_map(|&id| {
327
                let item = cx.tcx.hir().expect_item_by_hir_id(id.id);
G
Guillaume Gomez 已提交
328
                match item.node {
C
csmoe 已提交
329
                    hir::ItemKind::Mod(_) => {
330
                        as_keyword(Res::Def(
331 332 333
                            DefKind::Mod,
                            cx.tcx.hir().local_def_id_from_hir_id(id.id),
                        ))
G
Guillaume Gomez 已提交
334
                    }
C
csmoe 已提交
335
                    hir::ItemKind::Use(ref path, hir::UseKind::Single)
336
                    if item.vis.node.is_pub() => {
337
                        as_keyword(path.res).map(|(_, prim, attrs)| {
338
                            (cx.tcx.hir().local_def_id_from_hir_id(id.id), prim, attrs)
G
Guillaume Gomez 已提交
339 340 341 342 343 344
                        })
                    }
                    _ => None
                }
            }).collect()
        } else {
345
            cx.tcx.item_children(root).iter().map(|item| item.res)
G
Guillaume Gomez 已提交
346 347 348
              .filter_map(as_keyword).collect()
        };

349
        ExternalCrate {
350
            name: cx.tcx.crate_name(*self).to_string(),
351
            src: krate_src,
352
            attrs: cx.tcx.get_attrs(root).clean(cx),
353
            primitives,
G
Guillaume Gomez 已提交
354
            keywords,
C
Corey Richardson 已提交
355 356 357 358 359 360 361
        }
    }
}

/// 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.
362
#[derive(Clone, RustcEncodable, RustcDecodable)]
C
Corey Richardson 已提交
363 364
pub struct Item {
    /// Stringified span
365
    pub source: Span,
C
Corey Richardson 已提交
366
    /// Not everything has a name. E.g., impls
367
    pub name: Option<String>,
368
    pub attrs: Attributes,
369 370
    pub inner: ItemEnum,
    pub visibility: Option<Visibility>,
N
Niko Matsakis 已提交
371
    pub def_id: DefId,
372
    pub stability: Option<Stability>,
373
    pub deprecation: Option<Deprecation>,
C
Corey Richardson 已提交
374 375
}

376
impl fmt::Debug for Item {
377
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
378 379 380

        let fake = MAX_DEF_ID.with(|m| m.borrow().get(&self.def_id.krate)
                                   .map(|id| self.def_id >= *id).unwrap_or(false));
T
Tatsuyuki Ishi 已提交
381
        let def_id: &dyn fmt::Debug = if fake { &"**FAKE**" } else { &self.def_id };
382 383 384 385 386 387 388 389 390 391 392 393 394 395

        fmt.debug_struct("Item")
            .field("source", &self.source)
            .field("name", &self.name)
            .field("attrs", &self.attrs)
            .field("inner", &self.inner)
            .field("visibility", &self.visibility)
            .field("def_id", def_id)
            .field("stability", &self.stability)
            .field("deprecation", &self.deprecation)
            .finish()
    }
}

396 397 398 399
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> {
400
        self.attrs.doc_value()
401
    }
402 403 404 405 406
    /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
    /// with newlines.
    pub fn collapsed_doc_value(&self) -> Option<String> {
        self.attrs.collapsed_doc_value()
    }
407 408

    pub fn links(&self) -> Vec<(String, String)> {
G
Guillaume Gomez 已提交
409
        self.attrs.links(&self.def_id.krate)
410 411
    }

M
mitaa 已提交
412 413
    pub fn is_crate(&self) -> bool {
        match self.inner {
414 415 416
            StrippedItem(box ModuleItem(Module { is_crate: true, ..})) |
            ModuleItem(Module { is_crate: true, ..}) => true,
            _ => false,
M
mitaa 已提交
417 418
        }
    }
419
    pub fn is_mod(&self) -> bool {
420
        self.type_() == ItemType::Module
421 422
    }
    pub fn is_trait(&self) -> bool {
423
        self.type_() == ItemType::Trait
424 425
    }
    pub fn is_struct(&self) -> bool {
426
        self.type_() == ItemType::Struct
427 428
    }
    pub fn is_enum(&self) -> bool {
429
        self.type_() == ItemType::Enum
430
    }
431 432 433
    pub fn is_variant(&self) -> bool {
        self.type_() == ItemType::Variant
    }
M
mitaa 已提交
434
    pub fn is_associated_type(&self) -> bool {
435
        self.type_() == ItemType::AssociatedType
M
mitaa 已提交
436 437
    }
    pub fn is_associated_const(&self) -> bool {
438
        self.type_() == ItemType::AssociatedConst
M
mitaa 已提交
439 440
    }
    pub fn is_method(&self) -> bool {
441
        self.type_() == ItemType::Method
M
mitaa 已提交
442 443
    }
    pub fn is_ty_method(&self) -> bool {
444
        self.type_() == ItemType::TyMethod
445
    }
446 447 448
    pub fn is_typedef(&self) -> bool {
        self.type_() == ItemType::Typedef
    }
449
    pub fn is_primitive(&self) -> bool {
450
        self.type_() == ItemType::Primitive
451
    }
452 453 454
    pub fn is_union(&self) -> bool {
        self.type_() == ItemType::Union
    }
G
Guillaume Gomez 已提交
455 456 457
    pub fn is_import(&self) -> bool {
        self.type_() == ItemType::Import
    }
458 459 460
    pub fn is_extern_crate(&self) -> bool {
        self.type_() == ItemType::ExternCrate
    }
G
Guillaume Gomez 已提交
461 462 463
    pub fn is_keyword(&self) -> bool {
        self.type_() == ItemType::Keyword
    }
G
Guillaume Gomez 已提交
464

465 466
    pub fn is_stripped(&self) -> bool {
        match self.inner { StrippedItem(..) => true, _ => false }
M
mitaa 已提交
467
    }
468 469 470
    pub fn has_stripped_fields(&self) -> Option<bool> {
        match self.inner {
            StructItem(ref _struct) => Some(_struct.fields_stripped),
V
Vadim Petrochenkov 已提交
471
            UnionItem(ref union) => Some(union.fields_stripped),
472
            VariantItem(Variant { kind: VariantKind::Struct(ref vstruct)} ) => {
473 474 475 476 477
                Some(vstruct.fields_stripped)
            },
            _ => None,
        }
    }
478

479
    pub fn stability_class(&self) -> Option<String> {
480 481
        self.stability.as_ref().and_then(|ref s| {
            let mut classes = Vec::with_capacity(2);
482

483 484 485
            if s.level == stability::Unstable {
                classes.push("unstable");
            }
486

487
            if s.deprecation.is_some() {
488 489
                classes.push("deprecated");
            }
490

491 492 493 494
            if classes.len() != 0 {
                Some(classes.join(" "))
            } else {
                None
495
            }
496
        })
497
    }
498 499

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

503 504
    pub fn is_non_exhaustive(&self) -> bool {
        self.attrs.other_attrs.iter()
505
            .any(|a| a.check_name(sym::non_exhaustive))
506 507
    }

508 509 510 511
    /// Returns a documentation-level item type from the item.
    pub fn type_(&self) -> ItemType {
        ItemType::from(self)
    }
512 513 514 515 516 517 518 519 520

    /// Returns the info in the item's `#[deprecated]` or `#[rustc_deprecated]` attributes.
    ///
    /// If the item is not deprecated, returns `None`.
    pub fn deprecation(&self) -> Option<&Deprecation> {
        self.deprecation
            .as_ref()
            .or_else(|| self.stability.as_ref().and_then(|s| s.deprecation.as_ref()))
    }
521 522 523 524 525 526 527 528 529 530 531 532
    pub fn is_default(&self) -> bool {
        match self.inner {
            ItemEnum::MethodItem(ref meth) => {
                if let Some(defaultness) = meth.defaultness {
                    defaultness.has_value() && !defaultness.is_final()
                } else {
                    false
                }
            }
            _ => false,
        }
    }
533 534
}

J
Jorge Aparicio 已提交
535
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
536
pub enum ItemEnum {
537 538
    ExternCrateItem(String, Option<String>),
    ImportItem(Import),
C
Corey Richardson 已提交
539
    StructItem(Struct),
V
Vadim Petrochenkov 已提交
540
    UnionItem(Union),
C
Corey Richardson 已提交
541 542 543
    EnumItem(Enum),
    FunctionItem(Function),
    ModuleItem(Module),
544
    TypedefItem(Typedef, bool /* is associated type */),
O
Oliver Schneider 已提交
545
    ExistentialItem(Existential, bool /* is associated type */),
C
Corey Richardson 已提交
546
    StaticItem(Static),
547
    ConstantItem(Constant),
C
Corey Richardson 已提交
548
    TraitItem(Trait),
549
    TraitAliasItem(TraitAlias),
C
Corey Richardson 已提交
550
    ImplItem(Impl),
551 552
    /// A method signature only. Used for required methods in traits (ie,
    /// non-default-methods).
C
Corey Richardson 已提交
553
    TyMethodItem(TyMethod),
554
    /// A method with a body.
C
Corey Richardson 已提交
555
    MethodItem(Method),
556
    StructFieldItem(Type),
C
Corey Richardson 已提交
557
    VariantItem(Variant),
558
    /// `fn`s from an extern block
559
    ForeignFunctionItem(Function),
560
    /// `static`s from an extern block
561
    ForeignStaticItem(Static),
P
Paul Lietar 已提交
562 563
    /// `type`s from an extern block
    ForeignTypeItem,
564
    MacroItem(Macro),
565
    ProcMacroItem(ProcMacro),
566
    PrimitiveItem(PrimitiveType),
567
    AssociatedConstItem(Type, Option<String>),
V
varkor 已提交
568
    AssociatedTypeItem(Vec<GenericBound>, Option<Type>),
569 570
    /// An item that has been stripped by a rustdoc pass
    StrippedItem(Box<ItemEnum>),
G
Guillaume Gomez 已提交
571
    KeywordItem(String),
C
Corey Richardson 已提交
572 573
}

574 575 576 577 578 579 580
impl ItemEnum {
    pub fn generics(&self) -> Option<&Generics> {
        Some(match *self {
            ItemEnum::StructItem(ref s) => &s.generics,
            ItemEnum::EnumItem(ref e) => &e.generics,
            ItemEnum::FunctionItem(ref f) => &f.generics,
            ItemEnum::TypedefItem(ref t, _) => &t.generics,
O
Oliver Schneider 已提交
581
            ItemEnum::ExistentialItem(ref t, _) => &t.generics,
582 583 584 585 586
            ItemEnum::TraitItem(ref t) => &t.generics,
            ItemEnum::ImplItem(ref i) => &i.generics,
            ItemEnum::TyMethodItem(ref i) => &i.generics,
            ItemEnum::MethodItem(ref i) => &i.generics,
            ItemEnum::ForeignFunctionItem(ref f) => &f.generics,
587
            ItemEnum::TraitAliasItem(ref ta) => &ta.generics,
588 589 590
            _ => return None,
        })
    }
G
Guillaume Gomez 已提交
591 592 593 594 595 596 597 598

    pub fn is_associated(&self) -> bool {
        match *self {
            ItemEnum::TypedefItem(_, _) |
            ItemEnum::AssociatedTypeItem(_, _) => true,
            _ => false,
        }
    }
599 600
}

J
Jorge Aparicio 已提交
601
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
602
pub struct Module {
603 604
    pub items: Vec<Item>,
    pub is_crate: bool,
C
Corey Richardson 已提交
605 606 607
}

impl Clean<Item> for doctree::Module {
608
    fn clean(&self, cx: &DocContext<'_>) -> Item {
C
Corey Richardson 已提交
609
        let name = if self.name.is_some() {
G
Guillaume Gomez 已提交
610
            self.name.expect("No name provided").clean(cx)
C
Corey Richardson 已提交
611
        } else {
612
            String::new()
C
Corey Richardson 已提交
613
        };
614

615 616 617
        // maintain a stack of mod ids, for doc comment path resolution
        // but we also need to resolve the module's own docs based on whether its docs were written
        // inside or outside the module, so check for that
618
        let attrs = self.attrs.clean(cx);
M
Manish Goregaokar 已提交
619

620
        let mut items: Vec<Item> = vec![];
D
DebugSteven 已提交
621
        items.extend(self.extern_crates.iter().flat_map(|x| x.clean(cx)));
622
        items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
623 624 625
        items.extend(self.structs.iter().map(|x| x.clean(cx)));
        items.extend(self.unions.iter().map(|x| x.clean(cx)));
        items.extend(self.enums.iter().map(|x| x.clean(cx)));
626
        items.extend(self.fns.iter().map(|x| x.clean(cx)));
627
        items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx)));
628 629
        items.extend(self.mods.iter().map(|x| x.clean(cx)));
        items.extend(self.typedefs.iter().map(|x| x.clean(cx)));
O
Oliver Schneider 已提交
630
        items.extend(self.existentials.iter().map(|x| x.clean(cx)));
631 632 633
        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)));
634
        items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
635
        items.extend(self.macros.iter().map(|x| x.clean(cx)));
636
        items.extend(self.proc_macros.iter().map(|x| x.clean(cx)));
637
        items.extend(self.trait_aliases.iter().map(|x| x.clean(cx)));
638 639 640

        // determine if we should display the inner contents or
        // the outer `mod` item for the source code.
641
        let whence = {
D
Donato Sciarra 已提交
642
            let cm = cx.sess().source_map();
643 644
            let outer = cm.lookup_char_pos(self.where_outer.lo());
            let inner = cm.lookup_char_pos(self.where_inner.lo());
645 646 647 648
            if outer.file.start_pos == inner.file.start_pos {
                // mod foo { ... }
                self.where_outer
            } else {
D
Donato Sciarra 已提交
649
                // mod foo; (and a separate SourceFile for the contents)
650 651 652 653
                self.where_inner
            }
        };

C
Corey Richardson 已提交
654 655
        Item {
            name: Some(name),
656
            attrs,
657 658 659
            source: whence.clean(cx),
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
660
            deprecation: self.depr.clean(cx),
661
            def_id: cx.tcx.hir().local_def_id(self.id),
C
Corey Richardson 已提交
662
            inner: ModuleItem(Module {
663
               is_crate: self.is_crate,
664
               items,
C
Corey Richardson 已提交
665 666 667 668 669
            })
        }
    }
}

670 671
pub struct ListAttributesIter<'a> {
    attrs: slice::Iter<'a, ast::Attribute>,
672
    current_list: vec::IntoIter<ast::NestedMetaItem>,
673
    name: Symbol,
M
mitaa 已提交
674 675
}

676
impl<'a> Iterator for ListAttributesIter<'a> {
677
    type Item = ast::NestedMetaItem;
678 679 680 681

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(nested) = self.current_list.next() {
            return Some(nested);
M
mitaa 已提交
682 683
        }

684
        for attr in &mut self.attrs {
685
            if let Some(list) = attr.meta_item_list() {
686
                if attr.check_name(self.name) {
687
                    self.current_list = list.into_iter();
688 689 690
                    if let Some(nested) = self.current_list.next() {
                        return Some(nested);
                    }
M
mitaa 已提交
691 692 693
                }
            }
        }
694

M
mitaa 已提交
695 696
        None
    }
697 698 699 700 701

    fn size_hint(&self) -> (usize, Option<usize>) {
        let lower = self.current_list.len();
        (lower, None)
    }
702
}
M
mitaa 已提交
703

704
pub trait AttributesExt {
M
mitaa 已提交
705
    /// Finds an attribute as List and returns the list of attributes nested inside.
706
    fn lists<'a>(&'a self, name: Symbol) -> ListAttributesIter<'a>;
707 708 709
}

impl AttributesExt for [ast::Attribute] {
710
    fn lists<'a>(&'a self, name: Symbol) -> ListAttributesIter<'a> {
711 712
        ListAttributesIter {
            attrs: self.iter(),
713
            current_list: Vec::new().into_iter(),
714
            name,
M
mitaa 已提交
715 716 717 718
        }
    }
}

719
pub trait NestedAttributesExt {
A
Alexander Regueiro 已提交
720
    /// Returns `true` if the attribute list contains a specific `Word`
721
    fn has_word(self, word: Symbol) -> bool;
722 723
}

724
impl<I: IntoIterator<Item=ast::NestedMetaItem>> NestedAttributesExt for I {
725
    fn has_word(self, word: Symbol) -> bool {
726 727 728 729
        self.into_iter().any(|attr| attr.is_word() && attr.check_name(word))
    }
}

730 731 732 733 734 735 736 737
/// A portion of documentation, extracted from a `#[doc]` attribute.
///
/// Each variant contains the line number within the complete doc-comment where the fragment
/// starts, as well as the Span where the corresponding doc comment or attribute is located.
///
/// Included files are kept separate from inline doc comments so that proper line-number
/// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
/// kept separate because of issue #42760.
738
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787
pub enum DocFragment {
    /// A doc fragment created from a `///` or `//!` doc comment.
    SugaredDoc(usize, syntax_pos::Span, String),
    /// A doc fragment created from a "raw" `#[doc=""]` attribute.
    RawDoc(usize, syntax_pos::Span, String),
    /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
    /// given filename and the file contents.
    Include(usize, syntax_pos::Span, String, String),
}

impl DocFragment {
    pub fn as_str(&self) -> &str {
        match *self {
            DocFragment::SugaredDoc(_, _, ref s) => &s[..],
            DocFragment::RawDoc(_, _, ref s) => &s[..],
            DocFragment::Include(_, _, _, ref s) => &s[..],
        }
    }

    pub fn span(&self) -> syntax_pos::Span {
        match *self {
            DocFragment::SugaredDoc(_, span, _) |
                DocFragment::RawDoc(_, span, _) |
                DocFragment::Include(_, span, _, _) => span,
        }
    }
}

impl<'a> FromIterator<&'a DocFragment> for String {
    fn from_iter<T>(iter: T) -> Self
    where
        T: IntoIterator<Item = &'a DocFragment>
    {
        iter.into_iter().fold(String::new(), |mut acc, frag| {
            if !acc.is_empty() {
                acc.push('\n');
            }
            match *frag {
                DocFragment::SugaredDoc(_, _, ref docs)
                    | DocFragment::RawDoc(_, _, ref docs)
                    | DocFragment::Include(_, _, _, ref docs) =>
                    acc.push_str(docs),
            }

            acc
        })
    }
}

788
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)]
789
pub struct Attributes {
790
    pub doc_strings: Vec<DocFragment>,
791
    pub other_attrs: Vec<ast::Attribute>,
J
John Kåre Alsaker 已提交
792
    pub cfg: Option<Arc<Cfg>>,
793
    pub span: Option<syntax_pos::Span>,
M
Manish Goregaokar 已提交
794
    /// map from Rust paths to resolved defs and potential URL fragments
G
Guillaume Gomez 已提交
795
    pub links: Vec<(String, Option<DefId>, Option<String>)>,
796
    pub inner_docs: bool,
797 798 799
}

impl Attributes {
K
kennytm 已提交
800 801
    /// Extracts the content from an attribute `#[doc(cfg(content))]`.
    fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
802
        use syntax::ast::NestedMetaItem::MetaItem;
K
kennytm 已提交
803 804 805

        if let ast::MetaItemKind::List(ref nmis) = mi.node {
            if nmis.len() == 1 {
806
                if let MetaItem(ref cfg_mi) = nmis[0] {
807
                    if cfg_mi.check_name(sym::cfg) {
K
kennytm 已提交
808 809
                        if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.node {
                            if cfg_nmis.len() == 1 {
810
                                if let MetaItem(ref content_mi) = cfg_nmis[0] {
K
kennytm 已提交
811 812 813 814 815 816 817 818 819 820 821 822
                                    return Some(content_mi);
                                }
                            }
                        }
                    }
                }
            }
        }

        None
    }

823 824 825 826 827 828 829 830
    /// Reads a `MetaItem` from within an attribute, looks for whether it is a
    /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
    /// its expansion.
    fn extract_include(mi: &ast::MetaItem)
        -> Option<(String, String)>
    {
        mi.meta_item_list().and_then(|list| {
            for meta in list {
831
                if meta.check_name(sym::include) {
832 833 834 835 836 837 838 839
                    // the actual compiled `#[doc(include="filename")]` gets expanded to
                    // `#[doc(include(file="filename", contents="file contents")]` so we need to
                    // look for that instead
                    return meta.meta_item_list().and_then(|list| {
                        let mut filename: Option<String> = None;
                        let mut contents: Option<String> = None;

                        for it in list {
840
                            if it.check_name(sym::file) {
841 842 843
                                if let Some(name) = it.value_str() {
                                    filename = Some(name.to_string());
                                }
844
                            } else if it.check_name(sym::contents) {
845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863
                                if let Some(docs) = it.value_str() {
                                    contents = Some(docs.to_string());
                                }
                            }
                        }

                        if let (Some(filename), Some(contents)) = (filename, contents) {
                            Some((filename, contents))
                        } else {
                            None
                        }
                    });
                }
            }

            None
        })
    }

864
    pub fn has_doc_flag(&self, flag: Symbol) -> bool {
865
        for attr in &self.other_attrs {
866
            if !attr.check_name(sym::doc) { continue; }
867 868

            if let Some(items) = attr.meta_item_list() {
869
                if items.iter().filter_map(|i| i.meta_item()).any(|it| it.check_name(flag)) {
870 871 872 873 874 875 876 877
                    return true;
                }
            }
        }

        false
    }

878 879
    pub fn from_ast(diagnostic: &::errors::Handler,
                    attrs: &[ast::Attribute]) -> Attributes {
880
        let mut doc_strings = vec![];
881
        let mut sp = None;
K
kennytm 已提交
882
        let mut cfg = Cfg::True;
883
        let mut doc_line = 0;
K
kennytm 已提交
884

885 886
        let other_attrs = attrs.iter().filter_map(|attr| {
            attr.with_desugared_doc(|attr| {
887
                if attr.check_name(sym::doc) {
K
kennytm 已提交
888 889 890
                    if let Some(mi) = attr.meta() {
                        if let Some(value) = mi.value_str() {
                            // Extracted #[doc = "..."]
891 892 893 894 895 896 897 898 899 900
                            let value = value.to_string();
                            let line = doc_line;
                            doc_line += value.lines().count();

                            if attr.is_sugared_doc {
                                doc_strings.push(DocFragment::SugaredDoc(line, attr.span, value));
                            } else {
                                doc_strings.push(DocFragment::RawDoc(line, attr.span, value));
                            }

K
kennytm 已提交
901 902 903 904 905 906 907 908 909 910 911
                            if sp.is_none() {
                                sp = Some(attr.span);
                            }
                            return None;
                        } else if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
                            // Extracted #[doc(cfg(...))]
                            match Cfg::parse(cfg_mi) {
                                Ok(new_cfg) => cfg &= new_cfg,
                                Err(e) => diagnostic.span_err(e.span, e.msg),
                            }
                            return None;
912 913 914 915 916 917 918 919
                        } else if let Some((filename, contents)) = Attributes::extract_include(&mi)
                        {
                            let line = doc_line;
                            doc_line += contents.lines().count();
                            doc_strings.push(DocFragment::Include(line,
                                                                  attr.span,
                                                                  filename,
                                                                  contents));
920
                        }
921 922 923 924 925
                    }
                }
                Some(attr.clone())
            })
        }).collect();
926

927 928
        // treat #[target_feature(enable = "feat")] attributes as if they were
        // #[doc(cfg(target_feature = "feat"))] attributes as well
929 930
        for attr in attrs.lists(sym::target_feature) {
            if attr.check_name(sym::enable) {
931
                if let Some(feat) = attr.value_str() {
932 933 934
                    let meta = attr::mk_name_value_item_str(
                        Ident::with_empty_ctxt(sym::target_feature),
                        dummy_spanned(feat));
935 936 937 938 939 940 941
                    if let Ok(feat_cfg) = Cfg::parse(&meta) {
                        cfg &= feat_cfg;
                    }
                }
            }
        }

942
        let inner_docs = attrs.iter()
943
                              .filter(|a| a.check_name(sym::doc))
944 945 946
                              .next()
                              .map_or(true, |a| a.style == AttrStyle::Inner);

947
        Attributes {
K
kennytm 已提交
948 949
            doc_strings,
            other_attrs,
J
John Kåre Alsaker 已提交
950
            cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) },
951
            span: sp,
952
            links: vec![],
953
            inner_docs,
954 955
        }
    }
956 957 958 959

    /// Finds the `doc` attribute as a NameValue and returns the corresponding
    /// value found.
    pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
960 961 962 963 964 965 966 967 968 969 970
        self.doc_strings.first().map(|s| s.as_str())
    }

    /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
    /// with newlines.
    pub fn collapsed_doc_value(&self) -> Option<String> {
        if !self.doc_strings.is_empty() {
            Some(self.doc_strings.iter().collect())
        } else {
            None
        }
971
    }
972

A
Alexander Regueiro 已提交
973
    /// Gets links as a vector
974 975
    ///
    /// Cache must be populated before call
G
Guillaume Gomez 已提交
976
    pub fn links(&self, krate: &CrateNum) -> Vec<(String, String)> {
977 978
        use crate::html::format::href;

M
Manish Goregaokar 已提交
979
        self.links.iter().filter_map(|&(ref s, did, ref fragment)| {
G
Guillaume Gomez 已提交
980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002
            match did {
                Some(did) => {
                    if let Some((mut href, ..)) = href(did) {
                        if let Some(ref fragment) = *fragment {
                            href.push_str("#");
                            href.push_str(fragment);
                        }
                        Some((s.clone(), href))
                    } else {
                        None
                    }
                }
                None => {
                    if let Some(ref fragment) = *fragment {
                        let cache = cache();
                        let url = match cache.extern_locations.get(krate) {
                            Some(&(_, ref src, ExternalLocation::Local)) =>
                                src.to_str().expect("invalid file path"),
                            Some(&(_, _, ExternalLocation::Remote(ref s))) => s,
                            Some(&(_, _, ExternalLocation::Unknown)) | None =>
                                "https://doc.rust-lang.org/nightly",
                        };
                        // This is a primitive so the url is done "by hand".
1003
                        let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
G
Guillaume Gomez 已提交
1004
                        Some((s.clone(),
1005
                              format!("{}{}std/primitive.{}.html{}",
G
Guillaume Gomez 已提交
1006 1007
                                      url,
                                      if !url.ends_with('/') { "/" } else { "" },
1008 1009
                                      &fragment[..tail],
                                      &fragment[tail..])))
G
Guillaume Gomez 已提交
1010 1011 1012
                    } else {
                        panic!("This isn't a primitive?!");
                    }
M
Manish Goregaokar 已提交
1013
                }
1014 1015 1016
            }
        }).collect()
    }
C
Corey Richardson 已提交
1017 1018
}

1019 1020 1021 1022 1023 1024
impl PartialEq for Attributes {
    fn eq(&self, rhs: &Self) -> bool {
        self.doc_strings == rhs.doc_strings &&
        self.cfg == rhs.cfg &&
        self.span == rhs.span &&
        self.links == rhs.links &&
1025
        self.other_attrs.iter().map(|attr| attr.id).eq(rhs.other_attrs.iter().map(|attr| attr.id))
1026 1027 1028 1029 1030
    }
}

impl Eq for Attributes {}

1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042
impl Hash for Attributes {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        self.doc_strings.hash(hasher);
        self.cfg.hash(hasher);
        self.span.hash(hasher);
        self.links.hash(hasher);
        for attr in &self.other_attrs {
            attr.id.hash(hasher);
        }
    }
}

1043
impl AttributesExt for Attributes {
1044
    fn lists<'a>(&'a self, name: Symbol) -> ListAttributesIter<'a> {
1045
        self.other_attrs.lists(name)
C
Corey Richardson 已提交
1046 1047 1048
    }
}

1049
impl Clean<Attributes> for [ast::Attribute] {
1050
    fn clean(&self, cx: &DocContext<'_>) -> Attributes {
1051
        Attributes::from_ast(cx.sess().diagnostic(), self)
C
Corey Richardson 已提交
1052 1053 1054
    }
}

1055
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
V
varkor 已提交
1056
pub enum GenericBound {
V
varkor 已提交
1057 1058
    TraitBound(PolyTrait, hir::TraitBoundModifier),
    Outlives(Lifetime),
C
Corey Richardson 已提交
1059 1060
}

V
varkor 已提交
1061
impl GenericBound {
1062
    fn maybe_sized(cx: &DocContext<'_>) -> GenericBound {
1063
        let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem);
1064
        let empty = cx.tcx.intern_substs(&[]);
1065
        let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
1066 1067
            Some(did), false, vec![], empty);
        inline::record_extern_fqn(cx, did, TypeKind::Trait);
V
varkor 已提交
1068
        GenericBound::TraitBound(PolyTrait {
1069
            trait_: ResolvedPath {
1070
                path,
1071
                param_names: None,
1072
                did,
1073 1074
                is_generic: false,
            },
1075
            generic_params: Vec::new(),
1076
        }, hir::TraitBoundModifier::Maybe)
1077 1078
    }

1079
    fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1080
        use rustc::hir::TraitBoundModifier as TBM;
V
varkor 已提交
1081
        if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
1082
            if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
1083
                return true;
1084 1085 1086 1087
            }
        }
        false
    }
1088 1089

    fn get_poly_trait(&self) -> Option<PolyTrait> {
V
varkor 已提交
1090
        if let GenericBound::TraitBound(ref p, _) = *self {
1091 1092 1093 1094 1095 1096
            return Some(p.clone())
        }
        None
    }

    fn get_trait_type(&self) -> Option<Type> {
V
varkor 已提交
1097
        if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1098 1099 1100
            Some(trait_.clone())
        } else {
            None
1101 1102
        }
    }
1103 1104
}

V
varkor 已提交
1105
impl Clean<GenericBound> for hir::GenericBound {
1106
    fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
C
Corey Richardson 已提交
1107
        match *self {
V
varkor 已提交
1108 1109 1110 1111
            hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)),
            hir::GenericBound::Trait(ref t, modifier) => {
                GenericBound::TraitBound(t.clean(cx), modifier)
            }
C
Corey Richardson 已提交
1112 1113 1114 1115
        }
    }
}

1116 1117 1118 1119 1120 1121 1122 1123
fn external_generic_args(
    cx: &DocContext<'_>,
    trait_did: Option<DefId>,
    has_self: bool,
    bindings: Vec<TypeBinding>,
    substs: SubstsRef<'_>,
) -> GenericArgs {
    let mut skip_self = has_self;
V
varkor 已提交
1124
    let mut ty_sty = None;
1125 1126 1127 1128 1129 1130 1131 1132 1133
    let args: Vec<_> = substs.iter().filter_map(|kind| match kind.unpack() {
        UnpackedKind::Lifetime(lt) => {
            lt.clean(cx).and_then(|lt| Some(GenericArg::Lifetime(lt)))
        }
        UnpackedKind::Type(_) if skip_self => {
            skip_self = false;
            None
        }
        UnpackedKind::Type(ty) => {
V
varkor 已提交
1134
            ty_sty = Some(&ty.sty);
1135 1136 1137 1138
            Some(GenericArg::Type(ty.clean(cx)))
        }
        UnpackedKind::Const(ct) => Some(GenericArg::Const(ct.clean(cx))),
    }).collect();
1139

1140
    match trait_did {
1141
        // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
1142
        Some(did) if cx.tcx.lang_items().fn_trait_kind(did).is_some() => {
V
varkor 已提交
1143 1144
            assert!(ty_sty.is_some());
            let inputs = match ty_sty {
V
varkor 已提交
1145
                Some(ty::Tuple(ref tys)) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(),
1146
                _ => return GenericArgs::AngleBracketed { args, bindings },
1147
            };
1148 1149 1150
            let output = None;
            // FIXME(#20299) return type comes from a projection now
            // match types[1].sty {
V
varkor 已提交
1151
            //     ty::Tuple(ref v) if v.is_empty() => None, // -> ()
1152 1153
            //     _ => Some(types[1].clean(cx))
            // };
1154
            GenericArgs::Parenthesized { inputs, output }
1155
        },
1156
        _ => {
1157
            GenericArgs::AngleBracketed { args, bindings }
1158 1159 1160 1161 1162 1163
        }
    }
}

// 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
1164
fn external_path(cx: &DocContext<'_>, name: &str, trait_did: Option<DefId>, has_self: bool,
C
csmoe 已提交
1165
                 bindings: Vec<TypeBinding>, substs: SubstsRef<'_>) -> Path {
1166 1167
    Path {
        global: false,
1168
        res: Res::Err,
1169
        segments: vec![PathSegment {
1170
            name: name.to_string(),
V
varkor 已提交
1171
            args: external_generic_args(cx, trait_did, has_self, bindings, substs)
1172
        }],
1173 1174 1175
    }
}

V
varkor 已提交
1176
impl<'a, 'tcx> Clean<GenericBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>) {
1177
    fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
1178 1179
        let (trait_ref, ref bounds) = *self;
        inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait);
1180
        let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id).as_str(),
1181
                                 Some(trait_ref.def_id), true, bounds.clone(), trait_ref.substs);
1182

1183
        debug!("ty::TraitRef\n  subst: {:?}\n", trait_ref.substs);
1184 1185 1186

        // collect any late bound regions
        let mut late_bounds = vec![];
1187
        for ty_s in trait_ref.input_types().skip(1) {
V
varkor 已提交
1188
            if let ty::Tuple(ts) = ty_s.sty {
1189
                for &ty_s in ts {
V
varkor 已提交
1190
                    if let ty::Ref(ref reg, _, _) = ty_s.expect_ty().sty {
N
Niko Matsakis 已提交
1191
                        if let &ty::RegionKind::ReLateBound(..) = *reg {
1192
                            debug!("  hit an ReLateBound {:?}", reg);
1193 1194 1195 1196 1197
                            if let Some(Lifetime(name)) = reg.clean(cx) {
                                late_bounds.push(GenericParamDef {
                                    name,
                                    kind: GenericParamDefKind::Lifetime,
                                });
1198 1199 1200 1201 1202 1203 1204
                            }
                        }
                    }
                }
            }
        }

V
varkor 已提交
1205
        GenericBound::TraitBound(
1206 1207
            PolyTrait {
                trait_: ResolvedPath {
1208
                    path,
V
varkor 已提交
1209
                    param_names: None,
1210
                    did: trait_ref.def_id,
1211 1212
                    is_generic: false,
                },
1213
                generic_params: late_bounds,
1214
            },
1215 1216
            hir::TraitBoundModifier::None
        )
1217 1218 1219
    }
}

V
varkor 已提交
1220
impl<'tcx> Clean<GenericBound> for ty::TraitRef<'tcx> {
1221
    fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
1222 1223 1224 1225
        (self, vec![]).clean(cx)
    }
}

C
csmoe 已提交
1226
impl<'tcx> Clean<Option<Vec<GenericBound>>> for InternalSubsts<'tcx> {
1227
    fn clean(&self, cx: &DocContext<'_>) -> Option<Vec<GenericBound>> {
1228
        let mut v = Vec::new();
V
varkor 已提交
1229 1230
        v.extend(self.regions().filter_map(|r| r.clean(cx)).map(GenericBound::Outlives));
        v.extend(self.types().map(|t| GenericBound::TraitBound(PolyTrait {
1231
            trait_: t.clean(cx),
1232
            generic_params: Vec::new(),
1233
        }, hir::TraitBoundModifier::None)));
1234
        if !v.is_empty() {Some(v)} else {None}
1235 1236 1237
    }
}

1238
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1239
pub struct Lifetime(String);
C
Corey Richardson 已提交
1240

1241 1242 1243
impl Lifetime {
    pub fn get_ref<'a>(&'a self) -> &'a str {
        let Lifetime(ref s) = *self;
1244
        let s: &'a str = s;
C
Corey Farwell 已提交
1245
        s
1246
    }
1247 1248 1249 1250

    pub fn statik() -> Lifetime {
        Lifetime("'static".to_string())
    }
1251 1252
}

1253
impl Clean<Lifetime> for hir::Lifetime {
1254
    fn clean(&self, cx: &DocContext<'_>) -> Lifetime {
L
ljedrz 已提交
1255
        if self.hir_id != hir::DUMMY_HIR_ID {
1256
            let def = cx.tcx.named_region(self.hir_id);
1257 1258 1259 1260 1261 1262 1263
            match def {
                Some(rl::Region::EarlyBound(_, node_id, _)) |
                Some(rl::Region::LateBound(_, node_id, _)) |
                Some(rl::Region::Free(_, node_id)) => {
                    if let Some(lt) = cx.lt_substs.borrow().get(&node_id).cloned() {
                        return lt;
                    }
E
Eduard Burtescu 已提交
1264
                }
1265
                _ => {}
E
Eduard Burtescu 已提交
1266 1267
            }
        }
1268
        Lifetime(self.name.ident().to_string())
C
Corey Richardson 已提交
1269 1270 1271
    }
}

V
varkor 已提交
1272
impl Clean<Lifetime> for hir::GenericParam {
1273
    fn clean(&self, _: &DocContext<'_>) -> Lifetime {
V
varkor 已提交
1274
        match self.kind {
V
varkor 已提交
1275 1276 1277
            hir::GenericParamKind::Lifetime { .. } => {
                if self.bounds.len() > 0 {
                    let mut bounds = self.bounds.iter().map(|bound| match bound {
V
varkor 已提交
1278
                        hir::GenericBound::Outlives(lt) => lt,
V
varkor 已提交
1279 1280
                        _ => panic!(),
                    });
G
Guillaume Gomez 已提交
1281
                    let name = bounds.next().expect("no more bounds").name.ident();
1282
                    let mut s = format!("{}: {}", self.name.ident(), name);
V
varkor 已提交
1283
                    for bound in bounds {
1284
                        s.push_str(&format!(" + {}", bound.name.ident()));
V
varkor 已提交
1285 1286 1287
                    }
                    Lifetime(s)
                } else {
1288
                    Lifetime(self.name.ident().to_string())
V
varkor 已提交
1289
                }
1290
            }
V
varkor 已提交
1291
            _ => panic!(),
1292
        }
1293 1294 1295
    }
}

V
varkor 已提交
1296
impl Clean<Constant> for hir::ConstArg {
1297
    fn clean(&self, cx: &DocContext<'_>) -> Constant {
V
varkor 已提交
1298 1299 1300 1301 1302 1303 1304
        Constant {
            type_: cx.tcx.type_of(cx.tcx.hir().body_owner_def_id(self.value.body)).clean(cx),
            expr: print_const_expr(cx, self.value.body),
        }
    }
}

1305
impl<'tcx> Clean<Lifetime> for ty::GenericParamDef {
1306
    fn clean(&self, _cx: &DocContext<'_>) -> Lifetime {
1307
        Lifetime(self.name.to_string())
1308 1309 1310
    }
}

1311
impl Clean<Option<Lifetime>> for ty::RegionKind {
1312
    fn clean(&self, cx: &DocContext<'_>) -> Option<Lifetime> {
1313
        match *self {
1314
            ty::ReStatic => Some(Lifetime::statik()),
1315
            ty::ReLateBound(_, ty::BrNamed(_, name)) => Some(Lifetime(name.to_string())),
N
Niko Matsakis 已提交
1316
            ty::ReEarlyBound(ref data) => Some(Lifetime(data.name.clean(cx))),
1317 1318 1319 1320

            ty::ReLateBound(..) |
            ty::ReFree(..) |
            ty::ReScope(..) |
1321
            ty::ReVar(..) |
N
Niko Matsakis 已提交
1322
            ty::RePlaceholder(..) |
1323
            ty::ReEmpty |
1324
            ty::ReClosureBound(_) |
1325 1326 1327 1328
            ty::ReErased => {
                debug!("Cannot clean region {:?}", self);
                None
            }
1329 1330 1331 1332
        }
    }
}

1333
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1334
pub enum WherePredicate {
V
varkor 已提交
1335 1336
    BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
    RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1337
    EqPredicate { lhs: Type, rhs: Type },
1338 1339
}

1340 1341 1342 1343 1344 1345 1346 1347 1348 1349
impl WherePredicate {
    pub fn get_bounds(&self) -> Option<&[GenericBound]> {
        match *self {
            WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
            WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
            _ => None,
        }
    }
}

1350
impl Clean<WherePredicate> for hir::WherePredicate {
1351
    fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
N
Nick Cameron 已提交
1352
        match *self {
1353
            hir::WherePredicate::BoundPredicate(ref wbp) => {
1354
                WherePredicate::BoundPredicate {
1355
                    ty: wbp.bounded_ty.clean(cx),
N
Nick Cameron 已提交
1356 1357 1358
                    bounds: wbp.bounds.clean(cx)
                }
            }
1359

1360
            hir::WherePredicate::RegionPredicate(ref wrp) => {
1361 1362 1363 1364 1365 1366
                WherePredicate::RegionPredicate {
                    lifetime: wrp.lifetime.clean(cx),
                    bounds: wrp.bounds.clean(cx)
                }
            }

1367 1368 1369 1370 1371
            hir::WherePredicate::EqPredicate(ref wrp) => {
                WherePredicate::EqPredicate {
                    lhs: wrp.lhs_ty.clean(cx),
                    rhs: wrp.rhs_ty.clean(cx)
                }
N
Nick Cameron 已提交
1372
            }
1373 1374 1375 1376
        }
    }
}

1377
impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
1378
    fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
1379
        use rustc::ty::Predicate;
1380 1381

        match *self {
1382 1383
            Predicate::Trait(ref pred) => Some(pred.clean(cx)),
            Predicate::Subtype(ref pred) => Some(pred.clean(cx)),
1384 1385
            Predicate::RegionOutlives(ref pred) => pred.clean(cx),
            Predicate::TypeOutlives(ref pred) => pred.clean(cx),
1386
            Predicate::Projection(ref pred) => Some(pred.clean(cx)),
1387 1388 1389 1390

            Predicate::WellFormed(..) |
            Predicate::ObjectSafe(..) |
            Predicate::ClosureKind(..) |
1391
            Predicate::ConstEvaluatable(..) => panic!("not user writable"),
1392 1393 1394 1395 1396
        }
    }
}

impl<'a> Clean<WherePredicate> for ty::TraitPredicate<'a> {
1397
    fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
1398
        WherePredicate::BoundPredicate {
1399
            ty: self.trait_ref.self_ty().clean(cx),
1400 1401 1402 1403 1404
            bounds: vec![self.trait_ref.clean(cx)]
        }
    }
}

N
Niko Matsakis 已提交
1405
impl<'tcx> Clean<WherePredicate> for ty::SubtypePredicate<'tcx> {
1406
    fn clean(&self, _cx: &DocContext<'_>) -> WherePredicate {
1407 1408
        panic!("subtype predicates are an internal rustc artifact \
                and should not be seen by rustdoc")
N
Niko Matsakis 已提交
1409 1410 1411
    }
}

1412 1413 1414
impl<'tcx> Clean<Option<WherePredicate>> for
    ty::OutlivesPredicate<ty::Region<'tcx>,ty::Region<'tcx>> {

1415
    fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
1416
        let ty::OutlivesPredicate(ref a, ref b) = *self;
1417 1418 1419 1420 1421 1422 1423 1424 1425

        match (a, b) {
            (ty::ReEmpty, ty::ReEmpty) => {
                return None;
            },
            _ => {}
        }

        Some(WherePredicate::RegionPredicate {
G
Guillaume Gomez 已提交
1426 1427
            lifetime: a.clean(cx).expect("failed to clean lifetime"),
            bounds: vec![GenericBound::Outlives(b.clean(cx).expect("failed to clean bounds"))]
1428
        })
1429 1430 1431
    }
}

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

1436 1437 1438 1439 1440 1441
        match lt {
            ty::ReEmpty => return None,
            _ => {}
        }

        Some(WherePredicate::BoundPredicate {
1442
            ty: ty.clean(cx),
G
Guillaume Gomez 已提交
1443
            bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))]
1444
        })
1445 1446 1447 1448
    }
}

impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
1449
    fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
1450 1451 1452 1453 1454 1455 1456 1457
        WherePredicate::EqPredicate {
            lhs: self.projection_ty.clean(cx),
            rhs: self.ty.clean(cx)
        }
    }
}

impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
1458
    fn clean(&self, cx: &DocContext<'_>) -> Type {
1459
        let trait_ = match self.trait_ref(cx.tcx).clean(cx) {
V
varkor 已提交
1460 1461
            GenericBound::TraitBound(t, _) => t.trait_,
            GenericBound::Outlives(_) => panic!("cleaning a trait got a lifetime"),
1462 1463
        };
        Type::QPath {
1464
            name: cx.tcx.associated_item(self.item_def_id).ident.name.clean(cx),
1465
            self_type: box self.self_ty().clean(cx),
1466 1467 1468 1469 1470
            trait_: box trait_
        }
    }
}

V
Vadim Petrochenkov 已提交
1471
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1472 1473 1474 1475
pub enum GenericParamDefKind {
    Lifetime,
    Type {
        did: DefId,
V
varkor 已提交
1476
        bounds: Vec<GenericBound>,
1477 1478 1479
        default: Option<Type>,
        synthetic: Option<hir::SyntheticTyParamKind>,
    },
V
varkor 已提交
1480 1481 1482 1483
    Const {
        did: DefId,
        ty: Type,
    },
1484 1485
}

1486 1487 1488 1489 1490 1491 1492 1493
impl GenericParamDefKind {
    pub fn is_type(&self) -> bool {
        match *self {
            GenericParamDefKind::Type { .. } => true,
            _ => false,
        }
    }

G
cleanup  
Guillaume Gomez 已提交
1494
    pub fn get_type(&self, cx: &DocContext<'_>) -> Option<Type> {
1495 1496 1497 1498 1499 1500 1501 1502 1503 1504
        match *self {
            GenericParamDefKind::Type { did, .. } => {
                rustc_typeck::checked_type_of(cx.tcx, did, false).map(|t| t.clean(cx))
            }
            GenericParamDefKind::Const { ref ty, .. } => Some(ty.clone()),
            GenericParamDefKind::Lifetime => None,
        }
    }
}

1505 1506 1507 1508 1509
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
pub struct GenericParamDef {
    pub name: String,

    pub kind: GenericParamDefKind,
1510 1511
}

V
varkor 已提交
1512
impl GenericParamDef {
1513
    pub fn is_synthetic_type_param(&self) -> bool {
1514
        match self.kind {
V
varkor 已提交
1515
            GenericParamDefKind::Lifetime |
1516
            GenericParamDefKind::Const { .. } => false,
1517 1518 1519
            GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
        }
    }
1520 1521 1522 1523 1524

    pub fn is_type(&self) -> bool {
        self.kind.is_type()
    }

G
cleanup  
Guillaume Gomez 已提交
1525
    pub fn get_type(&self, cx: &DocContext<'_>) -> Option<Type> {
1526 1527 1528 1529 1530 1531 1532 1533 1534
        self.kind.get_type(cx)
    }

    pub fn get_bounds(&self) -> Option<&[GenericBound]> {
        match self.kind {
            GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
            _ => None,
        }
    }
1535 1536
}

1537
impl Clean<GenericParamDef> for ty::GenericParamDef {
1538
    fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
1539 1540 1541 1542 1543
        let (name, kind) = match self.kind {
            ty::GenericParamDefKind::Lifetime => {
                (self.name.to_string(), GenericParamDefKind::Lifetime)
            }
            ty::GenericParamDefKind::Type { has_default, .. } => {
1544
                cx.renderinfo.borrow_mut().external_param_names
1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557
                             .insert(self.def_id, self.name.clean(cx));
                let default = if has_default {
                    Some(cx.tcx.type_of(self.def_id).clean(cx))
                } else {
                    None
                };
                (self.name.clean(cx), GenericParamDefKind::Type {
                    did: self.def_id,
                    bounds: vec![], // These are filled in from the where-clauses.
                    default,
                    synthetic: None,
                })
            }
1558
            ty::GenericParamDefKind::Const { .. } => {
1559 1560 1561 1562
                (self.name.clean(cx), GenericParamDefKind::Const {
                    did: self.def_id,
                    ty: cx.tcx.type_of(self.def_id).clean(cx),
                })
1563
            }
1564 1565 1566 1567 1568
        };

        GenericParamDef {
            name,
            kind,
1569 1570 1571 1572
        }
    }
}

V
varkor 已提交
1573
impl Clean<GenericParamDef> for hir::GenericParam {
1574
    fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
1575
        let (name, kind) = match self.kind {
V
varkor 已提交
1576 1577 1578
            hir::GenericParamKind::Lifetime { .. } => {
                let name = if self.bounds.len() > 0 {
                    let mut bounds = self.bounds.iter().map(|bound| match bound {
V
varkor 已提交
1579
                        hir::GenericBound::Outlives(lt) => lt,
V
varkor 已提交
1580 1581
                        _ => panic!(),
                    });
G
Guillaume Gomez 已提交
1582
                    let name = bounds.next().expect("no more bounds").name.ident();
V
Vadim Petrochenkov 已提交
1583
                    let mut s = format!("{}: {}", self.name.ident(), name);
V
varkor 已提交
1584
                    for bound in bounds {
V
Vadim Petrochenkov 已提交
1585
                        s.push_str(&format!(" + {}", bound.name.ident()));
1586 1587 1588
                    }
                    s
                } else {
V
Vadim Petrochenkov 已提交
1589
                    self.name.ident().to_string()
1590 1591 1592
                };
                (name, GenericParamDefKind::Lifetime)
            }
V
varkor 已提交
1593
            hir::GenericParamKind::Type { ref default, synthetic } => {
V
Vadim Petrochenkov 已提交
1594
                (self.name.ident().name.clean(cx), GenericParamDefKind::Type {
L
ljedrz 已提交
1595
                    did: cx.tcx.hir().local_def_id_from_hir_id(self.hir_id),
V
varkor 已提交
1596
                    bounds: self.bounds.clean(cx),
1597 1598 1599
                    default: default.clean(cx),
                    synthetic: synthetic,
                })
V
varkor 已提交
1600
            }
V
varkor 已提交
1601 1602
            hir::GenericParamKind::Const { ref ty } => {
                (self.name.ident().name.clean(cx), GenericParamDefKind::Const {
L
ljedrz 已提交
1603
                    did: cx.tcx.hir().local_def_id_from_hir_id(self.hir_id),
V
varkor 已提交
1604 1605 1606
                    ty: ty.clean(cx),
                })
            }
1607 1608 1609 1610 1611
        };

        GenericParamDef {
            name,
            kind,
1612 1613 1614 1615
        }
    }
}

1616 1617
// maybe use a Generic enum and use Vec<Generic>?
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Default, Hash)]
C
Corey Richardson 已提交
1618
pub struct Generics {
V
varkor 已提交
1619
    pub params: Vec<GenericParamDef>,
1620
    pub where_predicates: Vec<WherePredicate>,
1621
}
C
Corey Richardson 已提交
1622

1623
impl Clean<Generics> for hir::Generics {
1624
    fn clean(&self, cx: &DocContext<'_>) -> Generics {
1625 1626 1627 1628
        // Synthetic type-parameters are inserted after normal ones.
        // In order for normal parameters to be able to refer to synthetic ones,
        // scans them first.
        fn is_impl_trait(param: &hir::GenericParam) -> bool {
V
varkor 已提交
1629 1630 1631 1632 1633
            match param.kind {
                hir::GenericParamKind::Type { synthetic, .. } => {
                    synthetic == Some(hir::SyntheticTyParamKind::ImplTrait)
                }
                _ => false,
1634 1635 1636 1637
            }
        }
        let impl_trait_params = self.params
            .iter()
1638 1639 1640 1641 1642 1643 1644 1645
            .filter(|param| is_impl_trait(param))
            .map(|param| {
                let param: GenericParamDef = param.clean(cx);
                match param.kind {
                    GenericParamDefKind::Lifetime => unreachable!(),
                    GenericParamDefKind::Type { did, ref bounds, .. } => {
                        cx.impl_trait_bounds.borrow_mut().insert(did, bounds.clone());
                    }
V
varkor 已提交
1646
                    GenericParamDefKind::Const { .. } => unreachable!(),
1647
                }
1648
                param
1649 1650 1651
            })
            .collect::<Vec<_>>();

1652
        let mut params = Vec::with_capacity(self.params.len());
1653
        for p in self.params.iter().filter(|p| !is_impl_trait(p)) {
1654 1655 1656
            let p = p.clean(cx);
            params.push(p);
        }
1657 1658
        params.extend(impl_trait_params);

1659
        let mut generics = Generics {
1660
            params,
1661
            where_predicates: self.where_clause.predicates.clean(cx),
1662 1663 1664 1665 1666
        };

        // Some duplicates are generated for ?Sized bounds between type params and where
        // predicates. The point in here is to move the bounds definitions from type params
        // to where predicates when such cases occur.
1667
        for where_pred in &mut generics.where_predicates {
1668 1669 1670
            match *where_pred {
                WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => {
                    if bounds.is_empty() {
1671 1672 1673 1674 1675 1676 1677 1678
                        for param in &mut generics.params {
                            match param.kind {
                                GenericParamDefKind::Lifetime => {}
                                GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
                                    if &param.name == name {
                                        mem::swap(bounds, ty_bounds);
                                        break
                                    }
1679
                                }
V
varkor 已提交
1680
                                GenericParamDefKind::Const { .. } => {}
1681 1682 1683 1684 1685 1686
                            }
                        }
                    }
                }
                _ => continue,
            }
C
Corey Richardson 已提交
1687
        }
1688
        generics
C
Corey Richardson 已提交
1689 1690 1691
    }
}

1692
impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
1693
                                    &'a Lrc<ty::GenericPredicates<'tcx>>) {
1694
    fn clean(&self, cx: &DocContext<'_>) -> Generics {
1695 1696
        use self::WherePredicate as WP;

1697
        let (gens, preds) = *self;
1698

1699 1700 1701
        // Bounds in the type_params and lifetimes fields are repeated in the
        // predicates field (see rustc_typeck::collect::ty_generics), so remove
        // them.
1702 1703 1704
        let stripped_typarams = gens.params.iter().filter_map(|param| match param.kind {
            ty::GenericParamDefKind::Lifetime => None,
            ty::GenericParamDefKind::Type { .. } => {
1705
                if param.name.as_symbol() == keywords::SelfUpper.name() {
1706
                    assert_eq!(param.index, 0);
1707
                    return None;
V
varkor 已提交
1708
                }
1709
                Some(param.clean(cx))
1710
            }
1711
            ty::GenericParamDefKind::Const { .. } => None,
1712
        }).collect::<Vec<GenericParamDef>>();
1713

1714
        let mut where_predicates = preds.predicates.iter()
1715
            .flat_map(|(p, _)| p.clean(cx))
1716
            .collect::<Vec<_>>();
1717

1718
        // Type parameters and have a Sized bound by default unless removed with
1719
        // ?Sized. Scan through the predicates and mark any type parameter with
1720
        // a Sized bound, removing the bounds as we find them.
1721 1722
        //
        // Note that associated types also have a sized bound by default, but we
1723
        // don't actually know the set of associated types right here so that's
1724
        // handled in cleaning associated types
1725
        let mut sized_params = FxHashSet::default();
1726 1727 1728 1729 1730 1731 1732 1733 1734
        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
                    }
1735
                }
1736
                _ => true,
1737
            }
1738
        });
1739

1740
        // Run through the type parameters again and insert a ?Sized
1741
        // unbound for any we didn't find to be Sized.
1742
        for tp in &stripped_typarams {
1743 1744 1745
            if !sized_params.contains(&tp.name) {
                where_predicates.push(WP::BoundPredicate {
                    ty: Type::Generic(tp.name.clone()),
V
varkor 已提交
1746
                    bounds: vec![GenericBound::maybe_sized(cx)],
1747 1748 1749 1750 1751
                })
            }
        }

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

1755
        Generics {
V
varkor 已提交
1756 1757
            params: gens.params
                        .iter()
1758
                        .flat_map(|param| match param.kind {
1759
                            ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
1760
                            ty::GenericParamDefKind::Type { .. } => None,
1761
                            ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)),
1762
                        }).chain(simplify::ty_params(stripped_typarams).into_iter())
V
varkor 已提交
1763
                        .collect(),
1764
            where_predicates: simplify::where_clauses(cx, where_predicates),
1765 1766 1767 1768
        }
    }
}

G
cleanup  
Guillaume Gomez 已提交
1769 1770 1771 1772 1773
/// The point of this function is to replace bounds with types.
///
/// i.e. `[T, U]` when you have the following bounds: `T: Display, U: Option<T>` will return
/// `[Display, Option]` (we just returns the list of the types, we don't care about the
/// wrapped types in here).
1774
fn get_real_types(
1775 1776
    generics: &Generics,
    arg: &Type,
G
cleanup  
Guillaume Gomez 已提交
1777
    cx: &DocContext<'_>,
G
Guillaume Gomez 已提交
1778
    recurse: i32,
G
cleanup  
Guillaume Gomez 已提交
1779
) -> FxHashSet<Type> {
1780
    let arg_s = arg.to_string();
G
Guillaume Gomez 已提交
1781
    let mut res = FxHashSet::default();
G
Guillaume Gomez 已提交
1782 1783 1784
    if recurse >= 10 { // FIXME: remove this whole recurse thing when the recursion bug is fixed
        return res;
    }
1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800
    if arg.is_full_generic() {
        if let Some(where_pred) = generics.where_predicates.iter().find(|g| {
            match g {
                &WherePredicate::BoundPredicate { ref ty, .. } => ty.def_id() == arg.def_id(),
                _ => false,
            }
        }) {
            let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]);
            for bound in bounds.iter() {
                match *bound {
                    GenericBound::TraitBound(ref poly_trait, _) => {
                        for x in poly_trait.generic_params.iter() {
                            if !x.is_type() {
                                continue
                            }
                            if let Some(ty) = x.get_type(cx) {
G
Guillaume Gomez 已提交
1801
                                let adds = get_real_types(generics, &ty, cx, recurse + 1);
1802
                                if !adds.is_empty() {
G
cleanup  
Guillaume Gomez 已提交
1803
                                    res.extend(adds);
1804
                                } else if !ty.is_full_generic() {
G
Guillaume Gomez 已提交
1805
                                    res.insert(ty);
1806
                                }
1807 1808 1809
                            }
                        }
                    }
1810
                    _ => {}
1811 1812 1813 1814 1815 1816 1817 1818
                }
            }
        }
        if let Some(bound) = generics.params.iter().find(|g| {
            g.is_type() && g.name == arg_s
        }) {
            for bound in bound.get_bounds().unwrap_or_else(|| &[]) {
                if let Some(ty) = bound.get_trait_type() {
G
Guillaume Gomez 已提交
1819
                    let adds = get_real_types(generics, &ty, cx, recurse + 1);
1820
                    if !adds.is_empty() {
G
cleanup  
Guillaume Gomez 已提交
1821
                        res.extend(adds);
1822
                    } else if !ty.is_full_generic() {
G
Guillaume Gomez 已提交
1823
                        res.insert(ty.clone());
1824 1825 1826
                    }
                }
            }
1827 1828
        }
    } else {
G
Guillaume Gomez 已提交
1829
        res.insert(arg.clone());
1830
        if let Some(gens) = arg.generics() {
1831 1832
            for gen in gens.iter() {
                if gen.is_full_generic() {
G
Guillaume Gomez 已提交
1833
                    let adds = get_real_types(generics, gen, cx, recurse + 1);
1834
                    if !adds.is_empty() {
G
cleanup  
Guillaume Gomez 已提交
1835
                        res.extend(adds);
1836 1837
                    }
                } else {
G
Guillaume Gomez 已提交
1838
                    res.insert(gen.clone());
1839 1840 1841 1842
                }
            }
        }
    }
1843
    res
1844 1845
}

G
cleanup  
Guillaume Gomez 已提交
1846 1847 1848 1849
/// Return the full list of types when bounds have been resolved.
///
/// i.e. `fn foo<A: Display, B: Option<A>>(x: u32, y: B)` will return
/// `[u32, Display, Option]`.
1850 1851 1852
pub fn get_all_types(
    generics: &Generics,
    decl: &FnDecl,
G
cleanup  
Guillaume Gomez 已提交
1853
    cx: &DocContext<'_>,
1854
) -> (Vec<Type>, Vec<Type>) {
G
Guillaume Gomez 已提交
1855
    let mut all_types = FxHashSet::default();
1856 1857 1858 1859
    for arg in decl.inputs.values.iter() {
        if arg.type_.is_self_type() {
            continue;
        }
G
Guillaume Gomez 已提交
1860
        let args = get_real_types(generics, &arg.type_, cx, 0);
1861
        if !args.is_empty() {
G
cleanup  
Guillaume Gomez 已提交
1862
            all_types.extend(args);
1863
        } else {
G
Guillaume Gomez 已提交
1864
            all_types.insert(arg.type_.clone());
1865 1866
        }
    }
1867

G
Guillaume Gomez 已提交
1868
    let ret_types = match decl.output {
1869
        FunctionRetTy::Return(ref return_type) => {
G
Guillaume Gomez 已提交
1870
            let mut ret = get_real_types(generics, &return_type, cx, 0);
1871
            if ret.is_empty() {
G
Guillaume Gomez 已提交
1872
                ret.insert(return_type.clone());
1873
            }
G
Guillaume Gomez 已提交
1874
            ret.into_iter().collect()
1875 1876 1877
        }
        _ => Vec::new(),
    };
G
Guillaume Gomez 已提交
1878
    (all_types.into_iter().collect(), ret_types)
1879 1880
}

J
Jorge Aparicio 已提交
1881
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1882
pub struct Method {
1883 1884
    pub generics: Generics,
    pub decl: FnDecl,
W
Without Boats 已提交
1885
    pub header: hir::FnHeader,
1886
    pub defaultness: Option<hir::Defaultness>,
1887
    pub all_types: Vec<Type>,
1888
    pub ret_types: Vec<Type>,
C
Corey Richardson 已提交
1889 1890
}

1891 1892
impl<'a> Clean<Method> for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId,
                            Option<hir::Defaultness>) {
1893
    fn clean(&self, cx: &DocContext<'_>) -> Method {
1894 1895 1896
        let (generics, decl) = enter_impl_trait(cx, || {
            (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx))
        });
1897
        let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
1898
        Method {
1899
            decl,
1900
            generics,
W
Without Boats 已提交
1901
            header: self.0.header,
1902
            defaultness: self.3,
1903
            all_types,
1904
            ret_types,
C
Corey Richardson 已提交
1905 1906 1907 1908
        }
    }
}

J
Jorge Aparicio 已提交
1909
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1910
pub struct TyMethod {
W
Without Boats 已提交
1911
    pub header: hir::FnHeader,
1912 1913
    pub decl: FnDecl,
    pub generics: Generics,
1914
    pub all_types: Vec<Type>,
1915
    pub ret_types: Vec<Type>,
C
Corey Richardson 已提交
1916 1917
}

J
Jorge Aparicio 已提交
1918
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
1919
pub struct Function {
1920 1921
    pub decl: FnDecl,
    pub generics: Generics,
W
Without Boats 已提交
1922
    pub header: hir::FnHeader,
1923
    pub all_types: Vec<Type>,
1924
    pub ret_types: Vec<Type>,
C
Corey Richardson 已提交
1925 1926 1927
}

impl Clean<Item> for doctree::Function {
1928
    fn clean(&self, cx: &DocContext<'_>) -> Item {
1929 1930 1931
        let (generics, decl) = enter_impl_trait(cx, || {
            (self.generics.clean(cx), (&self.decl, self.body).clean(cx))
        });
G
Guillaume Gomez 已提交
1932

L
ljedrz 已提交
1933
        let did = cx.tcx.hir().local_def_id_from_hir_id(self.id);
G
Guillaume Gomez 已提交
1934 1935 1936 1937 1938
        let constness = if cx.tcx.is_min_const_fn(did) {
            hir::Constness::Const
        } else {
            hir::Constness::NotConst
        };
1939
        let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
C
Corey Richardson 已提交
1940
        Item {
1941 1942 1943 1944 1945
            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),
1946
            deprecation: self.depr.clean(cx),
G
Guillaume Gomez 已提交
1947
            def_id: did,
C
Corey Richardson 已提交
1948
            inner: FunctionItem(Function {
1949 1950
                decl,
                generics,
G
Guillaume Gomez 已提交
1951
                header: hir::FnHeader { constness, ..self.header },
1952
                all_types,
1953
                ret_types,
C
Corey Richardson 已提交
1954 1955 1956 1957 1958
            }),
        }
    }
}

1959
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
C
Corey Richardson 已提交
1960
pub struct FnDecl {
1961
    pub inputs: Arguments,
1962
    pub output: FunctionRetTy,
1963
    pub attrs: Attributes,
1964
}
C
Corey Richardson 已提交
1965

1966
impl FnDecl {
1967 1968 1969
    pub fn self_type(&self) -> Option<SelfTy> {
        self.inputs.values.get(0).and_then(|v| v.to_self())
    }
1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993

    /// Returns the sugared return type for an async function.
    ///
    /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
    /// will return `i32`.
    ///
    /// # Panics
    ///
    /// This function will panic if the return type does not match the expected sugaring for async
    /// functions.
    pub fn sugared_async_return_type(&self) -> FunctionRetTy {
        match &self.output {
            FunctionRetTy::Return(Type::ImplTrait(bounds)) => {
                match &bounds[0] {
                    GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
                        let bindings = trait_.bindings().unwrap();
                        FunctionRetTy::Return(bindings[0].ty.clone())
                    }
                    _ => panic!("unexpected desugaring of async function"),
                }
            }
            _ => panic!("unexpected desugaring of async function"),
        }
    }
1994 1995
}

1996
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1997
pub struct Arguments {
1998
    pub values: Vec<Argument>,
1999 2000
}

2001
impl<'a> Clean<Arguments> for (&'a [hir::Ty], &'a [ast::Ident]) {
2002
    fn clean(&self, cx: &DocContext<'_>) -> Arguments {
2003 2004
        Arguments {
            values: self.0.iter().enumerate().map(|(i, ty)| {
2005
                let mut name = self.1.get(i).map(|ident| ident.to_string())
2006 2007 2008 2009 2010
                                            .unwrap_or(String::new());
                if name.is_empty() {
                    name = "_".to_string();
                }
                Argument {
2011
                    name,
2012 2013 2014 2015 2016 2017 2018
                    type_: ty.clean(cx),
                }
            }).collect()
        }
    }
}

O
Oliver Schneider 已提交
2019
impl<'a> Clean<Arguments> for (&'a [hir::Ty], hir::BodyId) {
2020
    fn clean(&self, cx: &DocContext<'_>) -> Arguments {
2021
        let body = cx.tcx.hir().body(self.1);
2022 2023 2024 2025

        Arguments {
            values: self.0.iter().enumerate().map(|(i, ty)| {
                Argument {
2026
                    name: name_from_pat(&body.arguments[i].original_pat()),
2027 2028 2029 2030 2031 2032 2033 2034
                    type_: ty.clean(cx),
                }
            }).collect()
        }
    }
}

impl<'a, A: Copy> Clean<FnDecl> for (&'a hir::FnDecl, A)
O
Oliver Schneider 已提交
2035
    where (&'a [hir::Ty], A): Clean<Arguments>
2036
{
2037
    fn clean(&self, cx: &DocContext<'_>) -> FnDecl {
C
Corey Richardson 已提交
2038
        FnDecl {
2039 2040
            inputs: (&self.0.inputs[..], self.1).clean(cx),
            output: self.0.output.clean(cx),
2041
            attrs: Attributes::default(),
C
Corey Richardson 已提交
2042 2043 2044 2045
        }
    }
}

2046
impl<'a, 'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
2047
    fn clean(&self, cx: &DocContext<'_>) -> FnDecl {
2048
        let (did, sig) = *self;
2049
        let mut names = if cx.tcx.hir().as_local_hir_id(did).is_some() {
2050
            vec![].into_iter()
2051
        } else {
A
achernyak 已提交
2052
            cx.tcx.fn_arg_names(did).into_iter()
S
Cleanup  
Shotaro Yamada 已提交
2053 2054
        };

2055
        FnDecl {
2056
            output: Return(sig.skip_binder().output().clean(cx)),
2057
            attrs: Attributes::default(),
2058
            inputs: Arguments {
2059
                values: sig.skip_binder().inputs().iter().map(|t| {
2060
                    Argument {
2061
                        type_: t.clean(cx),
2062
                        name: names.next().map_or(String::new(), |name| name.to_string()),
2063 2064 2065 2066 2067 2068 2069
                    }
                }).collect(),
            },
        }
    }
}

2070
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
C
Corey Richardson 已提交
2071
pub struct Argument {
2072
    pub type_: Type,
2073
    pub name: String,
C
Corey Richardson 已提交
2074 2075
}

2076 2077 2078 2079 2080 2081 2082 2083 2084
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
pub enum SelfTy {
    SelfValue,
    SelfBorrowed(Option<Lifetime>, Mutability),
    SelfExplicit(Type),
}

impl Argument {
    pub fn to_self(&self) -> Option<SelfTy> {
2085 2086 2087 2088 2089 2090 2091 2092 2093
        if self.name != "self" {
            return None;
        }
        if self.type_.is_self_type() {
            return Some(SelfValue);
        }
        match self.type_ {
            BorrowedRef{ref lifetime, mutability, ref type_} if type_.is_self_type() => {
                Some(SelfBorrowed(lifetime.clone(), mutability))
2094
            }
2095
            _ => Some(SelfExplicit(self.type_.clone()))
2096 2097 2098 2099
        }
    }
}

2100
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
2101 2102
pub enum FunctionRetTy {
    Return(Type),
2103
    DefaultReturn,
C
Corey Richardson 已提交
2104 2105
}

2106
impl Clean<FunctionRetTy> for hir::FunctionRetTy {
2107
    fn clean(&self, cx: &DocContext<'_>) -> FunctionRetTy {
C
Corey Richardson 已提交
2108
        match *self {
2109 2110
            hir::Return(ref typ) => Return(typ.clean(cx)),
            hir::DefaultReturn(..) => DefaultReturn,
C
Corey Richardson 已提交
2111 2112 2113 2114
        }
    }
}

2115 2116 2117 2118 2119 2120 2121 2122 2123
impl GetDefId for FunctionRetTy {
    fn def_id(&self) -> Option<DefId> {
        match *self {
            Return(ref ty) => ty.def_id(),
            DefaultReturn => None,
        }
    }
}

J
Jorge Aparicio 已提交
2124
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
2125
pub struct Trait {
2126
    pub auto: bool,
2127
    pub unsafety: hir::Unsafety,
2128
    pub items: Vec<Item>,
2129
    pub generics: Generics,
V
varkor 已提交
2130
    pub bounds: Vec<GenericBound>,
2131
    pub is_spotlight: bool,
2132
    pub is_auto: bool,
C
Corey Richardson 已提交
2133 2134 2135
}

impl Clean<Item> for doctree::Trait {
2136
    fn clean(&self, cx: &DocContext<'_>) -> Item {
2137
        let attrs = self.attrs.clean(cx);
2138
        let is_spotlight = attrs.has_doc_flag(sym::spotlight);
C
Corey Richardson 已提交
2139
        Item {
2140
            name: Some(self.name.clean(cx)),
2141
            attrs: attrs,
2142
            source: self.whence.clean(cx),
L
ljedrz 已提交
2143
            def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
2144 2145
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
2146
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
2147
            inner: TraitItem(Trait {
2148
                auto: self.is_auto.clean(cx),
2149
                unsafety: self.unsafety,
2150 2151 2152
                items: self.items.clean(cx),
                generics: self.generics.clean(cx),
                bounds: self.bounds.clean(cx),
2153
                is_spotlight,
2154
                is_auto: self.is_auto.clean(cx),
C
Corey Richardson 已提交
2155 2156 2157 2158 2159
            }),
        }
    }
}

2160 2161 2162 2163 2164 2165 2166
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct TraitAlias {
    pub generics: Generics,
    pub bounds: Vec<GenericBound>,
}

impl Clean<Item> for doctree::TraitAlias {
2167
    fn clean(&self, cx: &DocContext<'_>) -> Item {
2168 2169 2170 2171 2172
        let attrs = self.attrs.clean(cx);
        Item {
            name: Some(self.name.clean(cx)),
            attrs,
            source: self.whence.clean(cx),
L
ljedrz 已提交
2173
            def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
            deprecation: self.depr.clean(cx),
            inner: TraitAliasItem(TraitAlias {
                generics: self.generics.clean(cx),
                bounds: self.bounds.clean(cx),
            }),
        }
    }
}

2185
impl Clean<bool> for hir::IsAuto {
2186
    fn clean(&self, _: &DocContext<'_>) -> bool {
2187 2188 2189 2190 2191 2192 2193
        match *self {
            hir::IsAuto::Yes => true,
            hir::IsAuto::No => false,
        }
    }
}

2194
impl Clean<Type> for hir::TraitRef {
2195
    fn clean(&self, cx: &DocContext<'_>) -> Type {
L
ljedrz 已提交
2196
        resolve_type(cx, self.path.clean(cx), self.hir_ref_id)
C
Corey Richardson 已提交
2197 2198 2199
    }
}

2200
impl Clean<PolyTrait> for hir::PolyTraitRef {
2201
    fn clean(&self, cx: &DocContext<'_>) -> PolyTrait {
2202 2203
        PolyTrait {
            trait_: self.trait_ref.clean(cx),
2204
            generic_params: self.bound_generic_params.clean(cx)
2205
        }
N
Niko Matsakis 已提交
2206 2207 2208
    }
}

2209
impl Clean<Item> for hir::TraitItem {
2210
    fn clean(&self, cx: &DocContext<'_>) -> Item {
2211
        let inner = match self.node {
2212
            hir::TraitItemKind::Const(ref ty, default) => {
2213
                AssociatedConstItem(ty.clean(cx),
2214
                                    default.map(|e| print_const_expr(cx, e)))
2215
            }
2216
            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
2217
                MethodItem((sig, &self.generics, body, None).clean(cx))
2218
            }
2219
            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => {
2220 2221 2222
                let (generics, decl) = enter_impl_trait(cx, || {
                    (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
                });
2223
                let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
2224
                TyMethodItem(TyMethod {
W
Without Boats 已提交
2225
                    header: sig.header,
2226
                    decl,
2227
                    generics,
2228
                    all_types,
2229
                    ret_types,
2230
                })
2231
            }
2232
            hir::TraitItemKind::Type(ref bounds, ref default) => {
2233 2234 2235
                AssociatedTypeItem(bounds.clean(cx), default.clean(cx))
            }
        };
L
ljedrz 已提交
2236
        let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);
2237
        Item {
2238
            name: Some(self.ident.name.clean(cx)),
2239 2240
            attrs: self.attrs.clean(cx),
            source: self.span.clean(cx),
L
ljedrz 已提交
2241
            def_id: local_did,
2242
            visibility: None,
L
ljedrz 已提交
2243 2244
            stability: get_stability(cx, local_did),
            deprecation: get_deprecation(cx, local_did),
2245
            inner,
2246 2247 2248 2249
        }
    }
}

2250
impl Clean<Item> for hir::ImplItem {
2251
    fn clean(&self, cx: &DocContext<'_>) -> Item {
2252
        let inner = match self.node {
2253
            hir::ImplItemKind::Const(ref ty, expr) => {
2254
                AssociatedConstItem(ty.clean(cx),
2255
                                    Some(print_const_expr(cx, expr)))
2256
            }
2257
            hir::ImplItemKind::Method(ref sig, body) => {
2258
                MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx))
2259
            }
2260
            hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef {
2261
                type_: ty.clean(cx),
2262
                generics: Generics::default(),
2263
            }, true),
O
Oliver Schneider 已提交
2264 2265 2266 2267
            hir::ImplItemKind::Existential(ref bounds) => ExistentialItem(Existential {
                bounds: bounds.clean(cx),
                generics: Generics::default(),
            }, true),
2268
        };
L
ljedrz 已提交
2269
        let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);
2270
        Item {
2271
            name: Some(self.ident.name.clean(cx)),
2272 2273
            source: self.span.clean(cx),
            attrs: self.attrs.clean(cx),
L
ljedrz 已提交
2274
            def_id: local_did,
2275
            visibility: self.vis.clean(cx),
L
ljedrz 已提交
2276 2277
            stability: get_stability(cx, local_did),
            deprecation: get_deprecation(cx, local_did),
2278
            inner,
C
Corey Richardson 已提交
2279 2280 2281 2282
        }
    }
}

2283
impl<'tcx> Clean<Item> for ty::AssociatedItem {
2284
    fn clean(&self, cx: &DocContext<'_>) -> Item {
2285 2286
        let inner = match self.kind {
            ty::AssociatedKind::Const => {
2287
                let ty = cx.tcx.type_of(self.def_id);
2288 2289 2290 2291 2292 2293
                let default = if self.defaultness.has_value() {
                    Some(inline::print_inlined_const(cx, self.def_id))
                } else {
                    None
                };
                AssociatedConstItem(ty.clean(cx), default)
2294
            }
2295
            ty::AssociatedKind::Method => {
2296
                let generics = (cx.tcx.generics_of(self.def_id),
2297
                                &cx.tcx.explicit_predicates_of(self.def_id)).clean(cx);
2298
                let sig = cx.tcx.fn_sig(self.def_id);
2299
                let mut decl = (self.def_id, sig).clean(cx);
2300 2301 2302 2303

                if self.method_has_self_argument {
                    let self_ty = match self.container {
                        ty::ImplContainer(def_id) => {
2304
                            cx.tcx.type_of(def_id)
2305
                        }
2306
                        ty::TraitContainer(_) => cx.tcx.mk_self_type()
2307
                    };
2308
                    let self_arg_ty = *sig.input(0).skip_binder();
2309
                    if self_arg_ty == self_ty {
2310
                        decl.inputs.values[0].type_ = Generic(String::from("Self"));
V
varkor 已提交
2311
                    } else if let ty::Ref(_, ty, _) = self_arg_ty.sty {
2312
                        if ty == self_ty {
2313
                            match decl.inputs.values[0].type_ {
2314 2315 2316
                                BorrowedRef{ref mut type_, ..} => {
                                    **type_ = Generic(String::from("Self"))
                                }
2317 2318 2319 2320 2321
                                _ => unreachable!(),
                            }
                        }
                    }
                }
2322

2323
                let provided = match self.container {
2324
                    ty::ImplContainer(_) => true,
2325
                    ty::TraitContainer(_) => self.defaultness.has_value()
2326
                };
2327
                let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
2328
                if provided {
2329
                    let constness = if cx.tcx.is_min_const_fn(self.def_id) {
2330 2331 2332 2333
                        hir::Constness::Const
                    } else {
                        hir::Constness::NotConst
                    };
2334 2335 2336 2337
                    let defaultness = match self.container {
                        ty::ImplContainer(_) => Some(self.defaultness),
                        ty::TraitContainer(_) => None,
                    };
2338
                    MethodItem(Method {
2339 2340
                        generics,
                        decl,
W
Without Boats 已提交
2341 2342 2343 2344
                        header: hir::FnHeader {
                            unsafety: sig.unsafety(),
                            abi: sig.abi(),
                            constness,
2345
                            asyncness: hir::IsAsync::NotAsync,
2346
                        },
2347
                        defaultness,
2348
                        all_types,
2349
                        ret_types,
2350 2351 2352
                    })
                } else {
                    TyMethodItem(TyMethod {
2353 2354
                        generics,
                        decl,
W
Without Boats 已提交
2355 2356 2357
                        header: hir::FnHeader {
                            unsafety: sig.unsafety(),
                            abi: sig.abi(),
2358 2359
                            constness: hir::Constness::NotConst,
                            asyncness: hir::IsAsync::NotAsync,
2360 2361
                        },
                        all_types,
2362
                        ret_types,
2363
                    })
2364 2365
                }
            }
2366
            ty::AssociatedKind::Type => {
2367
                let my_name = self.ident.name.clean(cx);
2368

2369
                if let ty::TraitContainer(did) = self.container {
2370 2371 2372 2373
                    // 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.
2374
                    let predicates = cx.tcx.explicit_predicates_of(did);
2375
                    let generics = (cx.tcx.generics_of(did), &predicates).clean(cx);
2376
                    let mut bounds = generics.where_predicates.iter().filter_map(|pred| {
2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393
                        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)
2394 2395 2396 2397 2398 2399 2400 2401
                    }).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>();
                    // 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); }
V
varkor 已提交
2402
                        None => bounds.push(GenericBound::maybe_sized(cx)),
2403
                    }
2404

2405 2406 2407 2408 2409
                    let ty = if self.defaultness.has_value() {
                        Some(cx.tcx.type_of(self.def_id))
                    } else {
                        None
                    };
2410

2411
                    AssociatedTypeItem(bounds, ty.clean(cx))
2412
                } else {
2413 2414 2415
                    TypedefItem(Typedef {
                        type_: cx.tcx.type_of(self.def_id).clean(cx),
                        generics: Generics {
2416
                            params: Vec::new(),
2417 2418 2419 2420
                            where_predicates: Vec::new(),
                        },
                    }, true)
                }
2421
            }
O
Oliver Schneider 已提交
2422
            ty::AssociatedKind::Existential => unimplemented!(),
2423 2424
        };

2425 2426 2427 2428 2429
        let visibility = match self.container {
            ty::ImplContainer(_) => self.vis.clean(cx),
            ty::TraitContainer(_) => None,
        };

2430
        Item {
2431
            name: Some(self.ident.name.clean(cx)),
2432
            visibility,
2433
            stability: get_stability(cx, self.def_id),
2434
            deprecation: get_deprecation(cx, self.def_id),
2435
            def_id: self.def_id,
2436
            attrs: inline::load_attrs(cx, self.def_id),
2437
            source: cx.tcx.def_span(self.def_id).clean(cx),
2438
            inner,
2439
        }
2440 2441 2442
    }
}

2443
/// A trait reference, which may have higher ranked lifetimes.
2444
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
2445 2446
pub struct PolyTrait {
    pub trait_: Type,
V
varkor 已提交
2447
    pub generic_params: Vec<GenericParamDef>,
2448 2449
}

C
Corey Richardson 已提交
2450
/// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
2451
/// type out of the AST/TyCtxt given one of these, if more information is needed. Most importantly
C
Corey Richardson 已提交
2452
/// it does not preserve mutability or boxes.
2453
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
C
Corey Richardson 已提交
2454
pub enum Type {
A
Alexander Regueiro 已提交
2455
    /// Structs/enums/traits (most that'd be an `hir::TyKind::Path`).
2456
    ResolvedPath {
S
Steven Fackler 已提交
2457
        path: Path,
V
varkor 已提交
2458
        param_names: Option<Vec<GenericBound>>,
N
Niko Matsakis 已提交
2459
        did: DefId,
A
Alexander Regueiro 已提交
2460
        /// `true` if is a `T::Name` path for associated types.
2461
        is_generic: bool,
2462
    },
2463 2464 2465
    /// For parameterized types, so the consumer of the JSON don't go
    /// looking for types which don't exist anywhere.
    Generic(String),
2466
    /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
2467
    /// arrays, slices, and tuples.
2468
    Primitive(PrimitiveType),
C
Corey Richardson 已提交
2469
    /// extern "ABI" fn
2470
    BareFunction(Box<BareFunctionDecl>),
2471
    Tuple(Vec<Type>),
2472
    Slice(Box<Type>),
2473
    Array(Box<Type>, String),
A
Andrew Cann 已提交
2474
    Never,
2475
    CVarArgs,
2476 2477
    Unique(Box<Type>),
    RawPointer(Mutability, Box<Type>),
2478
    BorrowedRef {
S
Steven Fackler 已提交
2479 2480 2481
        lifetime: Option<Lifetime>,
        mutability: Mutability,
        type_: Box<Type>,
2482
    },
2483 2484

    // <Type as Trait>::Name
T
Tom Jakubowski 已提交
2485 2486 2487 2488 2489
    QPath {
        name: String,
        self_type: Box<Type>,
        trait_: Box<Type>
    },
2490 2491 2492 2493

    // _
    Infer,

2494
    // impl TraitA+TraitB
V
varkor 已提交
2495
    ImplTrait(Vec<GenericBound>),
C
Corey Richardson 已提交
2496 2497
}

J
Jorge Aparicio 已提交
2498
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
2499
pub enum PrimitiveType {
2500 2501
    Isize, I8, I16, I32, I64, I128,
    Usize, U8, U16, U32, U64, U128,
2502
    F32, F64,
2503 2504 2505 2506
    Char,
    Bool,
    Str,
    Slice,
2507
    Array,
2508
    Tuple,
2509
    Unit,
2510
    RawPointer,
2511
    Reference,
2512
    Fn,
A
Andrew Cann 已提交
2513
    Never,
2514
    CVarArgs,
2515 2516
}

J
Jorge Aparicio 已提交
2517
#[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
2518
pub enum TypeKind {
2519 2520 2521 2522 2523 2524 2525 2526 2527 2528
    Enum,
    Function,
    Module,
    Const,
    Static,
    Struct,
    Union,
    Trait,
    Variant,
    Typedef,
P
Paul Lietar 已提交
2529
    Foreign,
M
Manish Goregaokar 已提交
2530
    Macro,
2531 2532
    Attr,
    Derive,
2533
    TraitAlias,
2534 2535
}

2536 2537 2538 2539 2540 2541 2542 2543 2544 2545
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())
    }
}

2546 2547 2548 2549
impl Type {
    pub fn primitive_type(&self) -> Option<PrimitiveType> {
        match *self {
            Primitive(p) | BorrowedRef { type_: box Primitive(p), ..} => Some(p),
2550 2551
            Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
            Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
2552 2553 2554 2555 2556
            Tuple(ref tys) => if tys.is_empty() {
                Some(PrimitiveType::Unit)
            } else {
                Some(PrimitiveType::Tuple)
            },
2557
            RawPointer(..) => Some(PrimitiveType::RawPointer),
2558
            BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
2559
            BareFunction(..) => Some(PrimitiveType::Fn),
A
Andrew Cann 已提交
2560
            Never => Some(PrimitiveType::Never),
2561 2562 2563
            _ => None,
        }
    }
2564

2565 2566 2567 2568 2569 2570
    pub fn is_generic(&self) -> bool {
        match *self {
            ResolvedPath { is_generic, .. } => is_generic,
            _ => false,
        }
    }
2571 2572 2573 2574 2575 2576 2577

    pub fn is_self_type(&self) -> bool {
        match *self {
            Generic(ref name) => name == "Self",
            _ => false
        }
    }
2578

2579
    pub fn generics(&self) -> Option<Vec<Type>> {
2580 2581 2582
        match *self {
            ResolvedPath { ref path, .. } => {
                path.segments.last().and_then(|seg| {
2583 2584 2585 2586 2587
                    if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
                        Some(args.iter().filter_map(|arg| match arg {
                            GenericArg::Type(ty) => Some(ty.clone()),
                            _ => None,
                        }).collect())
2588 2589 2590 2591 2592 2593 2594 2595
                    } else {
                        None
                    }
                })
            }
            _ => None,
        }
    }
2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610

    pub fn bindings(&self) -> Option<&[TypeBinding]> {
        match *self {
            ResolvedPath { ref path, .. } => {
                path.segments.last().and_then(|seg| {
                    if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
                        Some(&**bindings)
                    } else {
                        None
                    }
                })
            }
            _ => None
        }
    }
2611 2612 2613 2614 2615 2616 2617

    pub fn is_full_generic(&self) -> bool {
        match *self {
            Type::Generic(_) => true,
            _ => false,
        }
    }
2618
}
2619

2620
impl GetDefId for Type {
2621 2622 2623
    fn def_id(&self) -> Option<DefId> {
        match *self {
            ResolvedPath { did, .. } => Some(did),
2624
            Primitive(p) => crate::html::render::cache().primitive_locations.get(&p).cloned(),
2625 2626 2627
            BorrowedRef { type_: box Generic(..), .. } =>
                Primitive(PrimitiveType::Reference).def_id(),
            BorrowedRef { ref type_, .. } => type_.def_id(),
2628 2629 2630 2631 2632
            Tuple(ref tys) => if tys.is_empty() {
                Primitive(PrimitiveType::Unit).def_id()
            } else {
                Primitive(PrimitiveType::Tuple).def_id()
            },
2633
            BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
A
Andrew Cann 已提交
2634
            Never => Primitive(PrimitiveType::Never).def_id(),
2635 2636 2637 2638
            Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
            Array(..) => Primitive(PrimitiveType::Array).def_id(),
            RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(),
            QPath { ref self_type, .. } => self_type.def_id(),
2639 2640 2641
            _ => None,
        }
    }
2642 2643
}

2644 2645
impl PrimitiveType {
    fn from_str(s: &str) -> Option<PrimitiveType> {
2646
        match s {
2647 2648 2649 2650 2651
            "isize" => Some(PrimitiveType::Isize),
            "i8" => Some(PrimitiveType::I8),
            "i16" => Some(PrimitiveType::I16),
            "i32" => Some(PrimitiveType::I32),
            "i64" => Some(PrimitiveType::I64),
2652
            "i128" => Some(PrimitiveType::I128),
2653 2654 2655 2656 2657
            "usize" => Some(PrimitiveType::Usize),
            "u8" => Some(PrimitiveType::U8),
            "u16" => Some(PrimitiveType::U16),
            "u32" => Some(PrimitiveType::U32),
            "u64" => Some(PrimitiveType::U64),
2658
            "u128" => Some(PrimitiveType::U128),
2659 2660 2661 2662 2663 2664 2665
            "bool" => Some(PrimitiveType::Bool),
            "char" => Some(PrimitiveType::Char),
            "str" => Some(PrimitiveType::Str),
            "f32" => Some(PrimitiveType::F32),
            "f64" => Some(PrimitiveType::F64),
            "array" => Some(PrimitiveType::Array),
            "slice" => Some(PrimitiveType::Slice),
2666
            "tuple" => Some(PrimitiveType::Tuple),
2667
            "unit" => Some(PrimitiveType::Unit),
2668
            "pointer" => Some(PrimitiveType::RawPointer),
2669
            "reference" => Some(PrimitiveType::Reference),
2670
            "fn" => Some(PrimitiveType::Fn),
A
Andrew Cann 已提交
2671
            "never" => Some(PrimitiveType::Never),
2672 2673 2674 2675
            _ => None,
        }
    }

2676
    pub fn as_str(&self) -> &'static str {
E
est31 已提交
2677
        use self::PrimitiveType::*;
2678
        match *self {
2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698
            Isize => "isize",
            I8 => "i8",
            I16 => "i16",
            I32 => "i32",
            I64 => "i64",
            I128 => "i128",
            Usize => "usize",
            U8 => "u8",
            U16 => "u16",
            U32 => "u32",
            U64 => "u64",
            U128 => "u128",
            F32 => "f32",
            F64 => "f64",
            Str => "str",
            Bool => "bool",
            Char => "char",
            Array => "array",
            Slice => "slice",
            Tuple => "tuple",
2699
            Unit => "unit",
2700
            RawPointer => "pointer",
2701
            Reference => "reference",
2702
            Fn => "fn",
A
Andrew Cann 已提交
2703
            Never => "never",
2704
            CVarArgs => "...",
2705 2706 2707 2708
        }
    }

    pub fn to_url_str(&self) -> &'static str {
2709
        self.as_str()
2710 2711 2712
    }
}

2713 2714 2715
impl From<ast::IntTy> for PrimitiveType {
    fn from(int_ty: ast::IntTy) -> PrimitiveType {
        match int_ty {
2716
            ast::IntTy::Isize => PrimitiveType::Isize,
2717 2718 2719 2720
            ast::IntTy::I8 => PrimitiveType::I8,
            ast::IntTy::I16 => PrimitiveType::I16,
            ast::IntTy::I32 => PrimitiveType::I32,
            ast::IntTy::I64 => PrimitiveType::I64,
2721
            ast::IntTy::I128 => PrimitiveType::I128,
2722 2723 2724
        }
    }
}
2725

2726 2727 2728
impl From<ast::UintTy> for PrimitiveType {
    fn from(uint_ty: ast::UintTy) -> PrimitiveType {
        match uint_ty {
2729
            ast::UintTy::Usize => PrimitiveType::Usize,
2730 2731 2732 2733
            ast::UintTy::U8 => PrimitiveType::U8,
            ast::UintTy::U16 => PrimitiveType::U16,
            ast::UintTy::U32 => PrimitiveType::U32,
            ast::UintTy::U64 => PrimitiveType::U64,
2734
            ast::UintTy::U128 => PrimitiveType::U128,
2735 2736 2737 2738
        }
    }
}

2739 2740 2741 2742 2743 2744 2745 2746 2747
impl From<ast::FloatTy> for PrimitiveType {
    fn from(float_ty: ast::FloatTy) -> PrimitiveType {
        match float_ty {
            ast::FloatTy::F32 => PrimitiveType::F32,
            ast::FloatTy::F64 => PrimitiveType::F64,
        }
    }
}

2748
impl Clean<Type> for hir::Ty {
2749
    fn clean(&self, cx: &DocContext<'_>) -> Type {
2750
        use rustc::hir::*;
2751

2752
        match self.node {
C
csmoe 已提交
2753
            TyKind::Never => Never,
2754
            TyKind::CVarArgs(_) => CVarArgs,
C
csmoe 已提交
2755 2756
            TyKind::Ptr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
            TyKind::Rptr(ref l, ref m) => {
2757 2758 2759 2760 2761 2762 2763 2764
                let lifetime = if l.is_elided() {
                    None
                } else {
                    Some(l.clean(cx))
                };
                BorrowedRef {lifetime: lifetime, mutability: m.mutbl.clean(cx),
                             type_: box m.ty.clean(cx)}
            }
C
csmoe 已提交
2765 2766
            TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
            TyKind::Array(ref ty, ref length) => {
L
ljedrz 已提交
2767
                let def_id = cx.tcx.hir().local_def_id_from_hir_id(length.hir_id);
2768
                let param_env = cx.tcx.param_env(def_id);
C
csmoe 已提交
2769
                let substs = InternalSubsts::identity_for_item(cx.tcx, def_id);
O
Oliver Schneider 已提交
2770 2771 2772 2773
                let cid = GlobalId {
                    instance: ty::Instance::new(def_id, substs),
                    promoted: None
                };
2774
                let length = match cx.tcx.const_eval(param_env.and(cid)) {
O
Oliver Scherer 已提交
2775
                    Ok(length) => print_const(cx, length),
2776 2777
                    Err(_) => "_".to_string(),
                };
2778
                Array(box ty.clean(cx), length)
2779
            },
C
csmoe 已提交
2780
            TyKind::Tup(ref tys) => Tuple(tys.clean(cx)),
O
Oliver Schneider 已提交
2781
            TyKind::Def(item_id, _) => {
2782
                let item = cx.tcx.hir().expect_item_by_hir_id(item_id.id);
O
Oliver Schneider 已提交
2783 2784 2785 2786 2787 2788
                if let hir::ItemKind::Existential(ref ty) = item.node {
                    ImplTrait(ty.bounds.clean(cx))
                } else {
                    unreachable!()
                }
            }
C
csmoe 已提交
2789
            TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
2790
                if let Res::Def(DefKind::TyParam, did) = path.res {
2791 2792 2793
                    if let Some(new_ty) = cx.ty_substs.borrow().get(&did).cloned() {
                        return new_ty;
                    }
2794 2795 2796 2797 2798
                    if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did) {
                        return ImplTrait(bounds);
                    }
                }

2799
                let mut alias = None;
2800
                if let Res::Def(DefKind::TyAlias, def_id) = path.res {
2801
                    // Substitute private type aliases
2802
                    if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
2803
                        if !cx.renderinfo.borrow().access_levels.is_exported(def_id) {
2804
                            alias = Some(&cx.tcx.hir().expect_item_by_hir_id(hir_id).node);
2805
                        }
E
Eduard Burtescu 已提交
2806
                    }
2807 2808
                };

C
csmoe 已提交
2809
                if let Some(&hir::ItemKind::Ty(ref ty, ref generics)) = alias {
G
Guillaume Gomez 已提交
2810
                    let provided_params = &path.segments.last().expect("segments were empty");
2811 2812
                    let mut ty_substs = FxHashMap::default();
                    let mut lt_substs = FxHashMap::default();
2813
                    let mut ct_substs = FxHashMap::default();
2814
                    provided_params.with_generic_args(|generic_args| {
V
varkor 已提交
2815
                        let mut indices: GenericParamCount = Default::default();
2816
                        for param in generics.params.iter() {
V
varkor 已提交
2817 2818
                            match param.kind {
                                hir::GenericParamKind::Lifetime { .. } => {
2819 2820 2821
                                    let mut j = 0;
                                    let lifetime = generic_args.args.iter().find_map(|arg| {
                                        match arg {
V
varkor 已提交
2822
                                            hir::GenericArg::Lifetime(lt) => {
2823 2824 2825 2826 2827 2828 2829 2830 2831 2832
                                                if indices.lifetimes == j {
                                                    return Some(lt);
                                                }
                                                j += 1;
                                                None
                                            }
                                            _ => None,
                                        }
                                    });
                                    if let Some(lt) = lifetime.cloned() {
2833 2834
                                        if !lt.is_elided() {
                                            let lt_def_id =
L
ljedrz 已提交
2835
                                                cx.tcx.hir().local_def_id_from_hir_id(param.hir_id);
2836 2837 2838 2839 2840
                                            lt_substs.insert(lt_def_id, lt.clean(cx));
                                        }
                                    }
                                    indices.lifetimes += 1;
                                }
V
varkor 已提交
2841
                                hir::GenericParamKind::Type { ref default, .. } => {
2842 2843
                                    let ty_param_def_id =
                                        cx.tcx.hir().local_def_id_from_hir_id(param.hir_id);
2844 2845 2846
                                    let mut j = 0;
                                    let type_ = generic_args.args.iter().find_map(|arg| {
                                        match arg {
V
varkor 已提交
2847
                                            hir::GenericArg::Type(ty) => {
2848 2849 2850 2851 2852 2853 2854 2855 2856 2857
                                                if indices.types == j {
                                                    return Some(ty);
                                                }
                                                j += 1;
                                                None
                                            }
                                            _ => None,
                                        }
                                    });
                                    if let Some(ty) = type_.cloned() {
2858
                                        ty_substs.insert(ty_param_def_id, ty.clean(cx));
V
varkor 已提交
2859
                                    } else if let Some(default) = default.clone() {
2860
                                        ty_substs.insert(ty_param_def_id,
2861 2862
                                                         default.into_inner().clean(cx));
                                    }
2863
                                    indices.types += 1;
2864
                                }
V
varkor 已提交
2865
                                hir::GenericParamKind::Const { .. } => {
2866 2867
                                    let const_param_def_id =
                                        cx.tcx.hir().local_def_id_from_hir_id(param.hir_id);
V
varkor 已提交
2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881
                                    let mut j = 0;
                                    let const_ = generic_args.args.iter().find_map(|arg| {
                                        match arg {
                                            hir::GenericArg::Const(ct) => {
                                                if indices.consts == j {
                                                    return Some(ct);
                                                }
                                                j += 1;
                                                None
                                            }
                                            _ => None,
                                        }
                                    });
                                    if let Some(ct) = const_.cloned() {
2882
                                        ct_substs.insert(const_param_def_id, ct.clean(cx));
V
varkor 已提交
2883 2884 2885 2886
                                    }
                                    // FIXME(const_generics:defaults)
                                    indices.consts += 1;
                                }
2887
                            }
2888
                        }
2889
                    });
2890
                    return cx.enter_alias(ty_substs, lt_substs, ct_substs, || ty.clean(cx));
2891
                }
L
ljedrz 已提交
2892
                resolve_type(cx, path.clean(cx), self.hir_id)
N
Niko Matsakis 已提交
2893
            }
C
csmoe 已提交
2894
            TyKind::Path(hir::QPath::Resolved(Some(ref qself), ref p)) => {
2895 2896 2897 2898
                let mut segments: Vec<_> = p.segments.clone().into();
                segments.pop();
                let trait_path = hir::Path {
                    span: p.span,
2899
                    res: Res::Def(
2900
                        DefKind::Trait,
2901
                        cx.tcx.associated_item(p.res.def_id()).container.id(),
2902
                    ),
2903 2904
                    segments: segments.into(),
                };
2905
                Type::QPath {
G
Guillaume Gomez 已提交
2906
                    name: p.segments.last().expect("segments were empty").ident.name.clean(cx),
2907
                    self_type: box qself.clean(cx),
L
ljedrz 已提交
2908
                    trait_: box resolve_type(cx, trait_path.clean(cx), self.hir_id)
2909 2910
                }
            }
C
csmoe 已提交
2911
            TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
2912
                let mut res = Res::Err;
2913
                let ty = hir_ty_to_ty(cx.tcx, self);
V
varkor 已提交
2914
                if let ty::Projection(proj) = ty.sty {
2915
                    res = Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id);
2916
                }
2917 2918
                let trait_path = hir::Path {
                    span: self.span,
2919
                    res,
2920 2921 2922
                    segments: vec![].into(),
                };
                Type::QPath {
2923
                    name: segment.ident.name.clean(cx),
2924
                    self_type: box qself.clean(cx),
L
ljedrz 已提交
2925
                    trait_: box resolve_type(cx, trait_path.clean(cx), self.hir_id)
2926 2927
                }
            }
C
csmoe 已提交
2928
            TyKind::TraitObject(ref bounds, ref lifetime) => {
2929
                match bounds[0].clean(cx).trait_ {
V
varkor 已提交
2930
                    ResolvedPath { path, param_names: None, did, is_generic } => {
V
varkor 已提交
2931
                        let mut bounds: Vec<self::GenericBound> = bounds[1..].iter().map(|bound| {
V
varkor 已提交
2932 2933
                            self::GenericBound::TraitBound(bound.clean(cx),
                                                           hir::TraitBoundModifier::None)
2934 2935
                        }).collect();
                        if !lifetime.is_elided() {
V
varkor 已提交
2936
                            bounds.push(self::GenericBound::Outlives(lifetime.clean(cx)));
2937
                        }
V
varkor 已提交
2938
                        ResolvedPath { path, param_names: Some(bounds), did, is_generic, }
N
Niko Matsakis 已提交
2939
                    }
2940
                    _ => Infer // shouldn't happen
N
Niko Matsakis 已提交
2941
                }
2942
            }
C
csmoe 已提交
2943 2944 2945
            TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
            TyKind::Infer | TyKind::Err => Infer,
            TyKind::Typeof(..) => panic!("Unimplemented type {:?}", self.node),
2946
        }
C
Corey Richardson 已提交
2947 2948 2949
    }
}

D
Douglas Campos 已提交
2950
impl<'tcx> Clean<Type> for Ty<'tcx> {
2951
    fn clean(&self, cx: &DocContext<'_>) -> Type {
2952
        debug!("cleaning type: {:?}", self);
2953
        match self.sty {
V
varkor 已提交
2954
            ty::Never => Never,
2955 2956 2957 2958 2959 2960
            ty::Bool => Primitive(PrimitiveType::Bool),
            ty::Char => Primitive(PrimitiveType::Char),
            ty::Int(int_ty) => Primitive(int_ty.into()),
            ty::Uint(uint_ty) => Primitive(uint_ty.into()),
            ty::Float(float_ty) => Primitive(float_ty.into()),
            ty::Str => Primitive(PrimitiveType::Str),
V
varkor 已提交
2961 2962
            ty::Slice(ty) => Slice(box ty.clean(cx)),
            ty::Array(ty, n) => {
2963
                let mut n = *cx.tcx.lift(&n).expect("array lift failed");
O
Oliver Scherer 已提交
2964
                if let ConstValue::Unevaluated(def_id, substs) = n.val {
2965
                    let param_env = cx.tcx.param_env(def_id);
O
Oliver Schneider 已提交
2966 2967 2968 2969 2970
                    let cid = GlobalId {
                        instance: ty::Instance::new(def_id, substs),
                        promoted: None
                    };
                    if let Ok(new_n) = cx.tcx.const_eval(param_env.and(cid)) {
O
Oliver Scherer 已提交
2971
                        n = new_n;
2972
                    }
2973
                };
O
Oliver Schneider 已提交
2974
                let n = print_const(cx, n);
2975 2976
                Array(box ty.clean(cx), n)
            }
V
varkor 已提交
2977 2978
            ty::RawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
            ty::Ref(r, ty, mutbl) => BorrowedRef {
2979
                lifetime: r.clean(cx),
2980 2981
                mutability: mutbl.clean(cx),
                type_: box ty.clean(cx),
2982
            },
V
varkor 已提交
2983 2984 2985
            ty::FnDef(..) |
            ty::FnPtr(_) => {
                let ty = cx.tcx.lift(self).expect("FnPtr lift failed");
2986 2987 2988
                let sig = ty.fn_sig(cx.tcx);
                BareFunction(box BareFunctionDecl {
                    unsafety: sig.unsafety(),
2989
                    generic_params: Vec::new(),
2990
                    decl: (cx.tcx.hir().local_def_id(ast::CRATE_NODE_ID), sig).clean(cx),
2991 2992 2993
                    abi: sig.abi(),
                })
            }
V
varkor 已提交
2994
            ty::Adt(def, substs) => {
2995
                let did = def.did;
2996
                let kind = match def.adt_kind() {
2997 2998 2999
                    AdtKind::Struct => TypeKind::Struct,
                    AdtKind::Union => TypeKind::Union,
                    AdtKind::Enum => TypeKind::Enum,
3000
                };
M
mitaa 已提交
3001
                inline::record_extern_fqn(cx, did, kind);
3002
                let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
3003
                                         None, false, vec![], substs);
3004
                ResolvedPath {
3005
                    path,
V
varkor 已提交
3006
                    param_names: None,
3007
                    did,
3008
                    is_generic: false,
3009 3010
                }
            }
V
varkor 已提交
3011
            ty::Foreign(did) => {
P
Paul Lietar 已提交
3012
                inline::record_extern_fqn(cx, did, TypeKind::Foreign);
3013
                let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
C
csmoe 已提交
3014
                                         None, false, vec![], InternalSubsts::empty());
P
Paul Lietar 已提交
3015 3016
                ResolvedPath {
                    path: path,
V
varkor 已提交
3017
                    param_names: None,
P
Paul Lietar 已提交
3018 3019 3020 3021
                    did: did,
                    is_generic: false,
                }
            }
V
varkor 已提交
3022
            ty::Dynamic(ref obj, ref reg) => {
A
Ariel Ben-Yehuda 已提交
3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035
                // HACK: pick the first `did` as the `did` of the trait object. Someone
                // might want to implement "native" support for marker-trait-only
                // trait objects.
                let mut dids = obj.principal_def_id().into_iter().chain(obj.auto_traits());
                let did = dids.next().unwrap_or_else(|| {
                    panic!("found trait object `{:?}` with no traits?", self)
                });
                let substs = match obj.principal() {
                    Some(principal) => principal.skip_binder().substs,
                    // marker traits have no substs.
                    _ => cx.tcx.intern_substs(&[])
                };

3036 3037
                inline::record_extern_fqn(cx, did, TypeKind::Trait);

V
varkor 已提交
3038 3039
                let mut param_names = vec![];
                reg.clean(cx).map(|b| param_names.push(GenericBound::Outlives(b)));
A
Ariel Ben-Yehuda 已提交
3040
                for did in dids {
3041 3042 3043
                    let empty = cx.tcx.intern_substs(&[]);
                    let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
                        Some(did), false, vec![], empty);
3044
                    inline::record_extern_fqn(cx, did, TypeKind::Trait);
3045 3046 3047
                    let bound = GenericBound::TraitBound(PolyTrait {
                        trait_: ResolvedPath {
                            path,
V
varkor 已提交
3048
                            param_names: None,
3049 3050 3051 3052 3053
                            did,
                            is_generic: false,
                        },
                        generic_params: Vec::new(),
                    }, hir::TraitBoundModifier::None);
V
varkor 已提交
3054
                    param_names.push(bound);
3055
                }
3056

3057 3058 3059 3060 3061 3062 3063
                let mut bindings = vec![];
                for pb in obj.projection_bounds() {
                    bindings.push(TypeBinding {
                        name: cx.tcx.associated_item(pb.item_def_id()).ident.name.clean(cx),
                        ty: pb.skip_binder().ty.clean(cx)
                    });
                }
3064

3065
                let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did),
A
Ariel Ben-Yehuda 已提交
3066
                    false, bindings, substs);
3067 3068
                ResolvedPath {
                    path,
V
varkor 已提交
3069
                    param_names: Some(param_names),
3070 3071
                    did,
                    is_generic: false,
3072 3073
                }
            }
V
varkor 已提交
3074 3075 3076
            ty::Tuple(ref t) => {
                Tuple(t.iter().map(|t| t.expect_ty()).collect::<Vec<_>>().clean(cx))
            }
3077

V
varkor 已提交
3078
            ty::Projection(ref data) => data.clean(cx),
3079

V
varkor 已提交
3080
            ty::Param(ref p) => Generic(p.name.to_string()),
3081

3082
            ty::Opaque(def_id, substs) => {
3083 3084
                // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
                // by looking up the projections associated with the def_id.
3085
                let predicates_of = cx.tcx.explicit_predicates_of(def_id);
3086
                let substs = cx.tcx.lift(&substs).expect("Opaque lift failed");
3087
                let bounds = predicates_of.instantiate(cx.tcx, substs);
3088 3089 3090
                let mut regions = vec![];
                let mut has_sized = false;
                let mut bounds = bounds.predicates.iter().filter_map(|predicate| {
3091 3092
                    let trait_ref = if let Some(tr) = predicate.to_opt_poly_trait_ref() {
                        tr
3093 3094
                    } else if let ty::Predicate::TypeOutlives(pred) = *predicate {
                        // these should turn up at the end
3095
                        pred.skip_binder().1.clean(cx).map(|r| {
V
varkor 已提交
3096
                            regions.push(GenericBound::Outlives(r))
3097
                        });
3098
                        return None;
3099 3100 3101 3102
                    } else {
                        return None;
                    };

3103 3104
                    if let Some(sized) = cx.tcx.lang_items().sized_trait() {
                        if trait_ref.def_id() == sized {
3105
                            has_sized = true;
3106 3107 3108 3109
                            return None;
                        }
                    }

3110 3111 3112 3113 3114 3115
                    let bounds = bounds.predicates.iter().filter_map(|pred|
                        if let ty::Predicate::Projection(proj) = *pred {
                            let proj = proj.skip_binder();
                            if proj.projection_ty.trait_ref(cx.tcx) == *trait_ref.skip_binder() {
                                Some(TypeBinding {
                                    name: cx.tcx.associated_item(proj.projection_ty.item_def_id)
3116
                                                .ident.name.clean(cx),
3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127
                                    ty: proj.ty.clean(cx),
                                })
                            } else {
                                None
                            }
                        } else {
                            None
                        }
                    ).collect();

                    Some((trait_ref.skip_binder(), bounds).clean(cx))
3128 3129 3130
                }).collect::<Vec<_>>();
                bounds.extend(regions);
                if !has_sized && !bounds.is_empty() {
V
varkor 已提交
3131
                    bounds.insert(0, GenericBound::maybe_sized(cx));
3132 3133
                }
                ImplTrait(bounds)
3134 3135
            }

V
varkor 已提交
3136
            ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton)
3137

S
scalexm 已提交
3138
            ty::Bound(..) => panic!("Bound"),
S
scalexm 已提交
3139
            ty::Placeholder(..) => panic!("Placeholder"),
3140
            ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"),
V
varkor 已提交
3141 3142 3143
            ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
            ty::Infer(..) => panic!("Infer"),
            ty::Error => panic!("Error"),
3144 3145 3146 3147
        }
    }
}

V
varkor 已提交
3148 3149 3150 3151
impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
    fn clean(&self, cx: &DocContext<'_>) -> Constant {
        Constant {
            type_: self.ty.clean(cx),
3152 3153 3154 3155
            expr: match self.val {
                ConstValue::Param(ty::ParamConst { name, .. }) => format!("{}", name),
                e => format!("{:?}", e), // FIXME generic consts with expressions
            },
V
varkor 已提交
3156 3157 3158 3159
        }
    }
}

3160
impl Clean<Item> for hir::StructField {
3161
    fn clean(&self, cx: &DocContext<'_>) -> Item {
L
ljedrz 已提交
3162 3163
        let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);

C
Corey Richardson 已提交
3164
        Item {
3165
            name: Some(self.ident.name).clean(cx),
3166
            attrs: self.attrs.clean(cx),
3167
            source: self.span.clean(cx),
3168
            visibility: self.vis.clean(cx),
L
ljedrz 已提交
3169 3170 3171
            stability: get_stability(cx, local_did),
            deprecation: get_deprecation(cx, local_did),
            def_id: local_did,
3172
            inner: StructFieldItem(self.ty.clean(cx)),
C
Corey Richardson 已提交
3173 3174 3175 3176
        }
    }
}

3177
impl<'tcx> Clean<Item> for ty::FieldDef {
3178
    fn clean(&self, cx: &DocContext<'_>) -> Item {
3179
        Item {
3180
            name: Some(self.ident.name).clean(cx),
3181
            attrs: cx.tcx.get_attrs(self.did).clean(cx),
3182
            source: cx.tcx.def_span(self.did).clean(cx),
3183
            visibility: self.vis.clean(cx),
3184
            stability: get_stability(cx, self.did),
3185
            deprecation: get_deprecation(cx, self.did),
3186
            def_id: self.did,
3187
            inner: StructFieldItem(cx.tcx.type_of(self.did).clean(cx)),
3188 3189 3190 3191
        }
    }
}

J
Jeffrey Seyfried 已提交
3192 3193 3194 3195
#[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug)]
pub enum Visibility {
    Public,
    Inherited,
3196 3197
    Crate,
    Restricted(DefId, Path),
J
Jeffrey Seyfried 已提交
3198
}
C
Corey Richardson 已提交
3199

3200
impl Clean<Option<Visibility>> for hir::Visibility {
3201
    fn clean(&self, cx: &DocContext<'_>) -> Option<Visibility> {
3202
        Some(match self.node {
3203 3204 3205 3206
            hir::VisibilityKind::Public => Visibility::Public,
            hir::VisibilityKind::Inherited => Visibility::Inherited,
            hir::VisibilityKind::Crate(_) => Visibility::Crate,
            hir::VisibilityKind::Restricted { ref path, .. } => {
3207
                let path = path.clean(cx);
3208
                let did = register_res(cx, path.res);
3209 3210 3211
                Visibility::Restricted(did, path)
            }
        })
3212 3213 3214 3215
    }
}

impl Clean<Option<Visibility>> for ty::Visibility {
3216
    fn clean(&self, _: &DocContext<'_>) -> Option<Visibility> {
J
Jeffrey Seyfried 已提交
3217
        Some(if *self == ty::Visibility::Public { Public } else { Inherited })
C
Corey Richardson 已提交
3218 3219 3220
    }
}

J
Jorge Aparicio 已提交
3221
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
3222
pub struct Struct {
3223 3224 3225 3226
    pub struct_type: doctree::StructType,
    pub generics: Generics,
    pub fields: Vec<Item>,
    pub fields_stripped: bool,
C
Corey Richardson 已提交
3227 3228
}

V
Vadim Petrochenkov 已提交
3229 3230 3231 3232 3233 3234 3235 3236
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Union {
    pub struct_type: doctree::StructType,
    pub generics: Generics,
    pub fields: Vec<Item>,
    pub fields_stripped: bool,
}

3237
impl Clean<Item> for doctree::Struct {
3238
    fn clean(&self, cx: &DocContext<'_>) -> Item {
3239 3240
        Item {
            name: Some(self.name.clean(cx)),
3241 3242
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
L
ljedrz 已提交
3243
            def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
3244 3245
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
3246
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
3247 3248
            inner: StructItem(Struct {
                struct_type: self.struct_type,
3249 3250
                generics: self.generics.clean(cx),
                fields: self.fields.clean(cx),
S
Steven Fackler 已提交
3251
                fields_stripped: false,
C
Corey Richardson 已提交
3252
            }),
3253
        }
C
Corey Richardson 已提交
3254 3255 3256
    }
}

3257
impl Clean<Item> for doctree::Union {
3258
    fn clean(&self, cx: &DocContext<'_>) -> Item {
3259 3260
        Item {
            name: Some(self.name.clean(cx)),
V
Vadim Petrochenkov 已提交
3261 3262
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
L
ljedrz 已提交
3263
            def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
V
Vadim Petrochenkov 已提交
3264 3265 3266 3267 3268 3269 3270 3271 3272
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
            deprecation: self.depr.clean(cx),
            inner: UnionItem(Union {
                struct_type: self.struct_type,
                generics: self.generics.clean(cx),
                fields: self.fields.clean(cx),
                fields_stripped: false,
            }),
3273
        }
V
Vadim Petrochenkov 已提交
3274 3275 3276
    }
}

3277
/// This is a more limited form of the standard Struct, different in that
C
Corey Richardson 已提交
3278 3279
/// it lacks the things most items have (name, id, parameterization). Found
/// only as a variant in an enum.
J
Jorge Aparicio 已提交
3280
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
3281
pub struct VariantStruct {
3282 3283 3284
    pub struct_type: doctree::StructType,
    pub fields: Vec<Item>,
    pub fields_stripped: bool,
C
Corey Richardson 已提交
3285 3286
}

3287
impl Clean<VariantStruct> for ::rustc::hir::VariantData {
3288
    fn clean(&self, cx: &DocContext<'_>) -> VariantStruct {
C
Corey Richardson 已提交
3289 3290
        VariantStruct {
            struct_type: doctree::struct_type_from_def(self),
3291
            fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
S
Steven Fackler 已提交
3292
            fields_stripped: false,
C
Corey Richardson 已提交
3293 3294 3295 3296
        }
    }
}

J
Jorge Aparicio 已提交
3297
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
3298
pub struct Enum {
3299
    pub variants: IndexVec<VariantIdx, Item>,
3300 3301
    pub generics: Generics,
    pub variants_stripped: bool,
C
Corey Richardson 已提交
3302 3303
}

3304
impl Clean<Item> for doctree::Enum {
3305
    fn clean(&self, cx: &DocContext<'_>) -> Item {
3306 3307
        Item {
            name: Some(self.name.clean(cx)),
3308 3309
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
L
ljedrz 已提交
3310
            def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
3311 3312
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
3313
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
3314
            inner: EnumItem(Enum {
3315
                variants: self.variants.iter().map(|v| v.clean(cx)).collect(),
3316
                generics: self.generics.clean(cx),
S
Steven Fackler 已提交
3317
                variants_stripped: false,
C
Corey Richardson 已提交
3318
            }),
3319
        }
C
Corey Richardson 已提交
3320 3321 3322
    }
}

J
Jorge Aparicio 已提交
3323
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
3324
pub struct Variant {
3325
    pub kind: VariantKind,
C
Corey Richardson 已提交
3326 3327 3328
}

impl Clean<Item> for doctree::Variant {
3329
    fn clean(&self, cx: &DocContext<'_>) -> Item {
C
Corey Richardson 已提交
3330
        Item {
3331 3332 3333
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
3334
            visibility: None,
3335
            stability: self.stab.clean(cx),
3336
            deprecation: self.depr.clean(cx),
3337
            def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
C
Corey Richardson 已提交
3338
            inner: VariantItem(Variant {
3339
                kind: self.def.clean(cx),
C
Corey Richardson 已提交
3340 3341 3342 3343 3344
            }),
        }
    }
}

3345
impl<'tcx> Clean<Item> for ty::VariantDef {
3346
    fn clean(&self, cx: &DocContext<'_>) -> Item {
3347 3348 3349
        let kind = match self.ctor_kind {
            CtorKind::Const => VariantKind::CLike,
            CtorKind::Fn => {
3350
                VariantKind::Tuple(
3351
                    self.fields.iter().map(|f| cx.tcx.type_of(f.did).clean(cx)).collect()
3352
                )
3353
            }
3354
            CtorKind::Fictive => {
3355
                VariantKind::Struct(VariantStruct {
3356 3357
                    struct_type: doctree::Plain,
                    fields_stripped: false,
3358
                    fields: self.fields.iter().map(|field| {
3359
                        Item {
3360
                            source: cx.tcx.def_span(field.did).clean(cx),
3361
                            name: Some(field.ident.name.clean(cx)),
3362
                            attrs: cx.tcx.get_attrs(field.did).clean(cx),
3363
                            visibility: field.vis.clean(cx),
3364 3365 3366
                            def_id: field.did,
                            stability: get_stability(cx, field.did),
                            deprecation: get_deprecation(cx, field.did),
3367
                            inner: StructFieldItem(cx.tcx.type_of(field.did).clean(cx))
3368 3369 3370 3371 3372 3373
                        }
                    }).collect()
                })
            }
        };
        Item {
3374
            name: Some(self.ident.clean(cx)),
3375 3376
            attrs: inline::load_attrs(cx, self.def_id),
            source: cx.tcx.def_span(self.def_id).clean(cx),
J
Jeffrey Seyfried 已提交
3377
            visibility: Some(Inherited),
3378
            def_id: self.def_id,
T
teresy 已提交
3379
            inner: VariantItem(Variant { kind }),
3380 3381
            stability: get_stability(cx, self.def_id),
            deprecation: get_deprecation(cx, self.def_id),
3382 3383 3384 3385
        }
    }
}

J
Jorge Aparicio 已提交
3386
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
3387
pub enum VariantKind {
3388 3389 3390
    CLike,
    Tuple(Vec<Type>),
    Struct(VariantStruct),
C
Corey Richardson 已提交
3391 3392
}

3393
impl Clean<VariantKind> for hir::VariantData {
3394
    fn clean(&self, cx: &DocContext<'_>) -> VariantKind {
3395 3396 3397 3398 3399
        match self {
            hir::VariantData::Struct(..) => VariantKind::Struct(self.clean(cx)),
            hir::VariantData::Tuple(..) =>
                VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect()),
            hir::VariantData::Unit(..) => VariantKind::CLike,
3400
        }
3401 3402 3403
    }
}

J
Jorge Aparicio 已提交
3404
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3405
pub struct Span {
3406
    pub filename: FileName,
3407 3408 3409 3410
    pub loline: usize,
    pub locol: usize,
    pub hiline: usize,
    pub hicol: usize,
G
Guillaume Gomez 已提交
3411
    pub original: syntax_pos::Span,
3412 3413
}

3414
impl Span {
3415
    pub fn empty() -> Span {
3416
        Span {
3417
            filename: FileName::Anon(0),
3418 3419
            loline: 0, locol: 0,
            hiline: 0, hicol: 0,
G
Guillaume Gomez 已提交
3420
            original: syntax_pos::DUMMY_SP,
3421 3422
        }
    }
G
Guillaume Gomez 已提交
3423 3424 3425 3426

    pub fn span(&self) -> syntax_pos::Span {
        self.original
    }
3427 3428
}

3429
impl Clean<Span> for syntax_pos::Span {
3430
    fn clean(&self, cx: &DocContext<'_>) -> Span {
V
Vadim Petrochenkov 已提交
3431
        if self.is_dummy() {
3432 3433 3434
            return Span::empty();
        }

D
Donato Sciarra 已提交
3435
        let cm = cx.sess().source_map();
3436
        let filename = cm.span_to_filename(*self);
3437 3438
        let lo = cm.lookup_char_pos(self.lo());
        let hi = cm.lookup_char_pos(self.hi());
3439
        Span {
3440
            filename,
3441
            loline: lo.line,
3442
            locol: lo.col.to_usize(),
3443
            hiline: hi.line,
3444
            hicol: hi.col.to_usize(),
G
Guillaume Gomez 已提交
3445
            original: *self,
3446
        }
C
Corey Richardson 已提交
3447 3448 3449
    }
}

3450
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
C
Corey Richardson 已提交
3451
pub struct Path {
3452
    pub global: bool,
3453
    pub res: Res,
3454
    pub segments: Vec<PathSegment>,
C
Corey Richardson 已提交
3455 3456
}

3457
impl Path {
B
bluss 已提交
3458
    pub fn last_name(&self) -> &str {
G
Guillaume Gomez 已提交
3459
        self.segments.last().expect("segments were empty").name.as_str()
3460
    }
3461 3462
}

3463
impl Clean<Path> for hir::Path {
3464
    fn clean(&self, cx: &DocContext<'_>) -> Path {
C
Corey Richardson 已提交
3465
        Path {
3466
            global: self.is_global(),
3467
            res: self.res,
3468
            segments: if self.is_global() { &self.segments[1..] } else { &self.segments }.clean(cx),
3469 3470 3471 3472
        }
    }
}

V
varkor 已提交
3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
pub enum GenericArg {
    Lifetime(Lifetime),
    Type(Type),
    Const(Constant),
}

impl fmt::Display for GenericArg {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            GenericArg::Lifetime(lt) => lt.fmt(f),
            GenericArg::Type(ty) => ty.fmt(f),
            GenericArg::Const(ct) => ct.fmt(f),
        }
    }
}

V
varkor 已提交
3490
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3491
pub enum GenericArgs {
3492
    AngleBracketed {
3493
        args: Vec<GenericArg>,
3494
        bindings: Vec<TypeBinding>,
3495 3496 3497
    },
    Parenthesized {
        inputs: Vec<Type>,
3498
        output: Option<Type>,
3499
    }
3500 3501
}

3502
impl Clean<GenericArgs> for hir::GenericArgs {
3503
    fn clean(&self, cx: &DocContext<'_>) -> GenericArgs {
3504 3505
        if self.parenthesized {
            let output = self.bindings[0].ty.clean(cx);
3506
            GenericArgs::Parenthesized {
3507 3508
                inputs: self.inputs().clean(cx),
                output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
3509
            }
3510
        } else {
3511 3512 3513 3514
            let elide_lifetimes = self.args.iter().all(|arg| match arg {
                hir::GenericArg::Lifetime(lt) => lt.is_elided(),
                _ => true,
            });
3515
            GenericArgs::AngleBracketed {
3516 3517 3518 3519 3520 3521 3522 3523
                args: self.args.iter().filter_map(|arg| match arg {
                    hir::GenericArg::Lifetime(lt) if !elide_lifetimes => {
                        Some(GenericArg::Lifetime(lt.clean(cx)))
                    }
                    hir::GenericArg::Lifetime(_) => None,
                    hir::GenericArg::Type(ty) => Some(GenericArg::Type(ty.clean(cx))),
                    hir::GenericArg::Const(ct) => Some(GenericArg::Const(ct.clean(cx))),
                }).collect(),
3524
                bindings: self.bindings.clean(cx),
3525
            }
3526 3527 3528
        }
    }
}
3529

3530
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3531 3532
pub struct PathSegment {
    pub name: String,
V
varkor 已提交
3533
    pub args: GenericArgs,
3534 3535
}

3536
impl Clean<PathSegment> for hir::PathSegment {
3537
    fn clean(&self, cx: &DocContext<'_>) -> PathSegment {
3538
        PathSegment {
3539
            name: self.ident.name.clean(cx),
3540
            args: self.with_generic_args(|generic_args| generic_args.clean(cx))
C
Corey Richardson 已提交
3541 3542 3543 3544
        }
    }
}

3545 3546
fn strip_type(ty: Type) -> Type {
    match ty {
V
varkor 已提交
3547 3548
        Type::ResolvedPath { path, param_names, did, is_generic } => {
            Type::ResolvedPath { path: strip_path(&path), param_names, did, is_generic }
A
Aaron Hill 已提交
3549
        }
3550 3551
        Type::Tuple(inner_tys) => {
            Type::Tuple(inner_tys.iter().map(|t| strip_type(t.clone())).collect())
A
Aaron Hill 已提交
3552
        }
3553 3554 3555 3556 3557 3558
        Type::Slice(inner_ty) => Type::Slice(Box::new(strip_type(*inner_ty))),
        Type::Array(inner_ty, s) => Type::Array(Box::new(strip_type(*inner_ty)), s),
        Type::Unique(inner_ty) => Type::Unique(Box::new(strip_type(*inner_ty))),
        Type::RawPointer(m, inner_ty) => Type::RawPointer(m, Box::new(strip_type(*inner_ty))),
        Type::BorrowedRef { lifetime, mutability, type_ } => {
            Type::BorrowedRef { lifetime, mutability, type_: Box::new(strip_type(*type_)) }
A
Aaron Hill 已提交
3559
        }
3560 3561 3562 3563 3564
        Type::QPath { name, self_type, trait_ } => {
            Type::QPath {
                name,
                self_type: Box::new(strip_type(*self_type)), trait_: Box::new(strip_type(*trait_))
            }
A
Aaron Hill 已提交
3565
        }
3566 3567 3568 3569 3570 3571 3572 3573
        _ => ty
    }
}

fn strip_path(path: &Path) -> Path {
    let segments = path.segments.iter().map(|s| {
        PathSegment {
            name: s.name.clone(),
V
varkor 已提交
3574
            args: GenericArgs::AngleBracketed {
3575 3576
                args: vec![],
                bindings: vec![],
3577 3578 3579 3580 3581 3582
            }
        }
    }).collect();

    Path {
        global: path.global,
3583
        res: path.res.clone(),
A
Aaron Hill 已提交
3584
        segments,
3585 3586 3587
    }
}

3588
fn qpath_to_string(p: &hir::QPath) -> String {
3589 3590
    let segments = match *p {
        hir::QPath::Resolved(_, ref path) => &path.segments,
3591
        hir::QPath::TypeRelative(_, ref segment) => return segment.ident.to_string(),
3592 3593
    };

3594
    let mut s = String::new();
3595 3596
    for (i, seg) in segments.iter().enumerate() {
        if i > 0 {
C
Corey Richardson 已提交
3597 3598
            s.push_str("::");
        }
V
Vadim Petrochenkov 已提交
3599
        if seg.ident.name != keywords::PathRoot.name() {
3600
            s.push_str(&*seg.ident.as_str());
3601
        }
C
Corey Richardson 已提交
3602
    }
3603
    s
C
Corey Richardson 已提交
3604 3605
}

3606 3607
impl Clean<String> for Ident {
    #[inline]
3608
    fn clean(&self, cx: &DocContext<'_>) -> String {
3609 3610 3611 3612
        self.name.clean(cx)
    }
}

3613
impl Clean<String> for ast::Name {
3614
    #[inline]
3615
    fn clean(&self, _: &DocContext<'_>) -> String {
3616
        self.to_string()
3617 3618 3619
    }
}

3620
impl Clean<String> for InternedString {
3621
    #[inline]
3622
    fn clean(&self, _: &DocContext<'_>) -> String {
3623 3624 3625 3626
        self.to_string()
    }
}

J
Jorge Aparicio 已提交
3627
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
3628
pub struct Typedef {
3629 3630
    pub type_: Type,
    pub generics: Generics,
C
Corey Richardson 已提交
3631 3632 3633
}

impl Clean<Item> for doctree::Typedef {
3634
    fn clean(&self, cx: &DocContext<'_>) -> Item {
C
Corey Richardson 已提交
3635
        Item {
3636 3637 3638
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
L
ljedrz 已提交
3639
            def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
3640 3641
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
3642
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
3643
            inner: TypedefItem(Typedef {
3644 3645
                type_: self.ty.clean(cx),
                generics: self.gen.clean(cx),
3646
            }, false),
C
Corey Richardson 已提交
3647 3648 3649 3650
        }
    }
}

O
Oliver Schneider 已提交
3651 3652 3653 3654 3655 3656 3657
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Existential {
    pub bounds: Vec<GenericBound>,
    pub generics: Generics,
}

impl Clean<Item> for doctree::Existential {
3658
    fn clean(&self, cx: &DocContext<'_>) -> Item {
O
Oliver Schneider 已提交
3659 3660 3661 3662
        Item {
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
L
ljedrz 已提交
3663
            def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
O
Oliver Schneider 已提交
3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
            deprecation: self.depr.clean(cx),
            inner: ExistentialItem(Existential {
                bounds: self.exist_ty.bounds.clean(cx),
                generics: self.exist_ty.generics.clean(cx),
            }, false),
        }
    }
}

3675
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
C
Corey Richardson 已提交
3676
pub struct BareFunctionDecl {
3677
    pub unsafety: hir::Unsafety,
V
varkor 已提交
3678
    pub generic_params: Vec<GenericParamDef>,
3679
    pub decl: FnDecl,
3680
    pub abi: Abi,
C
Corey Richardson 已提交
3681 3682
}

3683
impl Clean<BareFunctionDecl> for hir::BareFnTy {
3684
    fn clean(&self, cx: &DocContext<'_>) -> BareFunctionDecl {
3685 3686 3687
        let (generic_params, decl) = enter_impl_trait(cx, || {
            (self.generic_params.clean(cx), (&*self.decl, &self.arg_names[..]).clean(cx))
        });
C
Corey Richardson 已提交
3688
        BareFunctionDecl {
N
Niko Matsakis 已提交
3689
            unsafety: self.unsafety,
W
Without Boats 已提交
3690
            abi: self.abi,
3691
            decl,
3692
            generic_params,
C
Corey Richardson 已提交
3693 3694 3695 3696
        }
    }
}

J
Jorge Aparicio 已提交
3697
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
3698
pub struct Static {
3699 3700
    pub type_: Type,
    pub mutability: Mutability,
C
Corey Richardson 已提交
3701 3702 3703
    /// 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.
3704
    pub expr: String,
C
Corey Richardson 已提交
3705 3706 3707
}

impl Clean<Item> for doctree::Static {
3708
    fn clean(&self, cx: &DocContext<'_>) -> Item {
3709
        debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
C
Corey Richardson 已提交
3710
        Item {
3711 3712 3713
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
L
ljedrz 已提交
3714
            def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
3715 3716
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
3717
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
3718
            inner: StaticItem(Static {
3719 3720
                type_: self.type_.clean(cx),
                mutability: self.mutability.clean(cx),
3721
                expr: print_const_expr(cx, self.expr),
C
Corey Richardson 已提交
3722 3723 3724 3725 3726
            }),
        }
    }
}

3727
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
3728 3729 3730 3731 3732 3733
pub struct Constant {
    pub type_: Type,
    pub expr: String,
}

impl Clean<Item> for doctree::Constant {
3734
    fn clean(&self, cx: &DocContext<'_>) -> Item {
3735 3736 3737 3738
        Item {
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
L
ljedrz 已提交
3739
            def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
3740 3741
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
3742
            deprecation: self.depr.clean(cx),
3743 3744
            inner: ConstantItem(Constant {
                type_: self.type_.clean(cx),
3745
                expr: print_const_expr(cx, self.expr),
3746 3747 3748 3749 3750
            }),
        }
    }
}

3751
#[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Copy, Hash)]
C
Corey Richardson 已提交
3752 3753 3754 3755 3756
pub enum Mutability {
    Mutable,
    Immutable,
}

3757
impl Clean<Mutability> for hir::Mutability {
3758
    fn clean(&self, _: &DocContext<'_>) -> Mutability {
C
Corey Richardson 已提交
3759
        match self {
3760 3761
            &hir::MutMutable => Mutable,
            &hir::MutImmutable => Immutable,
C
Corey Richardson 已提交
3762 3763 3764 3765
        }
    }
}

3766
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Copy, Debug, Hash)]
3767 3768 3769 3770 3771
pub enum ImplPolarity {
    Positive,
    Negative,
}

3772
impl Clean<ImplPolarity> for hir::ImplPolarity {
3773
    fn clean(&self, _: &DocContext<'_>) -> ImplPolarity {
3774
        match self {
3775 3776
            &hir::ImplPolarity::Positive => ImplPolarity::Positive,
            &hir::ImplPolarity::Negative => ImplPolarity::Negative,
3777 3778 3779 3780
        }
    }
}

J
Jorge Aparicio 已提交
3781
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
C
Corey Richardson 已提交
3782
pub struct Impl {
3783
    pub unsafety: hir::Unsafety,
3784
    pub generics: Generics,
3785
    pub provided_trait_methods: FxHashSet<String>,
3786 3787
    pub trait_: Option<Type>,
    pub for_: Type,
3788
    pub items: Vec<Item>,
3789
    pub polarity: Option<ImplPolarity>,
3790
    pub synthetic: bool,
3791
    pub blanket_impl: Option<Type>,
3792 3793
}

3794 3795 3796 3797 3798 3799 3800
pub fn get_auto_trait_and_blanket_impls(
    cx: &DocContext<'tcx>,
    ty: Ty<'tcx>,
    param_env_def_id: DefId,
) -> impl Iterator<Item = Item> {
    AutoTraitFinder::new(cx).get_auto_trait_impls(ty, param_env_def_id).into_iter()
        .chain(BlanketImplFinder::new(cx).get_blanket_impls(ty, param_env_def_id))
G
Guillaume Gomez 已提交
3801 3802
}

3803
impl Clean<Vec<Item>> for doctree::Impl {
3804
    fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
3805 3806 3807 3808 3809 3810
        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.
3811
        if trait_.def_id() == cx.tcx.lang_items().deref_trait() {
3812
            build_deref_target_impls(cx, &items, &mut ret);
3813 3814
        }

3815 3816 3817
        let provided = trait_.def_id().map(|did| {
            cx.tcx.provided_trait_methods(did)
                  .into_iter()
3818
                  .map(|meth| meth.ident.to_string())
3819
                  .collect()
3820
        }).unwrap_or_default();
3821

3822
        ret.push(Item {
C
Corey Richardson 已提交
3823
            name: None,
3824 3825
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
L
ljedrz 已提交
3826
            def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
3827 3828
            visibility: self.vis.clean(cx),
            stability: self.stab.clean(cx),
3829
            deprecation: self.depr.clean(cx),
C
Corey Richardson 已提交
3830
            inner: ImplItem(Impl {
3831
                unsafety: self.unsafety,
3832
                generics: self.generics.clean(cx),
3833
                provided_trait_methods: provided,
3834
                trait_,
3835
                for_: self.for_.clean(cx),
3836
                items,
3837
                polarity: Some(self.polarity.clean(cx)),
A
Aaron Hill 已提交
3838
                synthetic: false,
3839
                blanket_impl: None,
3840
            })
3841
        });
M
mitaa 已提交
3842
        ret
3843 3844 3845
    }
}

3846
fn build_deref_target_impls(cx: &DocContext<'_>,
3847 3848
                            items: &[Item],
                            ret: &mut Vec<Item>) {
3849
    use self::PrimitiveType::*;
3850
    let tcx = cx.tcx;
3851 3852 3853

    for item in items {
        let target = match item.inner {
3854
            TypedefItem(ref t, true) => &t.type_,
3855 3856 3857
            _ => continue,
        };
        let primitive = match *target {
N
Niko Matsakis 已提交
3858
            ResolvedPath { did, .. } if did.is_local() => continue,
3859
            ResolvedPath { did, .. } => {
3860
                ret.extend(inline::build_impls(cx, did));
3861 3862 3863 3864 3865 3866 3867 3868
                continue
            }
            _ => match target.primitive_type() {
                Some(prim) => prim,
                None => continue,
            }
        };
        let did = match primitive {
3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883
            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(),
            I128 => tcx.lang_items().i128_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(),
            U128 => tcx.lang_items().u128_impl(),
            F32 => tcx.lang_items().f32_impl(),
            F64 => tcx.lang_items().f64_impl(),
            Char => tcx.lang_items().char_impl(),
3884
            Bool => None,
3885 3886 3887
            Str => tcx.lang_items().str_impl(),
            Slice => tcx.lang_items().slice_impl(),
            Array => tcx.lang_items().slice_impl(),
3888
            Tuple => None,
3889
            Unit => None,
3890
            RawPointer => tcx.lang_items().const_ptr_impl(),
3891
            Reference => None,
3892
            Fn => None,
A
Andrew Cann 已提交
3893
            Never => None,
3894
            CVarArgs => tcx.lang_items().va_list(),
3895 3896
        };
        if let Some(did) = did {
N
Niko Matsakis 已提交
3897
            if !did.is_local() {
3898
                inline::build_impl(cx, did, ret);
3899
            }
C
Corey Richardson 已提交
3900 3901 3902 3903
        }
    }
}

D
DebugSteven 已提交
3904
impl Clean<Vec<Item>> for doctree::ExternCrate {
3905
    fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
D
DebugSteven 已提交
3906 3907

        let please_inline = self.vis.node.is_pub() && self.attrs.iter().any(|a| {
3908 3909
            a.check_name(sym::doc) && match a.meta_item_list() {
                Some(l) => attr::list_contains_name(&l, sym::inline),
D
DebugSteven 已提交
3910 3911 3912 3913 3914 3915 3916
                None => false,
            }
        });

        if please_inline {
            let mut visited = FxHashSet::default();

3917
            let res = Res::Def(
3918 3919 3920 3921 3922 3923
                DefKind::Mod,
                DefId {
                    krate: self.cnum,
                    index: CRATE_DEF_INDEX,
                },
            );
D
DebugSteven 已提交
3924

3925
            if let Some(items) = inline::try_inline(cx, res, self.name, &mut visited) {
D
DebugSteven 已提交
3926 3927 3928 3929 3930
                return items;
            }
        }

        vec![Item {
3931 3932 3933
            name: None,
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
M
mitaa 已提交
3934
            def_id: DefId { krate: self.cnum, index: CRATE_DEF_INDEX },
3935 3936
            visibility: self.vis.clean(cx),
            stability: None,
3937
            deprecation: None,
3938
            inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
D
DebugSteven 已提交
3939
        }]
3940
    }
C
Corey Richardson 已提交
3941 3942
}

3943
impl Clean<Vec<Item>> for doctree::Import {
3944
    fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
J
Joseph Crail 已提交
3945
        // We consider inlining the documentation of `pub use` statements, but we
3946 3947
        // forcefully don't inline if this is not public or if the
        // #[doc(no_inline)] attribute is present.
3948
        // Don't inline doc(hidden) imports so they can be stripped at a later stage.
3949
        let mut denied = !self.vis.node.is_pub() || self.attrs.iter().any(|a| {
3950 3951 3952
            a.check_name(sym::doc) && match a.meta_item_list() {
                Some(l) => attr::list_contains_name(&l, sym::no_inline) ||
                           attr::list_contains_name(&l, sym::hidden),
3953 3954 3955
                None => false,
            }
        });
3956 3957
        // Also check whether imports were asked to be inlined, in case we're trying to re-export a
        // crate in Rust 2018+
3958
        let please_inline = self.attrs.lists(sym::doc).has_word(sym::inline);
3959 3960
        let path = self.path.clean(cx);
        let inner = if self.glob {
3961
            if !denied {
3962
                let mut visited = FxHashSet::default();
3963
                if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) {
3964 3965 3966 3967
                    return items;
                }
            }

3968
            Import::Glob(resolve_use_source(cx, path))
3969 3970
        } else {
            let name = self.name;
3971
            if !please_inline {
3972 3973
                match path.res {
                    Res::Def(DefKind::Mod, did) => {
3974 3975 3976 3977 3978
                        if !did.is_local() && did.index == CRATE_DEF_INDEX {
                            // if we're `pub use`ing an extern crate root, don't inline it unless we
                            // were specifically asked for it
                            denied = true;
                        }
3979 3980 3981 3982
                    }
                    _ => {}
                }
            }
3983
            if !denied {
3984
                let mut visited = FxHashSet::default();
3985
                if let Some(items) = inline::try_inline(cx, path.res, name, &mut visited) {
3986
                    return items;
3987
                }
3988
            }
3989
            Import::Simple(name.clean(cx), resolve_use_source(cx, path))
3990
        };
G
Guillaume Gomez 已提交
3991

3992
        vec![Item {
3993 3994 3995
            name: None,
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
3996
            def_id: cx.tcx.hir().local_def_id(ast::CRATE_NODE_ID),
3997 3998
            visibility: self.vis.clean(cx),
            stability: None,
3999
            deprecation: None,
4000
            inner: ImportItem(inner)
4001
        }]
C
Corey Richardson 已提交
4002 4003 4004
    }
}

J
Jorge Aparicio 已提交
4005
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
4006
pub enum Import {
4007
    // use source as str;
4008
    Simple(String, ImportSource),
A
Alex Crichton 已提交
4009
    // use source::*;
4010
    Glob(ImportSource)
A
Alex Crichton 已提交
4011 4012
}

J
Jorge Aparicio 已提交
4013
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
A
Alex Crichton 已提交
4014
pub struct ImportSource {
4015
    pub path: Path,
N
Niko Matsakis 已提交
4016
    pub did: Option<DefId>,
C
Corey Richardson 已提交
4017 4018
}

4019
impl Clean<Vec<Item>> for hir::ForeignMod {
4020
    fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
4021 4022
        let mut items = self.items.clean(cx);
        for item in &mut items {
M
mitaa 已提交
4023
            if let ForeignFunctionItem(ref mut f) = item.inner {
W
Without Boats 已提交
4024
                f.header.abi = self.abi;
4025 4026 4027
            }
        }
        items
4028 4029 4030
    }
}

4031
impl Clean<Item> for hir::ForeignItem {
4032
    fn clean(&self, cx: &DocContext<'_>) -> Item {
4033
        let inner = match self.node {
C
csmoe 已提交
4034
            hir::ForeignItemKind::Fn(ref decl, ref names, ref generics) => {
4035 4036 4037
                let (generics, decl) = enter_impl_trait(cx, || {
                    (generics.clean(cx), (&**decl, &names[..]).clean(cx))
                });
4038
                let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
4039
                ForeignFunctionItem(Function {
4040
                    decl,
4041
                    generics,
4042 4043 4044 4045 4046 4047
                    header: hir::FnHeader {
                        unsafety: hir::Unsafety::Unsafe,
                        abi: Abi::Rust,
                        constness: hir::Constness::NotConst,
                        asyncness: hir::IsAsync::NotAsync,
                    },
4048
                    all_types,
4049
                    ret_types,
4050 4051
                })
            }
C
csmoe 已提交
4052
            hir::ForeignItemKind::Static(ref ty, mutbl) => {
4053
                ForeignStaticItem(Static {
4054
                    type_: ty.clean(cx),
4055
                    mutability: mutbl.clean(cx),
4056
                    expr: String::new(),
4057 4058
                })
            }
C
csmoe 已提交
4059
            hir::ForeignItemKind::Type => {
P
Paul Lietar 已提交
4060 4061
                ForeignTypeItem
            }
4062
        };
G
Guillaume Gomez 已提交
4063

L
ljedrz 已提交
4064 4065
        let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);

4066
        Item {
4067
            name: Some(self.ident.clean(cx)),
4068 4069
            attrs: self.attrs.clean(cx),
            source: self.span.clean(cx),
L
ljedrz 已提交
4070
            def_id: local_did,
4071
            visibility: self.vis.clean(cx),
L
ljedrz 已提交
4072 4073
            stability: get_stability(cx, local_did),
            deprecation: get_deprecation(cx, local_did),
4074
            inner,
4075 4076 4077 4078
        }
    }
}

C
Corey Richardson 已提交
4079 4080
// Utilities

4081
pub trait ToSource {
4082
    fn to_src(&self, cx: &DocContext<'_>) -> String;
C
Corey Richardson 已提交
4083 4084
}

4085
impl ToSource for syntax_pos::Span {
4086
    fn to_src(&self, cx: &DocContext<'_>) -> String {
4087
        debug!("converting span {:?} to snippet", self.clean(cx));
D
Donato Sciarra 已提交
4088
        let sn = match cx.sess().source_map().span_to_snippet(*self) {
S
Shotaro Yamada 已提交
4089
            Ok(x) => x,
4090
            Err(_) => String::new()
C
Corey Richardson 已提交
4091
        };
4092
        debug!("got snippet {}", sn);
C
Corey Richardson 已提交
4093 4094 4095 4096
        sn
    }
}

4097
fn name_from_pat(p: &hir::Pat) -> String {
4098
    use rustc::hir::*;
4099
    debug!("Trying to get a name from pattern: {:?}", p);
4100

C
Corey Richardson 已提交
4101
    match p.node {
4102
        PatKind::Wild => "_".to_string(),
L
ljedrz 已提交
4103
        PatKind::Binding(_, _, ident, _) => ident.to_string(),
4104
        PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
4105
        PatKind::Struct(ref name, ref fields, etc) => {
4106
            format!("{} {{ {}{} }}", qpath_to_string(name),
4107
                fields.iter().map(|&Spanned { node: ref fp, .. }|
4108
                                  format!("{}: {}", fp.ident, name_from_pat(&*fp.pat)))
4109
                             .collect::<Vec<String>>().join(", "),
4110
                if etc { ", .." } else { "" }
4111
            )
4112
        }
4113
        PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
4114
                                            .collect::<Vec<String>>().join(", ")),
4115 4116 4117 4118
        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, \
4119
                  which is silly in function arguments");
4120
            "()".to_string()
4121
        },
4122
        PatKind::Range(..) => panic!("tried to get argument name from PatKind::Range, \
4123
                              which is not allowed in function arguments"),
4124
        PatKind::Slice(ref begin, ref mid, ref end) => {
4125 4126 4127
            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));
4128
            format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
4129
        },
C
Corey Richardson 已提交
4130 4131 4132
    }
}

O
Oliver Scherer 已提交
4133 4134 4135
fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
    match n.val {
        ConstValue::Unevaluated(def_id, _) => {
4136 4137
            if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
                print_const_expr(cx, cx.tcx.hir().body_owned_by(hir_id))
O
Oliver Schneider 已提交
4138 4139 4140 4141
            } else {
                inline::print_inlined_const(cx, def_id)
            }
        },
O
Oliver Scherer 已提交
4142
        _ => {
O
Oliver Schneider 已提交
4143
            let mut s = String::new();
G
Guillaume Gomez 已提交
4144
            ::rustc::mir::fmt_const_val(&mut s, n).expect("fmt_const_val failed");
O
Oliver Schneider 已提交
4145 4146 4147 4148 4149 4150 4151 4152 4153 4154
            // array lengths are obviously usize
            if s.ends_with("usize") {
                let n = s.len() - "usize".len();
                s.truncate(n);
            }
            s
        },
    }
}

4155
fn print_const_expr(cx: &DocContext<'_>, body: hir::BodyId) -> String {
L
ljedrz 已提交
4156
    cx.tcx.hir().hir_to_pretty_string(body.hir_id)
4157 4158
}

4159
/// Given a type Path, resolve it to a Type using the TyCtxt
4160
fn resolve_type(cx: &DocContext<'_>,
N
Niko Matsakis 已提交
4161
                path: Path,
L
ljedrz 已提交
4162 4163
                id: hir::HirId) -> Type {
    if id == hir::DUMMY_HIR_ID {
4164 4165 4166 4167
        debug!("resolve_type({:?})", path);
    } else {
        debug!("resolve_type({:?},{:?})", path, id);
    }
4168

4169 4170
    let is_generic = match path.res {
        Res::PrimTy(p) => match p {
4171 4172 4173 4174 4175 4176
            hir::Str => return Primitive(PrimitiveType::Str),
            hir::Bool => return Primitive(PrimitiveType::Bool),
            hir::Char => return Primitive(PrimitiveType::Char),
            hir::Int(int_ty) => return Primitive(int_ty.into()),
            hir::Uint(uint_ty) => return Primitive(uint_ty.into()),
            hir::Float(float_ty) => return Primitive(float_ty.into()),
C
Corey Richardson 已提交
4177
        },
4178
        Res::SelfTy(..) if path.segments.len() == 1 => {
V
Vadim Petrochenkov 已提交
4179
            return Generic(keywords::SelfUpper.name().to_string());
4180
        }
4181
        Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => {
4182 4183
            return Generic(format!("{:#}", path));
        }
4184 4185 4186
        Res::SelfTy(..)
        | Res::Def(DefKind::TyParam, _)
        | Res::Def(DefKind::AssociatedTy, _) => true,
4187
        _ => false,
4188
    };
4189
    let did = register_res(&*cx, path.res);
V
varkor 已提交
4190
    ResolvedPath { path: path, param_names: None, did: did, is_generic: is_generic }
4191 4192
}

4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207
pub fn register_res(cx: &DocContext<'_>, res: Res) -> DefId {
    debug!("register_res({:?})", res);

    let (did, kind) = match res {
        Res::Def(DefKind::Fn, i) => (i, TypeKind::Function),
        Res::Def(DefKind::TyAlias, i) => (i, TypeKind::Typedef),
        Res::Def(DefKind::Enum, i) => (i, TypeKind::Enum),
        Res::Def(DefKind::Trait, i) => (i, TypeKind::Trait),
        Res::Def(DefKind::Struct, i) => (i, TypeKind::Struct),
        Res::Def(DefKind::Union, i) => (i, TypeKind::Union),
        Res::Def(DefKind::Mod, i) => (i, TypeKind::Module),
        Res::Def(DefKind::ForeignTy, i) => (i, TypeKind::Foreign),
        Res::Def(DefKind::Const, i) => (i, TypeKind::Const),
        Res::Def(DefKind::Static, i) => (i, TypeKind::Static),
        Res::Def(DefKind::Variant, i) => (cx.tcx.parent(i).expect("cannot get parent def id"),
G
Guillaume Gomez 已提交
4208
                            TypeKind::Enum),
4209
        Res::Def(DefKind::Macro(mac_kind), i) => match mac_kind {
4210 4211 4212 4213 4214
            MacroKind::Bang => (i, TypeKind::Macro),
            MacroKind::Attr => (i, TypeKind::Attr),
            MacroKind::Derive => (i, TypeKind::Derive),
            MacroKind::ProcMacroStub => unreachable!(),
        },
4215 4216 4217 4218
        Res::Def(DefKind::TraitAlias, i) => (i, TypeKind::TraitAlias),
        Res::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
        Res::SelfTy(_, Some(impl_def_id)) => return impl_def_id,
        _ => return res.def_id()
C
Corey Richardson 已提交
4219
    };
N
Niko Matsakis 已提交
4220
    if did.is_local() { return did }
4221
    inline::record_extern_fqn(cx, did, kind);
4222
    if let TypeKind::Trait = kind {
4223
        inline::record_extern_trait(cx, did);
4224
    }
M
mitaa 已提交
4225
    did
C
Corey Richardson 已提交
4226
}
A
Alex Crichton 已提交
4227

4228
fn resolve_use_source(cx: &DocContext<'_>, path: Path) -> ImportSource {
A
Alex Crichton 已提交
4229
    ImportSource {
4230
        did: if path.res.opt_def_id().is_none() {
4231 4232
            None
        } else {
4233
            Some(register_res(cx, path.res))
4234
        },
4235
        path,
A
Alex Crichton 已提交
4236 4237 4238
    }
}

J
Jorge Aparicio 已提交
4239
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
4240
pub struct Macro {
4241
    pub source: String,
4242
    pub imported_from: Option<String>,
4243 4244 4245
}

impl Clean<Item> for doctree::Macro {
4246
    fn clean(&self, cx: &DocContext<'_>) -> Item {
4247
        let name = self.name.clean(cx);
4248
        Item {
4249
            name: Some(name.clone()),
4250 4251
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
J
Jeffrey Seyfried 已提交
4252
            visibility: Some(Public),
4253
            stability: self.stab.clean(cx),
4254
            deprecation: self.depr.clean(cx),
4255
            def_id: self.def_id,
4256
            inner: MacroItem(Macro {
4257
                source: format!("macro_rules! {} {{\n{}}}",
4258 4259 4260 4261
                                name,
                                self.matchers.iter().map(|span| {
                                    format!("    {} => {{ ... }};\n", span.to_src(cx))
                                }).collect::<String>()),
4262
                imported_from: self.imported_from.clean(cx),
4263 4264 4265 4266
            }),
        }
    }
}
4267

4268 4269 4270
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct ProcMacro {
    pub kind: MacroKind,
4271
    pub helpers: Vec<String>,
4272 4273 4274
}

impl Clean<Item> for doctree::ProcMacro {
4275
    fn clean(&self, cx: &DocContext<'_>) -> Item {
4276 4277 4278 4279 4280 4281 4282
        Item {
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
            visibility: Some(Public),
            stability: self.stab.clean(cx),
            deprecation: self.depr.clean(cx),
L
ljedrz 已提交
4283
            def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
4284 4285
            inner: ProcMacroItem(ProcMacro {
                kind: self.kind,
4286
                helpers: self.helpers.clean(cx),
4287 4288 4289 4290 4291
            }),
        }
    }
}

J
Jorge Aparicio 已提交
4292
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
4293
pub struct Stability {
V
Vadim Petrochenkov 已提交
4294
    pub level: stability::StabilityLevel,
4295
    pub feature: Option<String>,
4296
    pub since: String,
4297 4298 4299
    pub deprecation: Option<Deprecation>,
    pub unstable_reason: Option<String>,
    pub issue: Option<u32>,
4300 4301
}

4302 4303
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Deprecation {
4304 4305
    pub since: Option<String>,
    pub note: Option<String>,
4306 4307
}

4308
impl Clean<Stability> for attr::Stability {
4309
    fn clean(&self, _: &DocContext<'_>) -> Stability {
4310
        Stability {
V
Vadim Petrochenkov 已提交
4311
            level: stability::StabilityLevel::from_attr_level(&self.level),
4312
            feature: Some(self.feature.to_string()).filter(|f| !f.is_empty()),
V
Vadim Petrochenkov 已提交
4313 4314
            since: match self.level {
                attr::Stable {ref since} => since.to_string(),
4315
                _ => String::new(),
V
Vadim Petrochenkov 已提交
4316
            },
4317 4318 4319 4320 4321 4322
            deprecation: self.rustc_depr.as_ref().map(|d| {
                Deprecation {
                    note: Some(d.reason.to_string()).filter(|r| !r.is_empty()),
                    since: Some(d.since.to_string()).filter(|d| !d.is_empty()),
                }
            }),
4323
            unstable_reason: match self.level {
4324 4325
                attr::Unstable { reason: Some(ref reason), .. } => Some(reason.to_string()),
                _ => None,
V
Vadim Petrochenkov 已提交
4326 4327 4328 4329 4330
            },
            issue: match self.level {
                attr::Unstable {issue, ..} => Some(issue),
                _ => None,
            }
4331 4332 4333 4334 4335
        }
    }
}

impl<'a> Clean<Stability> for &'a attr::Stability {
4336
    fn clean(&self, dc: &DocContext<'_>) -> Stability {
V
Vadim Petrochenkov 已提交
4337
        (**self).clean(dc)
4338 4339
    }
}
A
Alex Crichton 已提交
4340

4341
impl Clean<Deprecation> for attr::Deprecation {
4342
    fn clean(&self, _: &DocContext<'_>) -> Deprecation {
4343
        Deprecation {
4344 4345
            since: self.since.map(|s| s.to_string()).filter(|s| !s.is_empty()),
            note: self.note.map(|n| n.to_string()).filter(|n| !n.is_empty()),
4346 4347 4348 4349
        }
    }
}

A
Alexander Regueiro 已提交
4350
/// An equality constraint on an associated type, e.g., `A = Bar` in `Foo<A = Bar>`
4351
#[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug, Hash)]
4352 4353 4354 4355 4356
pub struct TypeBinding {
    pub name: String,
    pub ty: Type
}

4357
impl Clean<TypeBinding> for hir::TypeBinding {
4358
    fn clean(&self, cx: &DocContext<'_>) -> TypeBinding {
4359
        TypeBinding {
4360
            name: self.ident.name.clean(cx),
4361 4362 4363 4364
            ty: self.ty.clean(cx)
        }
    }
}
4365

H
Hirokazu Hata 已提交
4366
pub fn def_id_to_path(
4367
    cx: &DocContext<'_>,
H
Hirokazu Hata 已提交
4368 4369 4370
    did: DefId,
    name: Option<String>
) -> Vec<String> {
4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383
    let crate_name = name.unwrap_or_else(|| cx.tcx.crate_name(did.krate).to_string());
    let relative = cx.tcx.def_path(did).data.into_iter().filter_map(|elem| {
        // extern blocks have an empty name
        let s = elem.data.to_string();
        if !s.is_empty() {
            Some(s)
        } else {
            None
        }
    });
    once(crate_name).chain(relative).collect()
}

4384
pub fn enter_impl_trait<F, R>(cx: &DocContext<'_>, f: F) -> R
4385 4386 4387
where
    F: FnOnce() -> R,
{
4388
    let old_bounds = mem::replace(&mut *cx.impl_trait_bounds.borrow_mut(), Default::default());
4389 4390 4391 4392 4393 4394
    let r = f();
    assert!(cx.impl_trait_bounds.borrow().is_empty());
    *cx.impl_trait_bounds.borrow_mut() = old_bounds;
    r
}

4395 4396
// Start of code copied from rust-clippy

4397
pub fn path_to_def_local(tcx: TyCtxt<'_, '_, '_>, path: &[Symbol]) -> Option<DefId> {
4398
    let krate = tcx.hir().krate();
4399 4400 4401 4402
    let mut items = krate.module.item_ids.clone();
    let mut path_it = path.iter().peekable();

    loop {
4403
        let segment = path_it.next()?;
4404 4405

        for item_id in mem::replace(&mut items, HirVec::new()).iter() {
4406
            let item = tcx.hir().expect_item_by_hir_id(item_id.id);
4407
            if item.ident.name == *segment {
4408
                if path_it.peek().is_none() {
4409
                    return Some(tcx.hir().local_def_id_from_hir_id(item_id.id))
4410 4411 4412
                }

                items = match &item.node {
C
csmoe 已提交
4413
                    &hir::ItemKind::Mod(ref m) => m.item_ids.clone(),
4414 4415 4416 4417 4418 4419 4420 4421
                    _ => panic!("Unexpected item {:?} in path {:?} path")
                };
                break;
            }
        }
    }
}

4422
pub fn path_to_def(tcx: TyCtxt<'_, '_, '_>, path: &[Symbol]) -> Option<DefId> {
4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437
    let crates = tcx.crates();

    let krate = crates
        .iter()
        .find(|&&krate| tcx.crate_name(krate) == path[0]);

    if let Some(krate) = krate {
        let krate = DefId {
            krate: *krate,
            index: CRATE_DEF_INDEX,
        };
        let mut items = tcx.item_children(krate);
        let mut path_it = path.iter().skip(1).peekable();

        loop {
4438
            let segment = path_it.next()?;
4439

4440
            for item in mem::replace(&mut items, Lrc::new(vec![])).iter() {
4441 4442
                if item.ident.name == *segment {
                    if path_it.peek().is_none() {
4443 4444
                        return match item.res {
                            def::Res::Def(DefKind::Trait, did) => Some(did),
A
Aaron Hill 已提交
4445
                            _ => None,
4446 4447 4448
                        }
                    }

4449
                    items = tcx.item_children(item.res.def_id());
4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474
                    break;
                }
            }
        }
    } else {
        None
    }
}

// End of code copied from rust-clippy

#[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
enum RegionTarget<'tcx> {
    Region(Region<'tcx>),
    RegionVid(RegionVid)
}

#[derive(Default, Debug, Clone)]
struct RegionDeps<'tcx> {
    larger: FxHashSet<RegionTarget<'tcx>>,
    smaller: FxHashSet<RegionTarget<'tcx>>
}

#[derive(Eq, PartialEq, Hash, Debug)]
enum SimpleBound {
V
varkor 已提交
4475 4476
    TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier),
    Outlives(Lifetime),
4477 4478
}

V
varkor 已提交
4479 4480
impl From<GenericBound> for SimpleBound {
    fn from(bound: GenericBound) -> Self {
4481
        match bound.clone() {
V
varkor 已提交
4482 4483
            GenericBound::Outlives(l) => SimpleBound::Outlives(l),
            GenericBound::TraitBound(t, mod_) => match t.trait_ {
V
varkor 已提交
4484
                Type::ResolvedPath { path, param_names, .. } => {
4485
                    SimpleBound::TraitBound(path.segments,
V
varkor 已提交
4486
                                            param_names
4487 4488 4489 4490 4491
                                                .map_or_else(|| Vec::new(), |v| v.iter()
                                                        .map(|p| SimpleBound::from(p.clone()))
                                                        .collect()),
                                            t.generic_params,
                                            mod_)
A
Aaron Hill 已提交
4492
                }
A
Aaron Hill 已提交
4493
                _ => panic!("Unexpected bound {:?}", bound),
4494 4495 4496 4497
            }
        }
    }
}