mod.rs 93.5 KB
Newer Older
C
Corey Richardson 已提交
1 2 3
//! This module contains the "cleaned" pieces of the AST, and the functions
//! that clean them.

4 5
pub mod inline;
pub mod cfg;
G
Guillaume Gomez 已提交
6
pub mod utils;
7 8
mod auto_trait;
mod blanket_impl;
9 10
mod simplify;
pub mod types;
S
Steven Fackler 已提交
11

12
use rustc_index::vec::{IndexVec, Idx};
13 14
use rustc_typeck::hir_ty_to_ty;
use rustc::infer::region_constraints::{RegionConstraintData, Constraint};
15
use rustc::middle::resolve_lifetime as rl;
16
use rustc::middle::lang_items;
17
use rustc::middle::stability;
C
Camille GILLOT 已提交
18
use rustc::mir::interpret::GlobalId;
19 20
use rustc::hir;
use rustc::hir::def::{CtorKind, DefKind, Res};
G
Guillaume Gomez 已提交
21
use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
22
use rustc::hir::ptr::P;
G
Guillaume Gomez 已提交
23
use rustc::ty::subst::InternalSubsts;
24
use rustc::ty::{self, TyCtxt, Ty, AdtKind};
25
use rustc::ty::fold::TypeFolder;
26
use rustc::util::nodemap::{FxHashMap, FxHashSet};
27
use syntax::ast::{self, Ident};
28
use syntax::attr;
G
Guillaume Gomez 已提交
29
use syntax_pos::symbol::{kw, sym};
30
use syntax_pos::hygiene::MacroKind;
31
use syntax_pos::{self, Pos};
32

33
use std::collections::hash_map::Entry;
34
use std::hash::Hash;
35
use std::default::Default;
36
use std::{mem, vec};
37
use std::rc::Rc;
38
use std::u32;
39

40
use crate::core::{self, DocContext, ImplTraitParam};
41 42
use crate::doctree;

G
Guillaume Gomez 已提交
43 44 45 46
use utils::*;

pub use utils::{get_auto_trait_and_blanket_impls, krate, register_res};

47 48 49 50 51 52 53
pub use self::types::*;
pub use self::types::Type::*;
pub use self::types::Mutability::*;
pub use self::types::ItemEnum::*;
pub use self::types::SelfTy::*;
pub use self::types::FunctionRetTy::*;
pub use self::types::Visibility::{Public, Inherited};
54 55

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

C
Corey Richardson 已提交
57
pub trait Clean<T> {
58
    fn clean(&self, cx: &DocContext<'_>) -> T;
C
Corey Richardson 已提交
59 60
}

61
impl<T: Clean<U>, U> Clean<Vec<U>> for [T] {
62
    fn clean(&self, cx: &DocContext<'_>) -> Vec<U> {
63
        self.iter().map(|x| x.clean(cx)).collect()
64 65 66
    }
}

67
impl<T: Clean<U>, U, V: Idx> Clean<IndexVec<V, U>> for IndexVec<V, T> {
68
    fn clean(&self, cx: &DocContext<'_>) -> IndexVec<V, U> {
69 70 71 72
        self.iter().map(|x| x.clean(cx)).collect()
    }
}

C
Camille GILLOT 已提交
73 74 75 76 77 78
impl<T: Clean<U>, U> Clean<U> for &T {
    fn clean(&self, cx: &DocContext<'_>) -> U {
        (**self).clean(cx)
    }
}

79
impl<T: Clean<U>, U> Clean<U> for P<T> {
80
    fn clean(&self, cx: &DocContext<'_>) -> U {
81
        (**self).clean(cx)
C
Corey Richardson 已提交
82 83 84
    }
}

85
impl<T: Clean<U>, U> Clean<U> for Rc<T> {
86
    fn clean(&self, cx: &DocContext<'_>) -> U {
87
        (**self).clean(cx)
88 89 90
    }
}

C
Corey Richardson 已提交
91
impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
92
    fn clean(&self, cx: &DocContext<'_>) -> Option<U> {
M
mitaa 已提交
93
        self.as_ref().map(|v| v.clean(cx))
C
Corey Richardson 已提交
94 95 96
    }
}

97
impl<T, U> Clean<U> for ty::Binder<T> where T: Clean<U> {
98
    fn clean(&self, cx: &DocContext<'_>) -> U {
99
        self.skip_binder().clean(cx)
100 101 102
    }
}

103
impl<T: Clean<U>, U> Clean<Vec<U>> for P<[T]> {
104
    fn clean(&self, cx: &DocContext<'_>) -> Vec<U> {
105
        self.iter().map(|x| x.clean(cx)).collect()
C
Corey Richardson 已提交
106 107 108
    }
}

A
Ariel Ben-Yehuda 已提交
109
impl Clean<ExternalCrate> for CrateNum {
110
    fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate {
111 112
        let root = DefId { krate: *self, index: CRATE_DEF_INDEX };
        let krate_span = cx.tcx.def_span(root);
D
Donato Sciarra 已提交
113
        let krate_src = cx.sess().source_map().span_to_filename(krate_span);
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131

        // 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.
132 133
        let as_primitive = |res: Res| {
            if let Res::Def(DefKind::Mod, def_id) = res {
134 135
                let attrs = cx.tcx.get_attrs(def_id).clean(cx);
                let mut prim = None;
136
                for attr in attrs.lists(sym::doc) {
137
                    if let Some(v) = attr.value_str() {
138
                        if attr.check_name(sym::primitive) {
139 140 141 142
                            prim = PrimitiveType::from_str(&v.as_str());
                            if prim.is_some() {
                                break;
                            }
143
                            // FIXME: should warn on unknown primitives?
144 145 146 147 148 149 150 151
                        }
                    }
                }
                return prim.map(|p| (def_id, p, attrs));
            }
            None
        };
        let primitives = if root.is_local() {
152
            cx.tcx.hir().krate().module.item_ids.iter().filter_map(|&id| {
153
                let item = cx.tcx.hir().expect_item(id.id);
V
varkor 已提交
154
                match item.kind {
C
csmoe 已提交
155
                    hir::ItemKind::Mod(_) => {
156
                        as_primitive(Res::Def(
157
                            DefKind::Mod,
158
                            cx.tcx.hir().local_def_id(id.id),
159
                        ))
160
                    }
C
csmoe 已提交
161
                    hir::ItemKind::Use(ref path, hir::UseKind::Single)
162
                    if item.vis.node.is_pub() => {
163
                        as_primitive(path.res).map(|(_, prim, attrs)| {
164
                            // Pretend the primitive is local.
165
                            (cx.tcx.hir().local_def_id(id.id), prim, attrs)
166 167 168 169 170 171
                        })
                    }
                    _ => None
                }
            }).collect()
        } else {
172
            cx.tcx.item_children(root).iter().map(|item| item.res)
173 174 175
              .filter_map(as_primitive).collect()
        };

176 177
        let as_keyword = |res: Res| {
            if let Res::Def(DefKind::Mod, def_id) = res {
G
Guillaume Gomez 已提交
178 179
                let attrs = cx.tcx.get_attrs(def_id).clean(cx);
                let mut keyword = None;
180
                for attr in attrs.lists(sym::doc) {
G
Guillaume Gomez 已提交
181
                    if let Some(v) = attr.value_str() {
182
                        if attr.check_name(sym::keyword) {
183 184 185
                            if v.is_doc_keyword() {
                                keyword = Some(v.to_string());
                                break;
G
Guillaume Gomez 已提交
186 187 188 189 190 191 192 193 194 195
                            }
                            // FIXME: should warn on unknown keywords?
                        }
                    }
                }
                return keyword.map(|p| (def_id, p, attrs));
            }
            None
        };
        let keywords = if root.is_local() {
196
            cx.tcx.hir().krate().module.item_ids.iter().filter_map(|&id| {
197
                let item = cx.tcx.hir().expect_item(id.id);
V
varkor 已提交
198
                match item.kind {
C
csmoe 已提交
199
                    hir::ItemKind::Mod(_) => {
200
                        as_keyword(Res::Def(
201
                            DefKind::Mod,
202
                            cx.tcx.hir().local_def_id(id.id),
203
                        ))
G
Guillaume Gomez 已提交
204
                    }
C
csmoe 已提交
205
                    hir::ItemKind::Use(ref path, hir::UseKind::Single)
206
                    if item.vis.node.is_pub() => {
207
                        as_keyword(path.res).map(|(_, prim, attrs)| {
208
                            (cx.tcx.hir().local_def_id(id.id), prim, attrs)
G
Guillaume Gomez 已提交
209 210 211 212 213 214
                        })
                    }
                    _ => None
                }
            }).collect()
        } else {
215
            cx.tcx.item_children(root).iter().map(|item| item.res)
G
Guillaume Gomez 已提交
216 217 218
              .filter_map(as_keyword).collect()
        };

219
        ExternalCrate {
220
            name: cx.tcx.crate_name(*self).to_string(),
221
            src: krate_src,
222
            attrs: cx.tcx.get_attrs(root).clean(cx),
223
            primitives,
G
Guillaume Gomez 已提交
224
            keywords,
C
Corey Richardson 已提交
225 226 227 228
        }
    }
}

229
impl Clean<Item> for doctree::Module<'_> {
230
    fn clean(&self, cx: &DocContext<'_>) -> Item {
C
Corey Richardson 已提交
231
        let name = if self.name.is_some() {
G
Guillaume Gomez 已提交
232
            self.name.expect("No name provided").clean(cx)
C
Corey Richardson 已提交
233
        } else {
234
            String::new()
C
Corey Richardson 已提交
235
        };
236

237 238 239
        // 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
240
        let attrs = self.attrs.clean(cx);
M
Manish Goregaokar 已提交
241

242
        let mut items: Vec<Item> = vec![];
D
DebugSteven 已提交
243
        items.extend(self.extern_crates.iter().flat_map(|x| x.clean(cx)));
244
        items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
245 246 247
        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)));
248
        items.extend(self.fns.iter().map(|x| x.clean(cx)));
249
        items.extend(self.foreigns.iter().map(|x| x.clean(cx)));
250 251
        items.extend(self.mods.iter().map(|x| x.clean(cx)));
        items.extend(self.typedefs.iter().map(|x| x.clean(cx)));
V
varkor 已提交
252
        items.extend(self.opaque_tys.iter().map(|x| x.clean(cx)));
253 254 255
        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)));
256
        items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
257
        items.extend(self.macros.iter().map(|x| x.clean(cx)));
258
        items.extend(self.proc_macros.iter().map(|x| x.clean(cx)));
259
        items.extend(self.trait_aliases.iter().map(|x| x.clean(cx)));
260 261 262

        // determine if we should display the inner contents or
        // the outer `mod` item for the source code.
263
        let whence = {
D
Donato Sciarra 已提交
264
            let cm = cx.sess().source_map();
265 266
            let outer = cm.lookup_char_pos(self.where_outer.lo());
            let inner = cm.lookup_char_pos(self.where_inner.lo());
267 268 269 270
            if outer.file.start_pos == inner.file.start_pos {
                // mod foo { ... }
                self.where_outer
            } else {
D
Donato Sciarra 已提交
271
                // mod foo; (and a separate SourceFile for the contents)
272 273 274 275
                self.where_inner
            }
        };

C
Corey Richardson 已提交
276 277
        Item {
            name: Some(name),
278
            attrs,
279 280
            source: whence.clean(cx),
            visibility: self.vis.clean(cx),
281 282 283
            stability: cx.stability(self.id).clean(cx),
            deprecation: cx.deprecation(self.id).clean(cx),
            def_id: cx.tcx.hir().local_def_id(self.id),
C
Corey Richardson 已提交
284
            inner: ModuleItem(Module {
285
               is_crate: self.is_crate,
286
               items,
C
Corey Richardson 已提交
287 288 289 290 291
            })
        }
    }
}

292
impl Clean<Attributes> for [ast::Attribute] {
293
    fn clean(&self, cx: &DocContext<'_>) -> Attributes {
294
        Attributes::from_ast(cx.sess().diagnostic(), self)
C
Corey Richardson 已提交
295 296 297
    }
}

V
varkor 已提交
298
impl Clean<GenericBound> for hir::GenericBound {
299
    fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
C
Corey Richardson 已提交
300
        match *self {
V
varkor 已提交
301 302 303 304
            hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)),
            hir::GenericBound::Trait(ref t, modifier) => {
                GenericBound::TraitBound(t.clean(cx), modifier)
            }
C
Corey Richardson 已提交
305 306 307 308
        }
    }
}

V
varkor 已提交
309
impl<'a, 'tcx> Clean<GenericBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>) {
310
    fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
311 312
        let (trait_ref, ref bounds) = *self;
        inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait);
313
        let path = external_path(cx, cx.tcx.item_name(trait_ref.def_id),
314
                                 Some(trait_ref.def_id), true, bounds.clone(), trait_ref.substs);
315

316
        debug!("ty::TraitRef\n  subst: {:?}\n", trait_ref.substs);
317 318 319

        // collect any late bound regions
        let mut late_bounds = vec![];
320
        for ty_s in trait_ref.input_types().skip(1) {
V
varkor 已提交
321
            if let ty::Tuple(ts) = ty_s.kind {
322
                for &ty_s in ts {
V
varkor 已提交
323
                    if let ty::Ref(ref reg, _, _) = ty_s.expect_ty().kind {
N
Niko Matsakis 已提交
324
                        if let &ty::RegionKind::ReLateBound(..) = *reg {
325
                            debug!("  hit an ReLateBound {:?}", reg);
326 327 328 329 330
                            if let Some(Lifetime(name)) = reg.clean(cx) {
                                late_bounds.push(GenericParamDef {
                                    name,
                                    kind: GenericParamDefKind::Lifetime,
                                });
331 332 333 334 335 336 337
                            }
                        }
                    }
                }
            }
        }

V
varkor 已提交
338
        GenericBound::TraitBound(
339 340
            PolyTrait {
                trait_: ResolvedPath {
341
                    path,
V
varkor 已提交
342
                    param_names: None,
343
                    did: trait_ref.def_id,
344 345
                    is_generic: false,
                },
346
                generic_params: late_bounds,
347
            },
348 349
            hir::TraitBoundModifier::None
        )
350 351 352
    }
}

V
varkor 已提交
353
impl<'tcx> Clean<GenericBound> for ty::TraitRef<'tcx> {
354
    fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
355 356 357 358
        (self, vec![]).clean(cx)
    }
}

C
csmoe 已提交
359
impl<'tcx> Clean<Option<Vec<GenericBound>>> for InternalSubsts<'tcx> {
360
    fn clean(&self, cx: &DocContext<'_>) -> Option<Vec<GenericBound>> {
361
        let mut v = Vec::new();
V
varkor 已提交
362 363
        v.extend(self.regions().filter_map(|r| r.clean(cx)).map(GenericBound::Outlives));
        v.extend(self.types().map(|t| GenericBound::TraitBound(PolyTrait {
364
            trait_: t.clean(cx),
365
            generic_params: Vec::new(),
366
        }, hir::TraitBoundModifier::None)));
367
        if !v.is_empty() {Some(v)} else {None}
368 369 370
    }
}

371
impl Clean<Lifetime> for hir::Lifetime {
372
    fn clean(&self, cx: &DocContext<'_>) -> Lifetime {
L
ljedrz 已提交
373
        if self.hir_id != hir::DUMMY_HIR_ID {
374
            let def = cx.tcx.named_region(self.hir_id);
375 376 377 378 379 380 381
            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 已提交
382
                }
383
                _ => {}
E
Eduard Burtescu 已提交
384 385
            }
        }
386
        Lifetime(self.name.ident().to_string())
C
Corey Richardson 已提交
387 388 389
    }
}

V
varkor 已提交
390
impl Clean<Lifetime> for hir::GenericParam {
391
    fn clean(&self, _: &DocContext<'_>) -> Lifetime {
V
varkor 已提交
392
        match self.kind {
V
varkor 已提交
393 394 395
            hir::GenericParamKind::Lifetime { .. } => {
                if self.bounds.len() > 0 {
                    let mut bounds = self.bounds.iter().map(|bound| match bound {
V
varkor 已提交
396
                        hir::GenericBound::Outlives(lt) => lt,
V
varkor 已提交
397 398
                        _ => panic!(),
                    });
G
Guillaume Gomez 已提交
399
                    let name = bounds.next().expect("no more bounds").name.ident();
400
                    let mut s = format!("{}: {}", self.name.ident(), name);
V
varkor 已提交
401
                    for bound in bounds {
402
                        s.push_str(&format!(" + {}", bound.name.ident()));
V
varkor 已提交
403 404 405
                    }
                    Lifetime(s)
                } else {
406
                    Lifetime(self.name.ident().to_string())
V
varkor 已提交
407
                }
408
            }
V
varkor 已提交
409
            _ => panic!(),
410
        }
411 412 413
    }
}

V
varkor 已提交
414
impl Clean<Constant> for hir::ConstArg {
415
    fn clean(&self, cx: &DocContext<'_>) -> Constant {
V
varkor 已提交
416 417 418 419 420 421 422
        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),
        }
    }
}

423
impl Clean<Lifetime> for ty::GenericParamDef {
424
    fn clean(&self, _cx: &DocContext<'_>) -> Lifetime {
425
        Lifetime(self.name.to_string())
426 427 428
    }
}

429
impl Clean<Option<Lifetime>> for ty::RegionKind {
430
    fn clean(&self, cx: &DocContext<'_>) -> Option<Lifetime> {
431
        match *self {
432
            ty::ReStatic => Some(Lifetime::statik()),
433
            ty::ReLateBound(_, ty::BrNamed(_, name)) => Some(Lifetime(name.to_string())),
N
Niko Matsakis 已提交
434
            ty::ReEarlyBound(ref data) => Some(Lifetime(data.name.clean(cx))),
435 436 437 438

            ty::ReLateBound(..) |
            ty::ReFree(..) |
            ty::ReScope(..) |
439
            ty::ReVar(..) |
N
Niko Matsakis 已提交
440
            ty::RePlaceholder(..) |
441
            ty::ReEmpty |
442
            ty::ReClosureBound(_) |
443
            ty::ReErased => {
444
                debug!("cannot clean region {:?}", self);
445 446
                None
            }
447 448 449 450
        }
    }
}

451
impl Clean<WherePredicate> for hir::WherePredicate {
452
    fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
N
Nick Cameron 已提交
453
        match *self {
454
            hir::WherePredicate::BoundPredicate(ref wbp) => {
455
                WherePredicate::BoundPredicate {
456
                    ty: wbp.bounded_ty.clean(cx),
N
Nick Cameron 已提交
457 458 459
                    bounds: wbp.bounds.clean(cx)
                }
            }
460

461
            hir::WherePredicate::RegionPredicate(ref wrp) => {
462 463 464 465 466 467
                WherePredicate::RegionPredicate {
                    lifetime: wrp.lifetime.clean(cx),
                    bounds: wrp.bounds.clean(cx)
                }
            }

468 469 470 471 472
            hir::WherePredicate::EqPredicate(ref wrp) => {
                WherePredicate::EqPredicate {
                    lhs: wrp.lhs_ty.clean(cx),
                    rhs: wrp.rhs_ty.clean(cx)
                }
N
Nick Cameron 已提交
473
            }
474 475 476 477
        }
    }
}

478
impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
479
    fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
480
        use rustc::ty::Predicate;
481 482

        match *self {
483 484
            Predicate::Trait(ref pred) => Some(pred.clean(cx)),
            Predicate::Subtype(ref pred) => Some(pred.clean(cx)),
485 486
            Predicate::RegionOutlives(ref pred) => pred.clean(cx),
            Predicate::TypeOutlives(ref pred) => pred.clean(cx),
487
            Predicate::Projection(ref pred) => Some(pred.clean(cx)),
488 489 490 491

            Predicate::WellFormed(..) |
            Predicate::ObjectSafe(..) |
            Predicate::ClosureKind(..) |
492
            Predicate::ConstEvaluatable(..) => panic!("not user writable"),
493 494 495 496 497
        }
    }
}

impl<'a> Clean<WherePredicate> for ty::TraitPredicate<'a> {
498
    fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
499
        WherePredicate::BoundPredicate {
500
            ty: self.trait_ref.self_ty().clean(cx),
501 502 503 504 505
            bounds: vec![self.trait_ref.clean(cx)]
        }
    }
}

N
Niko Matsakis 已提交
506
impl<'tcx> Clean<WherePredicate> for ty::SubtypePredicate<'tcx> {
507
    fn clean(&self, _cx: &DocContext<'_>) -> WherePredicate {
508 509
        panic!("subtype predicates are an internal rustc artifact \
                and should not be seen by rustdoc")
N
Niko Matsakis 已提交
510 511 512
    }
}

513 514 515
impl<'tcx> Clean<Option<WherePredicate>> for
    ty::OutlivesPredicate<ty::Region<'tcx>,ty::Region<'tcx>> {

516
    fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
517
        let ty::OutlivesPredicate(ref a, ref b) = *self;
518 519 520 521 522 523 524 525 526

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

        Some(WherePredicate::RegionPredicate {
G
Guillaume Gomez 已提交
527 528
            lifetime: a.clean(cx).expect("failed to clean lifetime"),
            bounds: vec![GenericBound::Outlives(b.clean(cx).expect("failed to clean bounds"))]
529
        })
530 531 532
    }
}

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

537 538 539 540 541 542
        match lt {
            ty::ReEmpty => return None,
            _ => {}
        }

        Some(WherePredicate::BoundPredicate {
543
            ty: ty.clean(cx),
G
Guillaume Gomez 已提交
544
            bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))]
545
        })
546 547 548 549
    }
}

impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
550
    fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
551 552 553 554 555 556 557 558
        WherePredicate::EqPredicate {
            lhs: self.projection_ty.clean(cx),
            rhs: self.ty.clean(cx)
        }
    }
}

impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
559
    fn clean(&self, cx: &DocContext<'_>) -> Type {
560
        let trait_ = match self.trait_ref(cx.tcx).clean(cx) {
V
varkor 已提交
561 562
            GenericBound::TraitBound(t, _) => t.trait_,
            GenericBound::Outlives(_) => panic!("cleaning a trait got a lifetime"),
563 564
        };
        Type::QPath {
565
            name: cx.tcx.associated_item(self.item_def_id).ident.name.clean(cx),
566
            self_type: box self.self_ty().clean(cx),
567 568 569 570 571
            trait_: box trait_
        }
    }
}

572
impl Clean<GenericParamDef> for ty::GenericParamDef {
573
    fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
574 575 576 577
        let (name, kind) = match self.kind {
            ty::GenericParamDefKind::Lifetime => {
                (self.name.to_string(), GenericParamDefKind::Lifetime)
            }
578
            ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
579 580 581 582 583 584 585 586 587
                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,
588
                    synthetic,
589 590
                })
            }
591
            ty::GenericParamDefKind::Const { .. } => {
592 593 594 595
                (self.name.clean(cx), GenericParamDefKind::Const {
                    did: self.def_id,
                    ty: cx.tcx.type_of(self.def_id).clean(cx),
                })
596
            }
597 598 599 600 601
        };

        GenericParamDef {
            name,
            kind,
602 603 604 605
        }
    }
}

V
varkor 已提交
606
impl Clean<GenericParamDef> for hir::GenericParam {
607
    fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
608
        let (name, kind) = match self.kind {
V
varkor 已提交
609 610 611
            hir::GenericParamKind::Lifetime { .. } => {
                let name = if self.bounds.len() > 0 {
                    let mut bounds = self.bounds.iter().map(|bound| match bound {
V
varkor 已提交
612
                        hir::GenericBound::Outlives(lt) => lt,
V
varkor 已提交
613 614
                        _ => panic!(),
                    });
G
Guillaume Gomez 已提交
615
                    let name = bounds.next().expect("no more bounds").name.ident();
V
Vadim Petrochenkov 已提交
616
                    let mut s = format!("{}: {}", self.name.ident(), name);
V
varkor 已提交
617
                    for bound in bounds {
V
Vadim Petrochenkov 已提交
618
                        s.push_str(&format!(" + {}", bound.name.ident()));
619 620 621
                    }
                    s
                } else {
V
Vadim Petrochenkov 已提交
622
                    self.name.ident().to_string()
623 624 625
                };
                (name, GenericParamDefKind::Lifetime)
            }
V
varkor 已提交
626
            hir::GenericParamKind::Type { ref default, synthetic } => {
V
Vadim Petrochenkov 已提交
627
                (self.name.ident().name.clean(cx), GenericParamDefKind::Type {
628
                    did: cx.tcx.hir().local_def_id(self.hir_id),
V
varkor 已提交
629
                    bounds: self.bounds.clean(cx),
630
                    default: default.clean(cx),
631
                    synthetic,
632
                })
V
varkor 已提交
633
            }
V
varkor 已提交
634 635
            hir::GenericParamKind::Const { ref ty } => {
                (self.name.ident().name.clean(cx), GenericParamDefKind::Const {
636
                    did: cx.tcx.hir().local_def_id(self.hir_id),
V
varkor 已提交
637 638 639
                    ty: ty.clean(cx),
                })
            }
640 641 642 643 644
        };

        GenericParamDef {
            name,
            kind,
645 646 647 648
        }
    }
}

649
impl Clean<Generics> for hir::Generics {
650
    fn clean(&self, cx: &DocContext<'_>) -> Generics {
651 652 653 654
        // 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 已提交
655 656 657 658 659
            match param.kind {
                hir::GenericParamKind::Type { synthetic, .. } => {
                    synthetic == Some(hir::SyntheticTyParamKind::ImplTrait)
                }
                _ => false,
660 661 662 663
            }
        }
        let impl_trait_params = self.params
            .iter()
664 665 666 667 668 669
            .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, .. } => {
670
                        cx.impl_trait_bounds.borrow_mut().insert(did.into(), bounds.clone());
671
                    }
V
varkor 已提交
672
                    GenericParamDefKind::Const { .. } => unreachable!(),
673
                }
674
                param
675 676 677
            })
            .collect::<Vec<_>>();

678
        let mut params = Vec::with_capacity(self.params.len());
679
        for p in self.params.iter().filter(|p| !is_impl_trait(p)) {
680 681 682
            let p = p.clean(cx);
            params.push(p);
        }
683 684
        params.extend(impl_trait_params);

685
        let mut generics = Generics {
686
            params,
687
            where_predicates: self.where_clause.predicates.clean(cx),
688 689 690 691 692
        };

        // 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.
693
        for where_pred in &mut generics.where_predicates {
694 695 696
            match *where_pred {
                WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => {
                    if bounds.is_empty() {
697 698 699 700 701 702 703 704
                        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
                                    }
705
                                }
V
varkor 已提交
706
                                GenericParamDefKind::Const { .. } => {}
707 708 709 710 711 712
                            }
                        }
                    }
                }
                _ => continue,
            }
C
Corey Richardson 已提交
713
        }
714
        generics
C
Corey Richardson 已提交
715 716 717
    }
}

718
impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx>) {
719
    fn clean(&self, cx: &DocContext<'_>) -> Generics {
720
        use self::WherePredicate as WP;
721
        use std::collections::BTreeMap;
722

723
        let (gens, preds) = *self;
724

725 726
        // Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
        // since `Clean for ty::Predicate` would consume them.
727
        let mut impl_trait = BTreeMap::<ImplTraitParam, Vec<GenericBound>>::default();
728

729 730 731
        // Bounds in the type_params and lifetimes fields are repeated in the
        // predicates field (see rustc_typeck::collect::ty_generics), so remove
        // them.
732 733 734 735
        let stripped_typarams = gens.params.iter()
            .filter_map(|param| match param.kind {
                ty::GenericParamDefKind::Lifetime => None,
                ty::GenericParamDefKind::Type { synthetic, .. } => {
736
                    if param.name == kw::SelfUpper {
737 738 739 740 741 742 743 744
                        assert_eq!(param.index, 0);
                        return None;
                    }
                    if synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) {
                        impl_trait.insert(param.index.into(), vec![]);
                        return None;
                    }
                    Some(param.clean(cx))
V
varkor 已提交
745
                }
746 747
                ty::GenericParamDefKind::Const { .. } => None,
            }).collect::<Vec<GenericParamDef>>();
748

S
Shotaro Yamada 已提交
749 750 751
        // param index -> [(DefId of trait, associated type name, type)]
        let mut impl_trait_proj =
            FxHashMap::<u32, Vec<(DefId, String, Ty<'tcx>)>>::default();
752

753
        let where_predicates = preds.predicates.iter()
754
            .flat_map(|(p, _)| {
S
Shotaro Yamada 已提交
755
                let mut projection = None;
756 757
                let param_idx = (|| {
                    if let Some(trait_ref) = p.to_opt_poly_trait_ref() {
V
varkor 已提交
758
                        if let ty::Param(param) = trait_ref.self_ty().kind {
759 760 761
                            return Some(param.index);
                        }
                    } else if let Some(outlives) = p.to_opt_type_outlives() {
V
varkor 已提交
762
                        if let ty::Param(param) = outlives.skip_binder().0.kind {
763 764
                            return Some(param.index);
                        }
S
Shotaro Yamada 已提交
765
                    } else if let ty::Predicate::Projection(p) = p {
V
varkor 已提交
766
                        if let ty::Param(param) = p.skip_binder().projection_ty.self_ty().kind {
S
Shotaro Yamada 已提交
767
                            projection = Some(p);
768 769
                            return Some(param.index);
                        }
770
                    }
771

772
                    None
773
                })();
774

775 776
                if let Some(param_idx) = param_idx {
                    if let Some(b) = impl_trait.get_mut(&param_idx.into()) {
777 778
                        let p = p.clean(cx)?;

779 780 781 782 783 784 785 786
                        b.extend(
                            p.get_bounds()
                                .into_iter()
                                .flatten()
                                .cloned()
                                .filter(|b| !b.is_sized_bound(cx))
                        );

S
Shotaro Yamada 已提交
787 788 789 790 791
                        let proj = projection
                            .map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().ty));
                        if let Some(((_, trait_did, name), rhs)) =
                            proj.as_ref().and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs)))
                        {
792
                            impl_trait_proj
S
Shotaro Yamada 已提交
793
                                .entry(param_idx)
794
                                .or_default()
S
Shotaro Yamada 已提交
795
                                .push((trait_did, name.to_string(), rhs));
796 797 798 799
                        }

                        return None;
                    }
800 801 802 803
                }

                Some(p)
            })
804
            .collect::<Vec<_>>();
805

806 807
        for (param, mut bounds) in impl_trait {
            // Move trait bounds to the front.
808 809 810 811 812 813
            bounds.sort_by_key(|b| if let GenericBound::TraitBound(..) = b {
                false
            } else {
                true
            });

S
Shotaro Yamada 已提交
814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831
            if let crate::core::ImplTraitParam::ParamIndex(idx) = param {
                if let Some(proj) = impl_trait_proj.remove(&idx) {
                    for (trait_did, name, rhs) in proj {
                        simplify::merge_bounds(
                            cx,
                            &mut bounds,
                            trait_did,
                            &name,
                            &rhs.clean(cx),
                        );
                    }
                }
            } else {
                unreachable!();
            }

            cx.impl_trait_bounds.borrow_mut().insert(param, bounds);
        }
832

833 834 835 836 837 838 839
        // Now that `cx.impl_trait_bounds` is populated, we can process
        // remaining predicates which could contain `impl Trait`.
        let mut where_predicates = where_predicates
            .into_iter()
            .flat_map(|p| p.clean(cx))
            .collect::<Vec<_>>();

840
        // Type parameters and have a Sized bound by default unless removed with
841
        // ?Sized. Scan through the predicates and mark any type parameter with
842
        // a Sized bound, removing the bounds as we find them.
843 844
        //
        // Note that associated types also have a sized bound by default, but we
845
        // don't actually know the set of associated types right here so that's
846
        // handled in cleaning associated types
847
        let mut sized_params = FxHashSet::default();
848 849 850 851 852 853 854 855 856
        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
                    }
857
                }
858
                _ => true,
859
            }
860
        });
861

862
        // Run through the type parameters again and insert a ?Sized
863
        // unbound for any we didn't find to be Sized.
864
        for tp in &stripped_typarams {
865 866 867
            if !sized_params.contains(&tp.name) {
                where_predicates.push(WP::BoundPredicate {
                    ty: Type::Generic(tp.name.clone()),
V
varkor 已提交
868
                    bounds: vec![GenericBound::maybe_sized(cx)],
869 870 871 872 873
                })
            }
        }

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

877
        Generics {
V
varkor 已提交
878 879
            params: gens.params
                        .iter()
880
                        .flat_map(|param| match param.kind {
881
                            ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
882
                            ty::GenericParamDefKind::Type { .. } => None,
883
                            ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)),
884
                        }).chain(simplify::ty_params(stripped_typarams).into_iter())
V
varkor 已提交
885
                        .collect(),
886
            where_predicates: simplify::where_clauses(cx, where_predicates),
887 888 889 890
        }
    }
}

M
Mazdak Farrokhzad 已提交
891
impl<'a> Clean<Method> for (&'a hir::FnSig, &'a hir::Generics, hir::BodyId,
892
                            Option<hir::Defaultness>) {
893
    fn clean(&self, cx: &DocContext<'_>) -> Method {
894 895 896
        let (generics, decl) = enter_impl_trait(cx, || {
            (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx))
        });
897
        let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
898
        Method {
899
            decl,
900
            generics,
W
Without Boats 已提交
901
            header: self.0.header,
902
            defaultness: self.3,
903
            all_types,
904
            ret_types,
C
Corey Richardson 已提交
905 906 907 908
        }
    }
}

909
impl Clean<Item> for doctree::Function<'_> {
910
    fn clean(&self, cx: &DocContext<'_>) -> Item {
911
        let (generics, decl) = enter_impl_trait(cx, || {
912
            (self.generics.clean(cx), (self.decl, self.body).clean(cx))
913
        });
G
Guillaume Gomez 已提交
914

915
        let did = cx.tcx.hir().local_def_id(self.id);
G
Guillaume Gomez 已提交
916 917 918 919 920
        let constness = if cx.tcx.is_min_const_fn(did) {
            hir::Constness::Const
        } else {
            hir::Constness::NotConst
        };
921
        let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
C
Corey Richardson 已提交
922
        Item {
923 924 925 926
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
            visibility: self.vis.clean(cx),
927
            stability: cx.stability(self.id).clean(cx),
928
            deprecation: cx.deprecation(self.id).clean(cx),
G
Guillaume Gomez 已提交
929
            def_id: did,
C
Corey Richardson 已提交
930
            inner: FunctionItem(Function {
931 932
                decl,
                generics,
G
Guillaume Gomez 已提交
933
                header: hir::FnHeader { constness, ..self.header },
934
                all_types,
935
                ret_types,
C
Corey Richardson 已提交
936 937 938 939 940
            }),
        }
    }
}

941
impl<'a> Clean<Arguments> for (&'a [hir::Ty], &'a [ast::Ident]) {
942
    fn clean(&self, cx: &DocContext<'_>) -> Arguments {
943 944
        Arguments {
            values: self.0.iter().enumerate().map(|(i, ty)| {
945
                let mut name = self.1.get(i).map(|ident| ident.to_string())
946 947 948 949 950
                                            .unwrap_or(String::new());
                if name.is_empty() {
                    name = "_".to_string();
                }
                Argument {
951
                    name,
952 953 954 955 956 957 958
                    type_: ty.clean(cx),
                }
            }).collect()
        }
    }
}

O
Oliver Schneider 已提交
959
impl<'a> Clean<Arguments> for (&'a [hir::Ty], hir::BodyId) {
960
    fn clean(&self, cx: &DocContext<'_>) -> Arguments {
961
        let body = cx.tcx.hir().body(self.1);
962 963 964 965

        Arguments {
            values: self.0.iter().enumerate().map(|(i, ty)| {
                Argument {
966
                    name: name_from_pat(&body.params[i].pat),
967 968 969 970 971 972 973 974
                    type_: ty.clean(cx),
                }
            }).collect()
        }
    }
}

impl<'a, A: Copy> Clean<FnDecl> for (&'a hir::FnDecl, A)
O
Oliver Schneider 已提交
975
    where (&'a [hir::Ty], A): Clean<Arguments>
976
{
977
    fn clean(&self, cx: &DocContext<'_>) -> FnDecl {
C
Corey Richardson 已提交
978
        FnDecl {
979 980
            inputs: (&self.0.inputs[..], self.1).clean(cx),
            output: self.0.output.clean(cx),
981
            c_variadic: self.0.c_variadic,
982
            attrs: Attributes::default(),
C
Corey Richardson 已提交
983 984 985 986
        }
    }
}

987
impl<'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
988
    fn clean(&self, cx: &DocContext<'_>) -> FnDecl {
989
        let (did, sig) = *self;
990
        let mut names = if cx.tcx.hir().as_local_hir_id(did).is_some() {
991
            vec![].into_iter()
992
        } else {
A
achernyak 已提交
993
            cx.tcx.fn_arg_names(did).into_iter()
S
Cleanup  
Shotaro Yamada 已提交
994 995
        };

996
        FnDecl {
997
            output: Return(sig.skip_binder().output().clean(cx)),
998
            attrs: Attributes::default(),
999
            c_variadic: sig.skip_binder().c_variadic,
1000
            inputs: Arguments {
1001
                values: sig.skip_binder().inputs().iter().map(|t| {
1002
                    Argument {
1003
                        type_: t.clean(cx),
1004
                        name: names.next().map_or(String::new(), |name| name.to_string()),
1005 1006 1007 1008 1009 1010 1011
                    }
                }).collect(),
            },
        }
    }
}

1012
impl Clean<FunctionRetTy> for hir::FunctionRetTy {
1013
    fn clean(&self, cx: &DocContext<'_>) -> FunctionRetTy {
C
Corey Richardson 已提交
1014
        match *self {
1015 1016
            hir::Return(ref typ) => Return(typ.clean(cx)),
            hir::DefaultReturn(..) => DefaultReturn,
C
Corey Richardson 已提交
1017 1018 1019 1020
        }
    }
}

1021
impl Clean<Item> for doctree::Trait<'_> {
1022
    fn clean(&self, cx: &DocContext<'_>) -> Item {
1023
        let attrs = self.attrs.clean(cx);
1024
        let is_spotlight = attrs.has_doc_flag(sym::spotlight);
C
Corey Richardson 已提交
1025
        Item {
1026
            name: Some(self.name.clean(cx)),
1027
            attrs,
1028
            source: self.whence.clean(cx),
1029
            def_id: cx.tcx.hir().local_def_id(self.id),
1030
            visibility: self.vis.clean(cx),
1031
            stability: cx.stability(self.id).clean(cx),
1032
            deprecation: cx.deprecation(self.id).clean(cx),
C
Corey Richardson 已提交
1033
            inner: TraitItem(Trait {
1034
                auto: self.is_auto.clean(cx),
1035
                unsafety: self.unsafety,
1036
                items: self.items.iter().map(|ti| ti.clean(cx)).collect(),
1037 1038
                generics: self.generics.clean(cx),
                bounds: self.bounds.clean(cx),
1039
                is_spotlight,
1040
                is_auto: self.is_auto.clean(cx),
C
Corey Richardson 已提交
1041 1042 1043 1044 1045
            }),
        }
    }
}

1046
impl Clean<Item> for doctree::TraitAlias<'_> {
1047
    fn clean(&self, cx: &DocContext<'_>) -> Item {
1048 1049 1050 1051 1052
        let attrs = self.attrs.clean(cx);
        Item {
            name: Some(self.name.clean(cx)),
            attrs,
            source: self.whence.clean(cx),
1053
            def_id: cx.tcx.hir().local_def_id(self.id),
1054
            visibility: self.vis.clean(cx),
1055
            stability: cx.stability(self.id).clean(cx),
1056
            deprecation: cx.deprecation(self.id).clean(cx),
1057 1058 1059 1060 1061 1062 1063 1064
            inner: TraitAliasItem(TraitAlias {
                generics: self.generics.clean(cx),
                bounds: self.bounds.clean(cx),
            }),
        }
    }
}

1065
impl Clean<bool> for hir::IsAuto {
1066
    fn clean(&self, _: &DocContext<'_>) -> bool {
1067 1068 1069 1070 1071 1072 1073
        match *self {
            hir::IsAuto::Yes => true,
            hir::IsAuto::No => false,
        }
    }
}

1074
impl Clean<Type> for hir::TraitRef {
1075
    fn clean(&self, cx: &DocContext<'_>) -> Type {
L
ljedrz 已提交
1076
        resolve_type(cx, self.path.clean(cx), self.hir_ref_id)
C
Corey Richardson 已提交
1077 1078 1079
    }
}

1080
impl Clean<PolyTrait> for hir::PolyTraitRef {
1081
    fn clean(&self, cx: &DocContext<'_>) -> PolyTrait {
1082 1083
        PolyTrait {
            trait_: self.trait_ref.clean(cx),
1084
            generic_params: self.bound_generic_params.clean(cx)
1085
        }
N
Niko Matsakis 已提交
1086 1087 1088
    }
}

C
Camille GILLOT 已提交
1089
impl Clean<Item> for hir::TraitItem<'_> {
1090
    fn clean(&self, cx: &DocContext<'_>) -> Item {
1091
        let inner = match self.kind {
1092
            hir::TraitItemKind::Const(ref ty, default) => {
A
Andrew Xu 已提交
1093
                AssocConstItem(ty.clean(cx),
1094
                                    default.map(|e| print_const_expr(cx, e)))
1095
            }
1096
            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
1097
                MethodItem((sig, &self.generics, body, None).clean(cx))
1098
            }
1099
            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => {
1100 1101 1102
                let (generics, decl) = enter_impl_trait(cx, || {
                    (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
                });
1103
                let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
1104
                TyMethodItem(TyMethod {
W
Without Boats 已提交
1105
                    header: sig.header,
1106
                    decl,
1107
                    generics,
1108
                    all_types,
1109
                    ret_types,
1110
                })
1111
            }
1112
            hir::TraitItemKind::Type(ref bounds, ref default) => {
A
Andrew Xu 已提交
1113
                AssocTypeItem(bounds.clean(cx), default.clean(cx))
1114 1115
            }
        };
1116
        let local_did = cx.tcx.hir().local_def_id(self.hir_id);
1117
        Item {
1118
            name: Some(self.ident.name.clean(cx)),
1119 1120
            attrs: self.attrs.clean(cx),
            source: self.span.clean(cx),
L
ljedrz 已提交
1121
            def_id: local_did,
M
Mark Rousskov 已提交
1122
            visibility: Visibility::Inherited,
L
ljedrz 已提交
1123 1124
            stability: get_stability(cx, local_did),
            deprecation: get_deprecation(cx, local_did),
1125
            inner,
1126 1127 1128 1129
        }
    }
}

1130
impl Clean<Item> for hir::ImplItem {
1131
    fn clean(&self, cx: &DocContext<'_>) -> Item {
1132
        let inner = match self.kind {
1133
            hir::ImplItemKind::Const(ref ty, expr) => {
A
Andrew Xu 已提交
1134
                AssocConstItem(ty.clean(cx),
1135
                                    Some(print_const_expr(cx, expr)))
1136
            }
1137
            hir::ImplItemKind::Method(ref sig, body) => {
1138
                MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx))
1139
            }
1140
            hir::ImplItemKind::TyAlias(ref ty) => TypedefItem(Typedef {
1141
                type_: ty.clean(cx),
1142
                generics: Generics::default(),
1143
            }, true),
V
varkor 已提交
1144
            hir::ImplItemKind::OpaqueTy(ref bounds) => OpaqueTyItem(OpaqueTy {
O
Oliver Schneider 已提交
1145 1146 1147
                bounds: bounds.clean(cx),
                generics: Generics::default(),
            }, true),
1148
        };
1149
        let local_did = cx.tcx.hir().local_def_id(self.hir_id);
1150
        Item {
1151
            name: Some(self.ident.name.clean(cx)),
1152 1153
            source: self.span.clean(cx),
            attrs: self.attrs.clean(cx),
L
ljedrz 已提交
1154
            def_id: local_did,
1155
            visibility: self.vis.clean(cx),
L
ljedrz 已提交
1156 1157
            stability: get_stability(cx, local_did),
            deprecation: get_deprecation(cx, local_did),
1158
            inner,
C
Corey Richardson 已提交
1159 1160 1161 1162
        }
    }
}

1163
impl Clean<Item> for ty::AssocItem {
1164
    fn clean(&self, cx: &DocContext<'_>) -> Item {
1165
        let inner = match self.kind {
A
Andrew Xu 已提交
1166
            ty::AssocKind::Const => {
1167
                let ty = cx.tcx.type_of(self.def_id);
1168 1169 1170 1171 1172
                let default = if self.defaultness.has_value() {
                    Some(inline::print_inlined_const(cx, self.def_id))
                } else {
                    None
                };
A
Andrew Xu 已提交
1173
                AssocConstItem(ty.clean(cx), default)
1174
            }
A
Andrew Xu 已提交
1175
            ty::AssocKind::Method => {
1176
                let generics = (cx.tcx.generics_of(self.def_id),
1177
                                cx.tcx.explicit_predicates_of(self.def_id)).clean(cx);
1178
                let sig = cx.tcx.fn_sig(self.def_id);
1179
                let mut decl = (self.def_id, sig).clean(cx);
1180 1181 1182 1183

                if self.method_has_self_argument {
                    let self_ty = match self.container {
                        ty::ImplContainer(def_id) => {
1184
                            cx.tcx.type_of(def_id)
1185
                        }
1186
                        ty::TraitContainer(_) => cx.tcx.types.self_param,
1187
                    };
1188
                    let self_arg_ty = *sig.input(0).skip_binder();
1189
                    if self_arg_ty == self_ty {
1190
                        decl.inputs.values[0].type_ = Generic(String::from("Self"));
V
varkor 已提交
1191
                    } else if let ty::Ref(_, ty, _) = self_arg_ty.kind {
1192
                        if ty == self_ty {
1193
                            match decl.inputs.values[0].type_ {
1194 1195 1196
                                BorrowedRef{ref mut type_, ..} => {
                                    **type_ = Generic(String::from("Self"))
                                }
1197 1198 1199 1200 1201
                                _ => unreachable!(),
                            }
                        }
                    }
                }
1202

1203
                let provided = match self.container {
1204
                    ty::ImplContainer(_) => true,
1205
                    ty::TraitContainer(_) => self.defaultness.has_value()
1206
                };
1207
                let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
1208
                if provided {
1209
                    let constness = if cx.tcx.is_min_const_fn(self.def_id) {
1210 1211 1212 1213
                        hir::Constness::Const
                    } else {
                        hir::Constness::NotConst
                    };
C
csmoe 已提交
1214
                    let asyncness = cx.tcx.asyncness(self.def_id);
1215 1216 1217 1218
                    let defaultness = match self.container {
                        ty::ImplContainer(_) => Some(self.defaultness),
                        ty::TraitContainer(_) => None,
                    };
1219
                    MethodItem(Method {
1220 1221
                        generics,
                        decl,
W
Without Boats 已提交
1222 1223 1224 1225
                        header: hir::FnHeader {
                            unsafety: sig.unsafety(),
                            abi: sig.abi(),
                            constness,
C
csmoe 已提交
1226
                            asyncness,
1227
                        },
1228
                        defaultness,
1229
                        all_types,
1230
                        ret_types,
1231 1232 1233
                    })
                } else {
                    TyMethodItem(TyMethod {
1234 1235
                        generics,
                        decl,
W
Without Boats 已提交
1236 1237 1238
                        header: hir::FnHeader {
                            unsafety: sig.unsafety(),
                            abi: sig.abi(),
1239 1240
                            constness: hir::Constness::NotConst,
                            asyncness: hir::IsAsync::NotAsync,
1241 1242
                        },
                        all_types,
1243
                        ret_types,
1244
                    })
1245 1246
                }
            }
A
Andrew Xu 已提交
1247
            ty::AssocKind::Type => {
1248
                let my_name = self.ident.name.clean(cx);
1249

1250
                if let ty::TraitContainer(did) = self.container {
1251 1252 1253 1254
                    // 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.
1255
                    let predicates = cx.tcx.explicit_predicates_of(did);
1256
                    let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
1257
                    let mut bounds = generics.where_predicates.iter().filter_map(|pred| {
1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274
                        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)
1275 1276 1277 1278 1279 1280 1281 1282
                    }).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 已提交
1283
                        None => bounds.push(GenericBound::maybe_sized(cx)),
1284
                    }
1285

1286 1287 1288 1289 1290
                    let ty = if self.defaultness.has_value() {
                        Some(cx.tcx.type_of(self.def_id))
                    } else {
                        None
                    };
1291

A
Andrew Xu 已提交
1292
                    AssocTypeItem(bounds, ty.clean(cx))
1293
                } else {
1294 1295 1296
                    TypedefItem(Typedef {
                        type_: cx.tcx.type_of(self.def_id).clean(cx),
                        generics: Generics {
1297
                            params: Vec::new(),
1298 1299 1300 1301
                            where_predicates: Vec::new(),
                        },
                    }, true)
                }
1302
            }
V
varkor 已提交
1303
            ty::AssocKind::OpaqueTy => unimplemented!(),
1304 1305
        };

1306 1307
        let visibility = match self.container {
            ty::ImplContainer(_) => self.vis.clean(cx),
M
Mark Rousskov 已提交
1308
            ty::TraitContainer(_) => Inherited,
1309 1310
        };

1311
        Item {
1312
            name: Some(self.ident.name.clean(cx)),
1313
            visibility,
1314
            stability: get_stability(cx, self.def_id),
1315
            deprecation: get_deprecation(cx, self.def_id),
1316
            def_id: self.def_id,
1317
            attrs: inline::load_attrs(cx, self.def_id).clean(cx),
1318
            source: cx.tcx.def_span(self.def_id).clean(cx),
1319
            inner,
1320
        }
1321 1322 1323
    }
}

1324
impl Clean<Type> for hir::Ty {
1325
    fn clean(&self, cx: &DocContext<'_>) -> Type {
1326
        use rustc::hir::*;
1327

V
varkor 已提交
1328
        match self.kind {
C
csmoe 已提交
1329 1330 1331
            TyKind::Never => Never,
            TyKind::Ptr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
            TyKind::Rptr(ref l, ref m) => {
1332 1333 1334 1335 1336
                let lifetime = if l.is_elided() {
                    None
                } else {
                    Some(l.clean(cx))
                };
1337
                BorrowedRef {lifetime, mutability: m.mutbl.clean(cx),
1338 1339
                             type_: box m.ty.clean(cx)}
            }
C
csmoe 已提交
1340 1341
            TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
            TyKind::Array(ref ty, ref length) => {
1342
                let def_id = cx.tcx.hir().local_def_id(length.hir_id);
1343
                let param_env = cx.tcx.param_env(def_id);
C
csmoe 已提交
1344
                let substs = InternalSubsts::identity_for_item(cx.tcx, def_id);
O
Oliver Schneider 已提交
1345 1346 1347 1348
                let cid = GlobalId {
                    instance: ty::Instance::new(def_id, substs),
                    promoted: None
                };
1349
                let length = match cx.tcx.const_eval(param_env.and(cid)) {
O
Oliver Scherer 已提交
1350
                    Ok(length) => print_const(cx, length),
1351 1352 1353 1354
                    Err(_) => cx.sess()
                                .source_map()
                                .span_to_snippet(cx.tcx.def_span(def_id))
                                .unwrap_or_else(|_| "_".to_string()),
1355
                };
1356
                Array(box ty.clean(cx), length)
1357
            },
C
csmoe 已提交
1358
            TyKind::Tup(ref tys) => Tuple(tys.clean(cx)),
O
Oliver Schneider 已提交
1359
            TyKind::Def(item_id, _) => {
1360
                let item = cx.tcx.hir().expect_item(item_id.id);
V
varkor 已提交
1361
                if let hir::ItemKind::OpaqueTy(ref ty) = item.kind {
O
Oliver Schneider 已提交
1362 1363 1364 1365 1366
                    ImplTrait(ty.bounds.clean(cx))
                } else {
                    unreachable!()
                }
            }
C
csmoe 已提交
1367
            TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
1368
                if let Res::Def(DefKind::TyParam, did) = path.res {
1369 1370 1371
                    if let Some(new_ty) = cx.ty_substs.borrow().get(&did).cloned() {
                        return new_ty;
                    }
1372
                    if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did.into()) {
1373 1374 1375 1376
                        return ImplTrait(bounds);
                    }
                }

1377
                let mut alias = None;
1378
                if let Res::Def(DefKind::TyAlias, def_id) = path.res {
1379
                    // Substitute private type aliases
1380
                    if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
1381
                        if !cx.renderinfo.borrow().access_levels.is_exported(def_id) {
V
varkor 已提交
1382
                            alias = Some(&cx.tcx.hir().expect_item(hir_id).kind);
1383
                        }
E
Eduard Burtescu 已提交
1384
                    }
1385 1386
                };

1387
                if let Some(&hir::ItemKind::TyAlias(ref ty, ref generics)) = alias {
G
Guillaume Gomez 已提交
1388
                    let provided_params = &path.segments.last().expect("segments were empty");
1389 1390
                    let mut ty_substs = FxHashMap::default();
                    let mut lt_substs = FxHashMap::default();
1391
                    let mut ct_substs = FxHashMap::default();
1392 1393
                    let generic_args = provided_params.generic_args();
                    {
V
varkor 已提交
1394
                        let mut indices: GenericParamCount = Default::default();
1395
                        for param in generics.params.iter() {
V
varkor 已提交
1396 1397
                            match param.kind {
                                hir::GenericParamKind::Lifetime { .. } => {
1398 1399 1400
                                    let mut j = 0;
                                    let lifetime = generic_args.args.iter().find_map(|arg| {
                                        match arg {
V
varkor 已提交
1401
                                            hir::GenericArg::Lifetime(lt) => {
1402 1403 1404 1405 1406 1407 1408 1409 1410 1411
                                                if indices.lifetimes == j {
                                                    return Some(lt);
                                                }
                                                j += 1;
                                                None
                                            }
                                            _ => None,
                                        }
                                    });
                                    if let Some(lt) = lifetime.cloned() {
1412 1413
                                        if !lt.is_elided() {
                                            let lt_def_id =
1414
                                                cx.tcx.hir().local_def_id(param.hir_id);
1415 1416 1417 1418 1419
                                            lt_substs.insert(lt_def_id, lt.clean(cx));
                                        }
                                    }
                                    indices.lifetimes += 1;
                                }
V
varkor 已提交
1420
                                hir::GenericParamKind::Type { ref default, .. } => {
1421
                                    let ty_param_def_id =
1422
                                        cx.tcx.hir().local_def_id(param.hir_id);
1423 1424 1425
                                    let mut j = 0;
                                    let type_ = generic_args.args.iter().find_map(|arg| {
                                        match arg {
V
varkor 已提交
1426
                                            hir::GenericArg::Type(ty) => {
1427 1428 1429 1430 1431 1432 1433 1434 1435
                                                if indices.types == j {
                                                    return Some(ty);
                                                }
                                                j += 1;
                                                None
                                            }
                                            _ => None,
                                        }
                                    });
1436
                                    if let Some(ty) = type_ {
1437
                                        ty_substs.insert(ty_param_def_id, ty.clean(cx));
V
varkor 已提交
1438
                                    } else if let Some(default) = default.clone() {
1439
                                        ty_substs.insert(ty_param_def_id,
1440
                                                         default.clean(cx));
1441
                                    }
1442
                                    indices.types += 1;
1443
                                }
V
varkor 已提交
1444
                                hir::GenericParamKind::Const { .. } => {
1445
                                    let const_param_def_id =
1446
                                        cx.tcx.hir().local_def_id(param.hir_id);
V
varkor 已提交
1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459
                                    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,
                                        }
                                    });
1460
                                    if let Some(ct) = const_ {
1461
                                        ct_substs.insert(const_param_def_id, ct.clean(cx));
V
varkor 已提交
1462 1463 1464 1465
                                    }
                                    // FIXME(const_generics:defaults)
                                    indices.consts += 1;
                                }
1466
                            }
1467
                        }
1468
                    }
1469
                    return cx.enter_alias(ty_substs, lt_substs, ct_substs, || ty.clean(cx));
1470
                }
L
ljedrz 已提交
1471
                resolve_type(cx, path.clean(cx), self.hir_id)
N
Niko Matsakis 已提交
1472
            }
C
csmoe 已提交
1473
            TyKind::Path(hir::QPath::Resolved(Some(ref qself), ref p)) => {
1474 1475 1476 1477
                let segments = if p.is_global() { &p.segments[1..] } else { &p.segments };
                let trait_segments = &segments[..segments.len() - 1];
                let trait_path = self::Path {
                    global: p.is_global(),
1478
                    res: Res::Def(
1479
                        DefKind::Trait,
1480
                        cx.tcx.associated_item(p.res.def_id()).container.id(),
1481
                    ),
1482
                    segments: trait_segments.clean(cx),
1483
                };
1484
                Type::QPath {
G
Guillaume Gomez 已提交
1485
                    name: p.segments.last().expect("segments were empty").ident.name.clean(cx),
1486
                    self_type: box qself.clean(cx),
1487
                    trait_: box resolve_type(cx, trait_path, self.hir_id)
1488 1489
                }
            }
C
csmoe 已提交
1490
            TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
1491
                let mut res = Res::Err;
1492
                let ty = hir_ty_to_ty(cx.tcx, self);
V
varkor 已提交
1493
                if let ty::Projection(proj) = ty.kind {
1494
                    res = Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id);
1495
                }
1496 1497
                let trait_path = hir::Path {
                    span: self.span,
1498
                    res,
1499 1500 1501
                    segments: vec![].into(),
                };
                Type::QPath {
1502
                    name: segment.ident.name.clean(cx),
1503
                    self_type: box qself.clean(cx),
L
ljedrz 已提交
1504
                    trait_: box resolve_type(cx, trait_path.clean(cx), self.hir_id)
1505 1506
                }
            }
C
csmoe 已提交
1507
            TyKind::TraitObject(ref bounds, ref lifetime) => {
1508
                match bounds[0].clean(cx).trait_ {
V
varkor 已提交
1509
                    ResolvedPath { path, param_names: None, did, is_generic } => {
V
varkor 已提交
1510
                        let mut bounds: Vec<self::GenericBound> = bounds[1..].iter().map(|bound| {
V
varkor 已提交
1511 1512
                            self::GenericBound::TraitBound(bound.clean(cx),
                                                           hir::TraitBoundModifier::None)
1513 1514
                        }).collect();
                        if !lifetime.is_elided() {
V
varkor 已提交
1515
                            bounds.push(self::GenericBound::Outlives(lifetime.clean(cx)));
1516
                        }
V
varkor 已提交
1517
                        ResolvedPath { path, param_names: Some(bounds), did, is_generic, }
N
Niko Matsakis 已提交
1518
                    }
1519
                    _ => Infer, // shouldn't happen
N
Niko Matsakis 已提交
1520
                }
1521
            }
C
csmoe 已提交
1522 1523
            TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
            TyKind::Infer | TyKind::Err => Infer,
V
varkor 已提交
1524
            TyKind::Typeof(..) => panic!("unimplemented type {:?}", self.kind),
1525
        }
C
Corey Richardson 已提交
1526 1527 1528
    }
}

D
Douglas Campos 已提交
1529
impl<'tcx> Clean<Type> for Ty<'tcx> {
1530
    fn clean(&self, cx: &DocContext<'_>) -> Type {
1531
        debug!("cleaning type: {:?}", self);
V
varkor 已提交
1532
        match self.kind {
V
varkor 已提交
1533
            ty::Never => Never,
1534 1535 1536 1537 1538 1539
            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 已提交
1540 1541
            ty::Slice(ty) => Slice(box ty.clean(cx)),
            ty::Array(ty, n) => {
1542
                let mut n = cx.tcx.lift(&n).expect("array lift failed");
C
Camille GILLOT 已提交
1543
                if let ty::ConstKind::Unevaluated(def_id, substs) = n.val {
1544
                    let param_env = cx.tcx.param_env(def_id);
O
Oliver Schneider 已提交
1545 1546 1547 1548 1549
                    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 已提交
1550
                        n = new_n;
1551
                    }
1552
                };
O
Oliver Schneider 已提交
1553
                let n = print_const(cx, n);
1554 1555
                Array(box ty.clean(cx), n)
            }
V
varkor 已提交
1556 1557
            ty::RawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
            ty::Ref(r, ty, mutbl) => BorrowedRef {
1558
                lifetime: r.clean(cx),
1559 1560
                mutability: mutbl.clean(cx),
                type_: box ty.clean(cx),
1561
            },
V
varkor 已提交
1562 1563 1564
            ty::FnDef(..) |
            ty::FnPtr(_) => {
                let ty = cx.tcx.lift(self).expect("FnPtr lift failed");
1565
                let sig = ty.fn_sig(cx.tcx);
1566
                let local_def_id = cx.tcx.hir().local_def_id_from_node_id(ast::CRATE_NODE_ID);
1567 1568
                BareFunction(box BareFunctionDecl {
                    unsafety: sig.unsafety(),
1569
                    generic_params: Vec::new(),
1570
                    decl: (local_def_id, sig).clean(cx),
1571 1572 1573
                    abi: sig.abi(),
                })
            }
V
varkor 已提交
1574
            ty::Adt(def, substs) => {
1575
                let did = def.did;
1576
                let kind = match def.adt_kind() {
1577 1578 1579
                    AdtKind::Struct => TypeKind::Struct,
                    AdtKind::Union => TypeKind::Union,
                    AdtKind::Enum => TypeKind::Enum,
1580
                };
M
mitaa 已提交
1581
                inline::record_extern_fqn(cx, did, kind);
1582
                let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], substs);
1583
                ResolvedPath {
1584
                    path,
V
varkor 已提交
1585
                    param_names: None,
1586
                    did,
1587
                    is_generic: false,
1588 1589
                }
            }
V
varkor 已提交
1590
            ty::Foreign(did) => {
P
Paul Lietar 已提交
1591
                inline::record_extern_fqn(cx, did, TypeKind::Foreign);
1592
                let path = external_path(cx, cx.tcx.item_name(did),
C
csmoe 已提交
1593
                                         None, false, vec![], InternalSubsts::empty());
P
Paul Lietar 已提交
1594
                ResolvedPath {
1595
                    path,
V
varkor 已提交
1596
                    param_names: None,
1597
                    did,
P
Paul Lietar 已提交
1598 1599 1600
                    is_generic: false,
                }
            }
V
varkor 已提交
1601
            ty::Dynamic(ref obj, ref reg) => {
A
Ariel Ben-Yehuda 已提交
1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614
                // 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(&[])
                };

1615 1616
                inline::record_extern_fqn(cx, did, TypeKind::Trait);

V
varkor 已提交
1617 1618
                let mut param_names = vec![];
                reg.clean(cx).map(|b| param_names.push(GenericBound::Outlives(b)));
A
Ariel Ben-Yehuda 已提交
1619
                for did in dids {
1620
                    let empty = cx.tcx.intern_substs(&[]);
1621
                    let path = external_path(cx, cx.tcx.item_name(did),
1622
                        Some(did), false, vec![], empty);
1623
                    inline::record_extern_fqn(cx, did, TypeKind::Trait);
1624 1625 1626
                    let bound = GenericBound::TraitBound(PolyTrait {
                        trait_: ResolvedPath {
                            path,
V
varkor 已提交
1627
                            param_names: None,
1628 1629 1630 1631 1632
                            did,
                            is_generic: false,
                        },
                        generic_params: Vec::new(),
                    }, hir::TraitBoundModifier::None);
V
varkor 已提交
1633
                    param_names.push(bound);
1634
                }
1635

1636 1637 1638 1639
                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),
1640 1641 1642
                        kind: TypeBindingKind::Equality {
                            ty: pb.skip_binder().ty.clean(cx)
                        },
1643 1644
                    });
                }
1645

1646
                let path = external_path(cx, cx.tcx.item_name(did), Some(did),
A
Ariel Ben-Yehuda 已提交
1647
                    false, bindings, substs);
1648 1649
                ResolvedPath {
                    path,
V
varkor 已提交
1650
                    param_names: Some(param_names),
1651 1652
                    did,
                    is_generic: false,
1653 1654
                }
            }
V
varkor 已提交
1655 1656 1657
            ty::Tuple(ref t) => {
                Tuple(t.iter().map(|t| t.expect_ty()).collect::<Vec<_>>().clean(cx))
            }
1658

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

1661 1662 1663 1664 1665 1666 1667
            ty::Param(ref p) => {
                if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&p.index.into()) {
                    ImplTrait(bounds)
                } else {
                    Generic(p.name.to_string())
                }
            }
1668

1669
            ty::Opaque(def_id, substs) => {
1670 1671
                // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
                // by looking up the projections associated with the def_id.
1672
                let predicates_of = cx.tcx.explicit_predicates_of(def_id);
1673
                let substs = cx.tcx.lift(&substs).expect("Opaque lift failed");
1674
                let bounds = predicates_of.instantiate(cx.tcx, substs);
1675 1676 1677
                let mut regions = vec![];
                let mut has_sized = false;
                let mut bounds = bounds.predicates.iter().filter_map(|predicate| {
1678 1679
                    let trait_ref = if let Some(tr) = predicate.to_opt_poly_trait_ref() {
                        tr
1680 1681
                    } else if let ty::Predicate::TypeOutlives(pred) = *predicate {
                        // these should turn up at the end
1682
                        pred.skip_binder().1.clean(cx).map(|r| {
V
varkor 已提交
1683
                            regions.push(GenericBound::Outlives(r))
1684
                        });
1685
                        return None;
1686 1687 1688 1689
                    } else {
                        return None;
                    };

1690 1691
                    if let Some(sized) = cx.tcx.lang_items().sized_trait() {
                        if trait_ref.def_id() == sized {
1692
                            has_sized = true;
1693 1694 1695 1696
                            return None;
                        }
                    }

1697 1698 1699 1700 1701 1702
                    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)
1703
                                                .ident.name.clean(cx),
1704 1705 1706
                                    kind: TypeBindingKind::Equality {
                                        ty: proj.ty.clean(cx),
                                    },
1707 1708 1709 1710 1711 1712 1713 1714 1715 1716
                                })
                            } else {
                                None
                            }
                        } else {
                            None
                        }
                    ).collect();

                    Some((trait_ref.skip_binder(), bounds).clean(cx))
1717 1718 1719
                }).collect::<Vec<_>>();
                bounds.extend(regions);
                if !has_sized && !bounds.is_empty() {
V
varkor 已提交
1720
                    bounds.insert(0, GenericBound::maybe_sized(cx));
1721 1722
                }
                ImplTrait(bounds)
1723 1724
            }

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

S
scalexm 已提交
1727
            ty::Bound(..) => panic!("Bound"),
S
scalexm 已提交
1728
            ty::Placeholder(..) => panic!("Placeholder"),
1729
            ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"),
V
varkor 已提交
1730 1731 1732
            ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
            ty::Infer(..) => panic!("Infer"),
            ty::Error => panic!("Error"),
1733 1734 1735 1736
        }
    }
}

V
varkor 已提交
1737 1738 1739 1740
impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
    fn clean(&self, cx: &DocContext<'_>) -> Constant {
        Constant {
            type_: self.ty.clean(cx),
V
varkor 已提交
1741
            expr: format!("{}", self),
V
varkor 已提交
1742 1743 1744 1745
        }
    }
}

1746
impl Clean<Item> for hir::StructField {
1747
    fn clean(&self, cx: &DocContext<'_>) -> Item {
1748
        let local_did = cx.tcx.hir().local_def_id(self.hir_id);
L
ljedrz 已提交
1749

C
Corey Richardson 已提交
1750
        Item {
1751
            name: Some(self.ident.name).clean(cx),
1752
            attrs: self.attrs.clean(cx),
1753
            source: self.span.clean(cx),
1754
            visibility: self.vis.clean(cx),
L
ljedrz 已提交
1755 1756 1757
            stability: get_stability(cx, local_did),
            deprecation: get_deprecation(cx, local_did),
            def_id: local_did,
1758
            inner: StructFieldItem(self.ty.clean(cx)),
C
Corey Richardson 已提交
1759 1760 1761 1762
        }
    }
}

1763
impl Clean<Item> for ty::FieldDef {
1764
    fn clean(&self, cx: &DocContext<'_>) -> Item {
1765
        Item {
1766
            name: Some(self.ident.name).clean(cx),
1767
            attrs: cx.tcx.get_attrs(self.did).clean(cx),
1768
            source: cx.tcx.def_span(self.did).clean(cx),
1769
            visibility: self.vis.clean(cx),
1770
            stability: get_stability(cx, self.did),
1771
            deprecation: get_deprecation(cx, self.did),
1772
            def_id: self.did,
1773
            inner: StructFieldItem(cx.tcx.type_of(self.did).clean(cx)),
1774 1775 1776 1777
        }
    }
}

M
Mark Rousskov 已提交
1778 1779 1780
impl Clean<Visibility> for hir::Visibility {
    fn clean(&self, cx: &DocContext<'_>) -> Visibility {
        match self.node {
1781 1782 1783 1784
            hir::VisibilityKind::Public => Visibility::Public,
            hir::VisibilityKind::Inherited => Visibility::Inherited,
            hir::VisibilityKind::Crate(_) => Visibility::Crate,
            hir::VisibilityKind::Restricted { ref path, .. } => {
1785
                let path = path.clean(cx);
1786
                let did = register_res(cx, path.res);
1787 1788
                Visibility::Restricted(did, path)
            }
M
Mark Rousskov 已提交
1789
        }
1790 1791 1792
    }
}

M
Mark Rousskov 已提交
1793 1794 1795
impl Clean<Visibility> for ty::Visibility {
    fn clean(&self, _: &DocContext<'_>) -> Visibility {
        if *self == ty::Visibility::Public { Public } else { Inherited }
C
Corey Richardson 已提交
1796 1797 1798
    }
}

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

1819
impl Clean<Item> for doctree::Union<'_> {
1820
    fn clean(&self, cx: &DocContext<'_>) -> Item {
1821 1822
        Item {
            name: Some(self.name.clean(cx)),
V
Vadim Petrochenkov 已提交
1823 1824
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
1825
            def_id: cx.tcx.hir().local_def_id(self.id),
V
Vadim Petrochenkov 已提交
1826
            visibility: self.vis.clean(cx),
1827
            stability: cx.stability(self.id).clean(cx),
1828
            deprecation: cx.deprecation(self.id).clean(cx),
V
Vadim Petrochenkov 已提交
1829 1830 1831 1832 1833 1834
            inner: UnionItem(Union {
                struct_type: self.struct_type,
                generics: self.generics.clean(cx),
                fields: self.fields.clean(cx),
                fields_stripped: false,
            }),
1835
        }
V
Vadim Petrochenkov 已提交
1836 1837 1838
    }
}

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

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

1868
impl Clean<Item> for doctree::Variant<'_> {
1869
    fn clean(&self, cx: &DocContext<'_>) -> Item {
C
Corey Richardson 已提交
1870
        Item {
1871 1872 1873
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
M
Mark Rousskov 已提交
1874
            visibility: Inherited,
1875
            stability: cx.stability(self.id).clean(cx),
1876
            deprecation: cx.deprecation(self.id).clean(cx),
1877
            def_id: cx.tcx.hir().local_def_id(self.id),
C
Corey Richardson 已提交
1878
            inner: VariantItem(Variant {
1879
                kind: self.def.clean(cx),
C
Corey Richardson 已提交
1880 1881 1882 1883 1884
            }),
        }
    }
}

1885
impl Clean<Item> for ty::VariantDef {
1886
    fn clean(&self, cx: &DocContext<'_>) -> Item {
1887 1888 1889
        let kind = match self.ctor_kind {
            CtorKind::Const => VariantKind::CLike,
            CtorKind::Fn => {
1890
                VariantKind::Tuple(
1891
                    self.fields.iter().map(|f| cx.tcx.type_of(f.did).clean(cx)).collect()
1892
                )
1893
            }
1894
            CtorKind::Fictive => {
1895
                VariantKind::Struct(VariantStruct {
1896 1897
                    struct_type: doctree::Plain,
                    fields_stripped: false,
1898
                    fields: self.fields.iter().map(|field| {
1899
                        Item {
1900
                            source: cx.tcx.def_span(field.did).clean(cx),
1901
                            name: Some(field.ident.name.clean(cx)),
1902
                            attrs: cx.tcx.get_attrs(field.did).clean(cx),
1903
                            visibility: field.vis.clean(cx),
1904 1905 1906
                            def_id: field.did,
                            stability: get_stability(cx, field.did),
                            deprecation: get_deprecation(cx, field.did),
1907
                            inner: StructFieldItem(cx.tcx.type_of(field.did).clean(cx))
1908 1909 1910 1911 1912 1913
                        }
                    }).collect()
                })
            }
        };
        Item {
1914
            name: Some(self.ident.clean(cx)),
1915
            attrs: inline::load_attrs(cx, self.def_id).clean(cx),
1916
            source: cx.tcx.def_span(self.def_id).clean(cx),
M
Mark Rousskov 已提交
1917
            visibility: Inherited,
1918
            def_id: self.def_id,
T
teresy 已提交
1919
            inner: VariantItem(Variant { kind }),
1920 1921
            stability: get_stability(cx, self.def_id),
            deprecation: get_deprecation(cx, self.def_id),
1922 1923 1924 1925
        }
    }
}

1926
impl Clean<VariantKind> for hir::VariantData {
1927
    fn clean(&self, cx: &DocContext<'_>) -> VariantKind {
1928 1929 1930 1931 1932
        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,
1933
        }
1934 1935 1936
    }
}

1937
impl Clean<Span> for syntax_pos::Span {
1938
    fn clean(&self, cx: &DocContext<'_>) -> Span {
V
Vadim Petrochenkov 已提交
1939
        if self.is_dummy() {
1940 1941 1942
            return Span::empty();
        }

D
Donato Sciarra 已提交
1943
        let cm = cx.sess().source_map();
1944
        let filename = cm.span_to_filename(*self);
1945 1946
        let lo = cm.lookup_char_pos(self.lo());
        let hi = cm.lookup_char_pos(self.hi());
1947
        Span {
1948
            filename,
1949
            loline: lo.line,
1950
            locol: lo.col.to_usize(),
1951
            hiline: hi.line,
1952
            hicol: hi.col.to_usize(),
G
Guillaume Gomez 已提交
1953
            original: *self,
1954
        }
C
Corey Richardson 已提交
1955 1956 1957
    }
}

1958
impl Clean<Path> for hir::Path {
1959
    fn clean(&self, cx: &DocContext<'_>) -> Path {
C
Corey Richardson 已提交
1960
        Path {
1961
            global: self.is_global(),
1962
            res: self.res,
1963
            segments: if self.is_global() { &self.segments[1..] } else { &self.segments }.clean(cx),
1964 1965 1966 1967
        }
    }
}

1968
impl Clean<GenericArgs> for hir::GenericArgs {
1969
    fn clean(&self, cx: &DocContext<'_>) -> GenericArgs {
1970
        if self.parenthesized {
1971
            let output = self.bindings[0].ty().clean(cx);
1972
            GenericArgs::Parenthesized {
1973 1974
                inputs: self.inputs().clean(cx),
                output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
1975
            }
1976
        } else {
1977 1978 1979 1980
            let elide_lifetimes = self.args.iter().all(|arg| match arg {
                hir::GenericArg::Lifetime(lt) => lt.is_elided(),
                _ => true,
            });
1981
            GenericArgs::AngleBracketed {
1982 1983 1984 1985 1986 1987 1988 1989
                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(),
1990
                bindings: self.bindings.clean(cx),
1991
            }
1992 1993 1994
        }
    }
}
1995

1996
impl Clean<PathSegment> for hir::PathSegment {
1997
    fn clean(&self, cx: &DocContext<'_>) -> PathSegment {
1998
        PathSegment {
1999
            name: self.ident.name.clean(cx),
2000
            args: self.generic_args().clean(cx),
C
Corey Richardson 已提交
2001 2002 2003 2004
        }
    }
}

2005 2006
impl Clean<String> for Ident {
    #[inline]
2007
    fn clean(&self, cx: &DocContext<'_>) -> String {
2008 2009 2010 2011
        self.name.clean(cx)
    }
}

2012
impl Clean<String> for ast::Name {
2013
    #[inline]
2014
    fn clean(&self, _: &DocContext<'_>) -> String {
2015
        self.to_string()
2016 2017 2018
    }
}

2019
impl Clean<Item> for doctree::Typedef<'_> {
2020
    fn clean(&self, cx: &DocContext<'_>) -> Item {
C
Corey Richardson 已提交
2021
        Item {
2022 2023 2024
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2025
            def_id: cx.tcx.hir().local_def_id(self.id),
2026
            visibility: self.vis.clean(cx),
2027
            stability: cx.stability(self.id).clean(cx),
2028
            deprecation: cx.deprecation(self.id).clean(cx),
C
Corey Richardson 已提交
2029
            inner: TypedefItem(Typedef {
2030 2031
                type_: self.ty.clean(cx),
                generics: self.gen.clean(cx),
2032
            }, false),
C
Corey Richardson 已提交
2033 2034 2035 2036
        }
    }
}

V
varkor 已提交
2037
impl Clean<Item> for doctree::OpaqueTy<'_> {
2038
    fn clean(&self, cx: &DocContext<'_>) -> Item {
O
Oliver Schneider 已提交
2039 2040 2041 2042
        Item {
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2043
            def_id: cx.tcx.hir().local_def_id(self.id),
O
Oliver Schneider 已提交
2044
            visibility: self.vis.clean(cx),
2045
            stability: cx.stability(self.id).clean(cx),
2046
            deprecation: cx.deprecation(self.id).clean(cx),
V
varkor 已提交
2047
            inner: OpaqueTyItem(OpaqueTy {
2048 2049
                bounds: self.opaque_ty.bounds.clean(cx),
                generics: self.opaque_ty.generics.clean(cx),
O
Oliver Schneider 已提交
2050 2051 2052 2053 2054
            }, false),
        }
    }
}

2055
impl Clean<BareFunctionDecl> for hir::BareFnTy {
2056
    fn clean(&self, cx: &DocContext<'_>) -> BareFunctionDecl {
2057
        let (generic_params, decl) = enter_impl_trait(cx, || {
2058
            (self.generic_params.clean(cx), (&*self.decl, &self.param_names[..]).clean(cx))
2059
        });
C
Corey Richardson 已提交
2060
        BareFunctionDecl {
N
Niko Matsakis 已提交
2061
            unsafety: self.unsafety,
W
Without Boats 已提交
2062
            abi: self.abi,
2063
            decl,
2064
            generic_params,
C
Corey Richardson 已提交
2065 2066 2067 2068
        }
    }
}

2069
impl Clean<Item> for doctree::Static<'_> {
2070
    fn clean(&self, cx: &DocContext<'_>) -> Item {
2071
        debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
C
Corey Richardson 已提交
2072
        Item {
2073 2074 2075
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2076
            def_id: cx.tcx.hir().local_def_id(self.id),
2077
            visibility: self.vis.clean(cx),
2078
            stability: cx.stability(self.id).clean(cx),
2079
            deprecation: cx.deprecation(self.id).clean(cx),
C
Corey Richardson 已提交
2080
            inner: StaticItem(Static {
2081 2082
                type_: self.type_.clean(cx),
                mutability: self.mutability.clean(cx),
2083
                expr: print_const_expr(cx, self.expr),
C
Corey Richardson 已提交
2084 2085 2086 2087 2088
            }),
        }
    }
}

2089
impl Clean<Item> for doctree::Constant<'_> {
2090
    fn clean(&self, cx: &DocContext<'_>) -> Item {
2091 2092 2093 2094
        Item {
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2095
            def_id: cx.tcx.hir().local_def_id(self.id),
2096
            visibility: self.vis.clean(cx),
2097
            stability: cx.stability(self.id).clean(cx),
2098
            deprecation: cx.deprecation(self.id).clean(cx),
2099 2100
            inner: ConstantItem(Constant {
                type_: self.type_.clean(cx),
2101
                expr: print_const_expr(cx, self.expr),
2102 2103 2104 2105 2106
            }),
        }
    }
}

2107
impl Clean<Mutability> for hir::Mutability {
2108
    fn clean(&self, _: &DocContext<'_>) -> Mutability {
C
Corey Richardson 已提交
2109
        match self {
2110 2111
            &hir::Mutability::Mut => Mutable,
            &hir::Mutability::Not => Immutable,
C
Corey Richardson 已提交
2112 2113 2114 2115
        }
    }
}

2116
impl Clean<ImplPolarity> for ty::ImplPolarity {
2117
    fn clean(&self, _: &DocContext<'_>) -> ImplPolarity {
2118
        match self {
2119 2120 2121 2122
            &ty::ImplPolarity::Positive |
            // FIXME: do we want to do something else here?
            &ty::ImplPolarity::Reservation => ImplPolarity::Positive,
            &ty::ImplPolarity::Negative => ImplPolarity::Negative,
2123 2124 2125 2126
        }
    }
}

2127
impl Clean<Vec<Item>> for doctree::Impl<'_> {
2128
    fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
2129 2130
        let mut ret = Vec::new();
        let trait_ = self.trait_.clean(cx);
2131
        let items = self.items.iter().map(|ii| ii.clean(cx)).collect::<Vec<_>>();
2132
        let def_id = cx.tcx.hir().local_def_id(self.id);
2133 2134 2135

        // 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.
2136
        if trait_.def_id() == cx.tcx.lang_items().deref_trait() {
2137
            build_deref_target_impls(cx, &items, &mut ret);
2138 2139
        }

2140 2141 2142
        let provided = trait_.def_id().map(|did| {
            cx.tcx.provided_trait_methods(did)
                  .into_iter()
2143
                  .map(|meth| meth.ident.to_string())
2144
                  .collect()
2145
        }).unwrap_or_default();
2146

2147
        ret.push(Item {
C
Corey Richardson 已提交
2148
            name: None,
2149 2150
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2151
            def_id,
2152
            visibility: self.vis.clean(cx),
2153
            stability: cx.stability(self.id).clean(cx),
2154
            deprecation: cx.deprecation(self.id).clean(cx),
C
Corey Richardson 已提交
2155
            inner: ImplItem(Impl {
2156
                unsafety: self.unsafety,
2157
                generics: self.generics.clean(cx),
2158
                provided_trait_methods: provided,
2159
                trait_,
2160
                for_: self.for_.clean(cx),
2161
                items,
2162
                polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)),
A
Aaron Hill 已提交
2163
                synthetic: false,
2164
                blanket_impl: None,
2165
            })
2166
        });
M
mitaa 已提交
2167
        ret
2168 2169 2170
    }
}

2171
impl Clean<Vec<Item>> for doctree::ExternCrate<'_> {
2172
    fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
D
DebugSteven 已提交
2173 2174

        let please_inline = self.vis.node.is_pub() && self.attrs.iter().any(|a| {
2175 2176
            a.check_name(sym::doc) && match a.meta_item_list() {
                Some(l) => attr::list_contains_name(&l, sym::inline),
D
DebugSteven 已提交
2177 2178 2179 2180 2181 2182 2183
                None => false,
            }
        });

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

2184
            let res = Res::Def(
2185 2186 2187 2188 2189 2190
                DefKind::Mod,
                DefId {
                    krate: self.cnum,
                    index: CRATE_DEF_INDEX,
                },
            );
D
DebugSteven 已提交
2191

2192 2193 2194 2195 2196
            if let Some(items) = inline::try_inline(
                cx, res, self.name,
                Some(rustc::ty::Attributes::Borrowed(self.attrs)),
                &mut visited
            ) {
D
DebugSteven 已提交
2197 2198 2199 2200 2201
                return items;
            }
        }

        vec![Item {
2202 2203 2204
            name: None,
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
M
mitaa 已提交
2205
            def_id: DefId { krate: self.cnum, index: CRATE_DEF_INDEX },
2206 2207
            visibility: self.vis.clean(cx),
            stability: None,
2208
            deprecation: None,
2209
            inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
D
DebugSteven 已提交
2210
        }]
2211
    }
C
Corey Richardson 已提交
2212 2213
}

2214
impl Clean<Vec<Item>> for doctree::Import<'_> {
2215
    fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
J
Joseph Crail 已提交
2216
        // We consider inlining the documentation of `pub use` statements, but we
2217 2218
        // forcefully don't inline if this is not public or if the
        // #[doc(no_inline)] attribute is present.
2219
        // Don't inline doc(hidden) imports so they can be stripped at a later stage.
2220
        let mut denied = !self.vis.node.is_pub() || self.attrs.iter().any(|a| {
2221 2222 2223
            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),
2224 2225 2226
                None => false,
            }
        });
2227 2228
        // Also check whether imports were asked to be inlined, in case we're trying to re-export a
        // crate in Rust 2018+
2229
        let please_inline = self.attrs.lists(sym::doc).has_word(sym::inline);
2230 2231
        let path = self.path.clean(cx);
        let inner = if self.glob {
2232
            if !denied {
2233
                let mut visited = FxHashSet::default();
2234
                if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) {
2235 2236 2237 2238
                    return items;
                }
            }

2239
            Import::Glob(resolve_use_source(cx, path))
2240 2241
        } else {
            let name = self.name;
2242
            if !please_inline {
2243 2244
                match path.res {
                    Res::Def(DefKind::Mod, did) => {
2245 2246 2247 2248 2249
                        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;
                        }
2250 2251 2252 2253
                    }
                    _ => {}
                }
            }
2254
            if !denied {
2255
                let mut visited = FxHashSet::default();
2256 2257 2258 2259 2260
                if let Some(items) = inline::try_inline(
                    cx, path.res, name,
                    Some(rustc::ty::Attributes::Borrowed(self.attrs)),
                    &mut visited
                ) {
2261
                    return items;
2262
                }
2263
            }
2264
            Import::Simple(name.clean(cx), resolve_use_source(cx, path))
2265
        };
G
Guillaume Gomez 已提交
2266

2267
        vec![Item {
2268 2269 2270
            name: None,
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
2271
            def_id: cx.tcx.hir().local_def_id_from_node_id(ast::CRATE_NODE_ID),
2272 2273
            visibility: self.vis.clean(cx),
            stability: None,
2274
            deprecation: None,
2275
            inner: ImportItem(inner)
2276
        }]
C
Corey Richardson 已提交
2277 2278 2279
    }
}

2280
impl Clean<Item> for doctree::ForeignItem<'_> {
2281
    fn clean(&self, cx: &DocContext<'_>) -> Item {
2282
        let inner = match self.kind {
C
csmoe 已提交
2283
            hir::ForeignItemKind::Fn(ref decl, ref names, ref generics) => {
2284
                let abi = cx.tcx.hir().get_foreign_abi(self.id);
2285 2286 2287
                let (generics, decl) = enter_impl_trait(cx, || {
                    (generics.clean(cx), (&**decl, &names[..]).clean(cx))
                });
2288
                let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
2289
                ForeignFunctionItem(Function {
2290
                    decl,
2291
                    generics,
2292 2293
                    header: hir::FnHeader {
                        unsafety: hir::Unsafety::Unsafe,
2294
                        abi,
2295 2296 2297
                        constness: hir::Constness::NotConst,
                        asyncness: hir::IsAsync::NotAsync,
                    },
2298
                    all_types,
2299
                    ret_types,
2300 2301
                })
            }
C
csmoe 已提交
2302
            hir::ForeignItemKind::Static(ref ty, mutbl) => {
2303
                ForeignStaticItem(Static {
2304
                    type_: ty.clean(cx),
2305
                    mutability: mutbl.clean(cx),
2306
                    expr: String::new(),
2307 2308
                })
            }
C
csmoe 已提交
2309
            hir::ForeignItemKind::Type => {
P
Paul Lietar 已提交
2310 2311
                ForeignTypeItem
            }
2312
        };
G
Guillaume Gomez 已提交
2313

2314
        Item {
2315
            name: Some(self.name.clean(cx)),
2316
            attrs: self.attrs.clean(cx),
2317
            source: self.whence.clean(cx),
2318
            def_id: cx.tcx.hir().local_def_id(self.id),
2319
            visibility: self.vis.clean(cx),
2320
            stability: cx.stability(self.id).clean(cx),
2321
            deprecation: cx.deprecation(self.id).clean(cx),
2322
            inner,
2323 2324 2325 2326
        }
    }
}

2327
impl Clean<Item> for doctree::Macro<'_> {
2328
    fn clean(&self, cx: &DocContext<'_>) -> Item {
2329
        let name = self.name.clean(cx);
2330
        Item {
2331
            name: Some(name.clone()),
2332 2333
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
M
Mark Rousskov 已提交
2334
            visibility: Public,
2335
            stability: cx.stability(self.hid).clean(cx),
2336
            deprecation: cx.deprecation(self.hid).clean(cx),
2337
            def_id: self.def_id,
2338
            inner: MacroItem(Macro {
2339
                source: format!("macro_rules! {} {{\n{}}}",
2340 2341 2342 2343
                                name,
                                self.matchers.iter().map(|span| {
                                    format!("    {} => {{ ... }};\n", span.to_src(cx))
                                }).collect::<String>()),
2344
                imported_from: self.imported_from.clean(cx),
2345 2346 2347 2348
            }),
        }
    }
}
2349

2350
impl Clean<Item> for doctree::ProcMacro<'_> {
2351
    fn clean(&self, cx: &DocContext<'_>) -> Item {
2352 2353 2354 2355
        Item {
            name: Some(self.name.clean(cx)),
            attrs: self.attrs.clean(cx),
            source: self.whence.clean(cx),
M
Mark Rousskov 已提交
2356
            visibility: Public,
2357
            stability: cx.stability(self.id).clean(cx),
2358
            deprecation: cx.deprecation(self.id).clean(cx),
2359
            def_id: cx.tcx.hir().local_def_id(self.id),
2360 2361
            inner: ProcMacroItem(ProcMacro {
                kind: self.kind,
2362
                helpers: self.helpers.clean(cx),
2363 2364 2365 2366 2367
            }),
        }
    }
}

2368
impl Clean<Stability> for attr::Stability {
2369
    fn clean(&self, _: &DocContext<'_>) -> Stability {
2370
        Stability {
V
Vadim Petrochenkov 已提交
2371
            level: stability::StabilityLevel::from_attr_level(&self.level),
2372
            feature: Some(self.feature.to_string()).filter(|f| !f.is_empty()),
V
Vadim Petrochenkov 已提交
2373 2374
            since: match self.level {
                attr::Stable {ref since} => since.to_string(),
2375
                _ => String::new(),
V
Vadim Petrochenkov 已提交
2376
            },
2377 2378 2379 2380 2381 2382
            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()),
                }
            }),
2383
            unstable_reason: match self.level {
2384 2385
                attr::Unstable { reason: Some(ref reason), .. } => Some(reason.to_string()),
                _ => None,
V
Vadim Petrochenkov 已提交
2386 2387
            },
            issue: match self.level {
2388
                attr::Unstable {issue, ..} => issue,
V
Vadim Petrochenkov 已提交
2389 2390
                _ => None,
            }
2391 2392 2393 2394
        }
    }
}

2395
impl Clean<Deprecation> for attr::Deprecation {
2396
    fn clean(&self, _: &DocContext<'_>) -> Deprecation {
2397
        Deprecation {
2398 2399
            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()),
2400 2401 2402 2403
        }
    }
}

2404
impl Clean<TypeBinding> for hir::TypeBinding {
2405
    fn clean(&self, cx: &DocContext<'_>) -> TypeBinding {
2406
        TypeBinding {
2407
            name: self.ident.name.clean(cx),
2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423
            kind: self.kind.clean(cx),
        }
    }
}

impl Clean<TypeBindingKind> for hir::TypeBindingKind {
    fn clean(&self, cx: &DocContext<'_>) -> TypeBindingKind {
        match *self {
            hir::TypeBindingKind::Equality { ref ty } =>
                TypeBindingKind::Equality {
                    ty: ty.clean(cx),
                },
            hir::TypeBindingKind::Constraint { ref bounds } =>
                TypeBindingKind::Constraint {
                    bounds: bounds.into_iter().map(|b| b.clean(cx)).collect(),
                },
2424 2425 2426
        }
    }
}
2427 2428

enum SimpleBound {
V
varkor 已提交
2429 2430
    TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier),
    Outlives(Lifetime),
2431 2432
}

V
varkor 已提交
2433 2434
impl From<GenericBound> for SimpleBound {
    fn from(bound: GenericBound) -> Self {
2435
        match bound.clone() {
V
varkor 已提交
2436 2437
            GenericBound::Outlives(l) => SimpleBound::Outlives(l),
            GenericBound::TraitBound(t, mod_) => match t.trait_ {
V
varkor 已提交
2438
                Type::ResolvedPath { path, param_names, .. } => {
2439
                    SimpleBound::TraitBound(path.segments,
V
varkor 已提交
2440
                                            param_names
2441 2442 2443 2444 2445
                                                .map_or_else(|| Vec::new(), |v| v.iter()
                                                        .map(|p| SimpleBound::from(p.clone()))
                                                        .collect()),
                                            t.generic_params,
                                            mod_)
A
Aaron Hill 已提交
2446
                }
A
Aaron Hill 已提交
2447
                _ => panic!("Unexpected bound {:?}", bound),
2448 2449 2450 2451
            }
        }
    }
}