mod.rs 90.8 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
mod auto_trait;
mod blanket_impl;
6 7
crate mod cfg;
crate mod inline;
8
mod simplify;
9 10
crate mod types;
crate mod utils;
S
Steven Fackler 已提交
11

U
Ujjwal Sharma 已提交
12
use rustc_ast as ast;
13
use rustc_attr as attr;
14
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
15 16 17
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
M
Mark Rousskov 已提交
18
use rustc_index::vec::{Idx, IndexVec};
C
Camille GILLOT 已提交
19
use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
D
David Wood 已提交
20
use rustc_middle::bug;
M
Mazdak Farrokhzad 已提交
21 22
use rustc_middle::middle::resolve_lifetime as rl;
use rustc_middle::ty::fold::TypeFolder;
M
Matthew Jasper 已提交
23
use rustc_middle::ty::subst::{InternalSubsts, Subst};
M
Mazdak Farrokhzad 已提交
24
use rustc_middle::ty::{self, AdtKind, Lift, Ty, TyCtxt};
25
use rustc_mir::const_eval::{is_const_fn, is_min_const_fn, is_unstable_const_fn};
26
use rustc_span::hygiene::{AstPass, MacroKind};
27
use rustc_span::symbol::{kw, sym, Ident, Symbol};
28
use rustc_span::{self, ExpnKind, Pos};
M
Mark Rousskov 已提交
29
use rustc_typeck::hir_ty_to_ty;
30

31
use std::collections::hash_map::Entry;
32
use std::default::Default;
M
Mark Rousskov 已提交
33
use std::hash::Hash;
34
use std::rc::Rc;
M
Mark Rousskov 已提交
35
use std::{mem, vec};
36

37
use crate::core::{self, DocContext, ImplTraitParam};
38 39
use crate::doctree;

G
Guillaume Gomez 已提交
40 41
use utils::*;

42
crate use utils::{get_auto_trait_and_blanket_impls, krate, register_res};
G
Guillaume Gomez 已提交
43

44 45 46 47 48 49
crate use self::types::FnRetTy::*;
crate use self::types::ItemKind::*;
crate use self::types::SelfTy::*;
crate use self::types::Type::*;
crate use self::types::Visibility::{Inherited, Public};
crate use self::types::*;
50

51
const FN_OUTPUT_NAME: &str = "Output";
K
kennytm 已提交
52

53
crate trait Clean<T> {
54
    fn clean(&self, cx: &DocContext<'_>) -> T;
C
Corey Richardson 已提交
55 56
}

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

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

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

75
impl<T: Clean<U>, U> Clean<U> for Rc<T> {
76
    fn clean(&self, cx: &DocContext<'_>) -> U {
77
        (**self).clean(cx)
78 79 80
    }
}

C
Corey Richardson 已提交
81
impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
82
    fn clean(&self, cx: &DocContext<'_>) -> Option<U> {
M
mitaa 已提交
83
        self.as_ref().map(|v| v.clean(cx))
C
Corey Richardson 已提交
84 85 86
    }
}

A
Ariel Ben-Yehuda 已提交
87
impl Clean<ExternalCrate> for CrateNum {
88
    fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate {
89 90
        let root = DefId { krate: *self, index: CRATE_DEF_INDEX };
        let krate_span = cx.tcx.def_span(root);
D
Donato Sciarra 已提交
91
        let krate_src = cx.sess().source_map().span_to_filename(krate_span);
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

        // 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.
110 111
        let as_primitive = |res: Res| {
            if let Res::Def(DefKind::Mod, def_id) = res {
112 113
                let attrs = cx.tcx.get_attrs(def_id).clean(cx);
                let mut prim = None;
114
                for attr in attrs.lists(sym::doc) {
115
                    if let Some(v) = attr.value_str() {
116
                        if attr.has_name(sym::primitive) {
117
                            prim = PrimitiveType::from_symbol(v);
118 119 120
                            if prim.is_some() {
                                break;
                            }
121
                            // FIXME: should warn on unknown primitives?
122 123 124 125 126 127 128 129
                        }
                    }
                }
                return prim.map(|p| (def_id, p, attrs));
            }
            None
        };
        let primitives = if root.is_local() {
M
Mark Rousskov 已提交
130 131 132
            cx.tcx
                .hir()
                .krate()
133
                .item
M
Mark Rousskov 已提交
134 135 136 137 138 139
                .module
                .item_ids
                .iter()
                .filter_map(|&id| {
                    let item = cx.tcx.hir().expect_item(id.id);
                    match item.kind {
140 141 142 143
                        hir::ItemKind::Mod(_) => as_primitive(Res::Def(
                            DefKind::Mod,
                            cx.tcx.hir().local_def_id(id.id).to_def_id(),
                        )),
M
Mark Rousskov 已提交
144 145 146 147 148
                        hir::ItemKind::Use(ref path, hir::UseKind::Single)
                            if item.vis.node.is_pub() =>
                        {
                            as_primitive(path.res).map(|(_, prim, attrs)| {
                                // Pretend the primitive is local.
149
                                (cx.tcx.hir().local_def_id(id.id).to_def_id(), prim, attrs)
M
Mark Rousskov 已提交
150 151 152
                            })
                        }
                        _ => None,
153
                    }
M
Mark Rousskov 已提交
154 155
                })
                .collect()
156
        } else {
M
Mark Rousskov 已提交
157 158 159 160 161 162
            cx.tcx
                .item_children(root)
                .iter()
                .map(|item| item.res)
                .filter_map(as_primitive)
                .collect()
163 164
        };

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

214
        ExternalCrate {
215
            name: cx.tcx.crate_name(*self).to_string(),
216
            src: krate_src,
217
            attrs: cx.tcx.get_attrs(root).clean(cx),
218
            primitives,
G
Guillaume Gomez 已提交
219
            keywords,
C
Corey Richardson 已提交
220 221 222 223
        }
    }
}

224
impl Clean<Item> for doctree::Module<'_> {
225
    fn clean(&self, cx: &DocContext<'_>) -> Item {
226 227 228
        // 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
229
        let attrs = self.attrs.clean(cx);
M
Manish Goregaokar 已提交
230

231
        let mut items: Vec<Item> = vec![];
D
DebugSteven 已提交
232
        items.extend(self.extern_crates.iter().flat_map(|x| x.clean(cx)));
233
        items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
234
        items.extend(self.fns.iter().map(|x| x.clean(cx)));
235
        items.extend(self.foreigns.iter().map(|x| x.clean(cx)));
236
        items.extend(self.mods.iter().map(|x| x.clean(cx)));
J
Joshua Nelson 已提交
237
        items.extend(self.items.iter().map(|x| x.clean(cx)).flatten());
238 239
        items.extend(self.traits.iter().map(|x| x.clean(cx)));
        items.extend(self.macros.iter().map(|x| x.clean(cx)));
240
        items.extend(self.proc_macros.iter().map(|x| x.clean(cx)));
241 242 243

        // determine if we should display the inner contents or
        // the outer `mod` item for the source code.
C
Camelid 已提交
244
        let span = {
245 246 247
            let sm = cx.sess().source_map();
            let outer = sm.lookup_char_pos(self.where_outer.lo());
            let inner = sm.lookup_char_pos(self.where_inner.lo());
248 249 250 251
            if outer.file.start_pos == inner.file.start_pos {
                // mod foo { ... }
                self.where_outer
            } else {
D
Donato Sciarra 已提交
252
                // mod foo; (and a separate SourceFile for the contents)
253 254 255 256
                self.where_inner
            }
        };

257 258 259 260 261 262
        let what_rustc_thinks = Item::from_hir_id_and_parts(
            self.id,
            self.name,
            ModuleItem(Module { is_crate: self.is_crate, items }),
            cx,
        );
C
Corey Richardson 已提交
263
        Item {
264
            name: Some(what_rustc_thinks.name.unwrap_or_default()),
265
            attrs,
C
Camelid 已提交
266
            source: span.clean(cx),
267
            ..what_rustc_thinks
C
Corey Richardson 已提交
268 269 270 271
        }
    }
}

272
impl Clean<Attributes> for [ast::Attribute] {
273
    fn clean(&self, cx: &DocContext<'_>) -> Attributes {
274
        Attributes::from_ast(cx.sess().diagnostic(), self, None)
C
Corey Richardson 已提交
275 276 277
    }
}

C
Camille GILLOT 已提交
278
impl Clean<GenericBound> for hir::GenericBound<'_> {
279
    fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
C
Corey Richardson 已提交
280
        match *self {
V
varkor 已提交
281
            hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)),
D
David Wood 已提交
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
            hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
                let def_id = cx.tcx.require_lang_item(lang_item, Some(span));

                let trait_ref = ty::TraitRef::identity(cx.tcx, def_id);

                let generic_args = generic_args.clean(cx);
                let bindings = match generic_args {
                    GenericArgs::AngleBracketed { bindings, .. } => bindings,
                    _ => bug!("clean: parenthesized `GenericBound::LangItemTrait`"),
                };

                GenericBound::TraitBound(
                    PolyTrait { trait_: (trait_ref, &*bindings).clean(cx), generic_params: vec![] },
                    hir::TraitBoundModifier::None,
                )
            }
V
varkor 已提交
298 299 300
            hir::GenericBound::Trait(ref t, modifier) => {
                GenericBound::TraitBound(t.clean(cx), modifier)
            }
C
Corey Richardson 已提交
301 302 303 304
        }
    }
}

305 306 307
impl Clean<Type> for (ty::TraitRef<'_>, &[TypeBinding]) {
    fn clean(&self, cx: &DocContext<'_>) -> Type {
        let (trait_ref, bounds) = *self;
308
        inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait);
M
Mark Rousskov 已提交
309 310 311 312 313
        let path = external_path(
            cx,
            cx.tcx.item_name(trait_ref.def_id),
            Some(trait_ref.def_id),
            true,
314
            bounds.to_vec(),
M
Mark Rousskov 已提交
315 316
            trait_ref.substs,
        );
317

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

320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
        ResolvedPath { path, param_names: None, did: trait_ref.def_id, is_generic: false }
    }
}

impl<'tcx> Clean<GenericBound> for ty::TraitRef<'tcx> {
    fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
        GenericBound::TraitBound(
            PolyTrait { trait_: (*self, &[][..]).clean(cx), generic_params: vec![] },
            hir::TraitBoundModifier::None,
        )
    }
}

impl Clean<GenericBound> for (ty::PolyTraitRef<'_>, &[TypeBinding]) {
    fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
        let (poly_trait_ref, bounds) = *self;
        let poly_trait_ref = poly_trait_ref.lift_to_tcx(cx.tcx).unwrap();

338
        // collect any late bound regions
339 340 341 342 343 344 345 346 347 348 349 350
        let late_bound_regions: Vec<_> = cx
            .tcx
            .collect_referenced_late_bound_regions(&poly_trait_ref)
            .into_iter()
            .filter_map(|br| match br {
                ty::BrNamed(_, name) => Some(GenericParamDef {
                    name: name.to_string(),
                    kind: GenericParamDefKind::Lifetime,
                }),
                _ => None,
            })
            .collect();
351

V
varkor 已提交
352
        GenericBound::TraitBound(
353
            PolyTrait {
354
                trait_: (poly_trait_ref.skip_binder(), bounds).clean(cx),
355
                generic_params: late_bound_regions,
356
            },
M
Mark Rousskov 已提交
357
            hir::TraitBoundModifier::None,
358
        )
359 360 361
    }
}

362
impl<'tcx> Clean<GenericBound> for ty::PolyTraitRef<'tcx> {
363
    fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
364
        (*self, &[][..]).clean(cx)
365 366 367
    }
}

C
csmoe 已提交
368
impl<'tcx> Clean<Option<Vec<GenericBound>>> for InternalSubsts<'tcx> {
369
    fn clean(&self, cx: &DocContext<'_>) -> Option<Vec<GenericBound>> {
370
        let mut v = Vec::new();
V
varkor 已提交
371
        v.extend(self.regions().filter_map(|r| r.clean(cx)).map(GenericBound::Outlives));
M
Mark Rousskov 已提交
372 373 374 375 376 377 378
        v.extend(self.types().map(|t| {
            GenericBound::TraitBound(
                PolyTrait { trait_: t.clean(cx), generic_params: Vec::new() },
                hir::TraitBoundModifier::None,
            )
        }));
        if !v.is_empty() { Some(v) } else { None }
379 380 381
    }
}

382
impl Clean<Lifetime> for hir::Lifetime {
383
    fn clean(&self, cx: &DocContext<'_>) -> Lifetime {
M
marmeladema 已提交
384 385
        let def = cx.tcx.named_region(self.hir_id);
        match def {
J
Josh Stone 已提交
386 387 388 389 390
            Some(
                rl::Region::EarlyBound(_, node_id, _)
                | rl::Region::LateBound(_, node_id, _)
                | rl::Region::Free(_, node_id),
            ) => {
M
marmeladema 已提交
391 392
                if let Some(lt) = cx.lt_substs.borrow().get(&node_id).cloned() {
                    return lt;
E
Eduard Burtescu 已提交
393 394
                }
            }
M
marmeladema 已提交
395
            _ => {}
E
Eduard Burtescu 已提交
396
        }
397
        Lifetime(self.name.ident().to_string())
C
Corey Richardson 已提交
398 399 400
    }
}

C
Camille GILLOT 已提交
401
impl Clean<Lifetime> for hir::GenericParam<'_> {
402
    fn clean(&self, _: &DocContext<'_>) -> Lifetime {
V
varkor 已提交
403
        match self.kind {
V
varkor 已提交
404
            hir::GenericParamKind::Lifetime { .. } => {
405
                if !self.bounds.is_empty() {
V
varkor 已提交
406
                    let mut bounds = self.bounds.iter().map(|bound| match bound {
V
varkor 已提交
407
                        hir::GenericBound::Outlives(lt) => lt,
V
varkor 已提交
408 409
                        _ => panic!(),
                    });
G
Guillaume Gomez 已提交
410
                    let name = bounds.next().expect("no more bounds").name.ident();
411
                    let mut s = format!("{}: {}", self.name.ident(), name);
V
varkor 已提交
412
                    for bound in bounds {
413
                        s.push_str(&format!(" + {}", bound.name.ident()));
V
varkor 已提交
414 415 416
                    }
                    Lifetime(s)
                } else {
417
                    Lifetime(self.name.ident().to_string())
V
varkor 已提交
418
                }
419
            }
V
varkor 已提交
420
            _ => panic!(),
421
        }
422 423 424
    }
}

V
varkor 已提交
425
impl Clean<Constant> for hir::ConstArg {
426
    fn clean(&self, cx: &DocContext<'_>) -> Constant {
V
varkor 已提交
427
        Constant {
428 429 430 431
            type_: cx
                .tcx
                .type_of(cx.tcx.hir().body_owner_def_id(self.value.body).to_def_id())
                .clean(cx),
V
varkor 已提交
432
            expr: print_const_expr(cx, self.value.body),
433 434
            value: None,
            is_literal: is_literal_expr(cx, self.value.body.hir_id),
V
varkor 已提交
435 436 437 438
        }
    }
}

439
impl Clean<Lifetime> for ty::GenericParamDef {
440
    fn clean(&self, _cx: &DocContext<'_>) -> Lifetime {
441
        Lifetime(self.name.to_string())
442 443 444
    }
}

445
impl Clean<Option<Lifetime>> for ty::RegionKind {
446
    fn clean(&self, cx: &DocContext<'_>) -> Option<Lifetime> {
447
        match *self {
448
            ty::ReStatic => Some(Lifetime::statik()),
449
            ty::ReLateBound(_, ty::BrNamed(_, name)) => Some(Lifetime(name.to_string())),
N
Niko Matsakis 已提交
450
            ty::ReEarlyBound(ref data) => Some(Lifetime(data.name.clean(cx))),
451

M
Mark Rousskov 已提交
452 453 454 455
            ty::ReLateBound(..)
            | ty::ReFree(..)
            | ty::ReVar(..)
            | ty::RePlaceholder(..)
N
Niko Matsakis 已提交
456
            | ty::ReEmpty(_)
M
Mark Rousskov 已提交
457
            | ty::ReErased => {
458
                debug!("cannot clean region {:?}", self);
459 460
                None
            }
461 462 463 464
        }
    }
}

C
Camille GILLOT 已提交
465
impl Clean<WherePredicate> for hir::WherePredicate<'_> {
466
    fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
N
Nick Cameron 已提交
467
        match *self {
M
Mark Rousskov 已提交
468 469 470 471
            hir::WherePredicate::BoundPredicate(ref wbp) => WherePredicate::BoundPredicate {
                ty: wbp.bounded_ty.clean(cx),
                bounds: wbp.bounds.clean(cx),
            },
472

M
Mark Rousskov 已提交
473 474 475 476
            hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
                lifetime: wrp.lifetime.clean(cx),
                bounds: wrp.bounds.clean(cx),
            },
477

478
            hir::WherePredicate::EqPredicate(ref wrp) => {
M
Mark Rousskov 已提交
479
                WherePredicate::EqPredicate { lhs: wrp.lhs_ty.clean(cx), rhs: wrp.rhs_ty.clean(cx) }
N
Nick Cameron 已提交
480
            }
481 482 483 484
        }
    }
}

485
impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
486
    fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
B
Bastian Kauschke 已提交
487 488
        match self.skip_binders() {
            ty::PredicateAtom::Trait(pred, _) => Some(ty::Binder::bind(pred).clean(cx)),
B
Bastian Kauschke 已提交
489 490 491
            ty::PredicateAtom::RegionOutlives(pred) => pred.clean(cx),
            ty::PredicateAtom::TypeOutlives(pred) => pred.clean(cx),
            ty::PredicateAtom::Projection(pred) => Some(pred.clean(cx)),
B
Bastian Kauschke 已提交
492

B
Bastian Kauschke 已提交
493 494
            ty::PredicateAtom::Subtype(..)
            | ty::PredicateAtom::WellFormed(..)
B
Bastian Kauschke 已提交
495 496 497
            | ty::PredicateAtom::ObjectSafe(..)
            | ty::PredicateAtom::ClosureKind(..)
            | ty::PredicateAtom::ConstEvaluatable(..)
498 499
            | ty::PredicateAtom::ConstEquate(..)
            | ty::PredicateAtom::TypeWellFormedFromEnv(..) => panic!("not user writable"),
500 501 502 503
        }
    }
}

504
impl<'a> Clean<WherePredicate> for ty::PolyTraitPredicate<'a> {
505
    fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
506
        let poly_trait_ref = self.map_bound(|pred| pred.trait_ref);
507
        WherePredicate::BoundPredicate {
508
            ty: poly_trait_ref.skip_binder().self_ty().clean(cx),
509
            bounds: vec![poly_trait_ref.clean(cx)],
510 511 512 513
        }
    }
}

M
Mark Rousskov 已提交
514
impl<'tcx> Clean<Option<WherePredicate>>
B
Bastian Kauschke 已提交
515
    for ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
M
Mark Rousskov 已提交
516
{
517
    fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
B
Bastian Kauschke 已提交
518
        let ty::OutlivesPredicate(a, b) = self;
519

M
Matthias Krüger 已提交
520 521
        if let (ty::ReEmpty(_), ty::ReEmpty(_)) = (a, b) {
            return None;
522 523 524
        }

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

B
Bastian Kauschke 已提交
531
impl<'tcx> Clean<Option<WherePredicate>> for ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>> {
532
    fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
B
Bastian Kauschke 已提交
533
        let ty::OutlivesPredicate(ty, lt) = self;
534

M
Matthias Krüger 已提交
535 536
        if let ty::ReEmpty(_) = lt {
            return None;
537 538 539
        }

        Some(WherePredicate::BoundPredicate {
540
            ty: ty.clean(cx),
M
Mark Rousskov 已提交
541
            bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))],
542
        })
543 544 545
    }
}

B
Bastian Kauschke 已提交
546
impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
547
    fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
B
Bastian Kauschke 已提交
548
        let ty::ProjectionPredicate { projection_ty, ty } = self;
549
        WherePredicate::EqPredicate { lhs: projection_ty.clean(cx), rhs: ty.clean(cx) }
550 551 552 553
    }
}

impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
554
    fn clean(&self, cx: &DocContext<'_>) -> Type {
M
Matthew Jasper 已提交
555 556
        let lifted = self.lift_to_tcx(cx.tcx).unwrap();
        let trait_ = match lifted.trait_ref(cx.tcx).clean(cx) {
V
varkor 已提交
557 558
            GenericBound::TraitBound(t, _) => t.trait_,
            GenericBound::Outlives(_) => panic!("cleaning a trait got a lifetime"),
559 560
        };
        Type::QPath {
561
            name: cx.tcx.associated_item(self.item_def_id).ident.name.clean(cx),
562
            self_type: box self.self_ty().clean(cx),
M
Mark Rousskov 已提交
563
            trait_: box trait_,
564 565 566 567
        }
    }
}

568
impl Clean<GenericParamDef> for ty::GenericParamDef {
569
    fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
570 571 572 573
        let (name, kind) = match self.kind {
            ty::GenericParamDefKind::Lifetime => {
                (self.name.to_string(), GenericParamDefKind::Lifetime)
            }
574
            ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
M
Mark Rousskov 已提交
575 576 577 578 579 580 581 582 583 584 585
                let default =
                    if has_default { Some(cx.tcx.type_of(self.def_id).clean(cx)) } else { None };
                (
                    self.name.clean(cx),
                    GenericParamDefKind::Type {
                        did: self.def_id,
                        bounds: vec![], // These are filled in from the where-clauses.
                        default,
                        synthetic,
                    },
                )
586
            }
M
Mark Rousskov 已提交
587 588 589
            ty::GenericParamDefKind::Const { .. } => (
                self.name.clean(cx),
                GenericParamDefKind::Const {
590 591
                    did: self.def_id,
                    ty: cx.tcx.type_of(self.def_id).clean(cx),
M
Mark Rousskov 已提交
592 593
                },
            ),
594 595
        };

M
Mark Rousskov 已提交
596
        GenericParamDef { name, kind }
597 598 599
    }
}

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

M
Mark Rousskov 已提交
638
        GenericParamDef { name, kind }
639 640 641
    }
}

C
Camille GILLOT 已提交
642
impl Clean<Generics> for hir::Generics<'_> {
643
    fn clean(&self, cx: &DocContext<'_>) -> Generics {
644 645 646
        // Synthetic type-parameters are inserted after normal ones.
        // In order for normal parameters to be able to refer to synthetic ones,
        // scans them first.
C
Camille GILLOT 已提交
647
        fn is_impl_trait(param: &hir::GenericParam<'_>) -> bool {
V
varkor 已提交
648 649 650 651 652
            match param.kind {
                hir::GenericParamKind::Type { synthetic, .. } => {
                    synthetic == Some(hir::SyntheticTyParamKind::ImplTrait)
                }
                _ => false,
653 654
            }
        }
M
Mark Rousskov 已提交
655 656
        let impl_trait_params = self
            .params
657
            .iter()
658 659 660 661 662 663
            .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, .. } => {
664
                        cx.impl_trait_bounds.borrow_mut().insert(did.into(), bounds.clone());
665
                    }
V
varkor 已提交
666
                    GenericParamDefKind::Const { .. } => unreachable!(),
667
                }
668
                param
669 670 671
            })
            .collect::<Vec<_>>();

672
        let mut params = Vec::with_capacity(self.params.len());
673
        for p in self.params.iter().filter(|p| !is_impl_trait(p)) {
674 675 676
            let p = p.clean(cx);
            params.push(p);
        }
677 678
        params.extend(impl_trait_params);

M
Mark Rousskov 已提交
679 680
        let mut generics =
            Generics { params, where_predicates: self.where_clause.predicates.clean(cx) };
681 682 683 684

        // 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.
685
        for where_pred in &mut generics.where_predicates {
686 687 688
            match *where_pred {
                WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => {
                    if bounds.is_empty() {
689 690 691 692 693 694
                        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);
M
Mark Rousskov 已提交
695
                                        break;
696
                                    }
697
                                }
V
varkor 已提交
698
                                GenericParamDefKind::Const { .. } => {}
699 700 701 702 703 704
                            }
                        }
                    }
                }
                _ => continue,
            }
C
Corey Richardson 已提交
705
        }
706
        generics
C
Corey Richardson 已提交
707 708 709
    }
}

710
impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx>) {
711
    fn clean(&self, cx: &DocContext<'_>) -> Generics {
712
        use self::WherePredicate as WP;
713
        use std::collections::BTreeMap;
714

715
        let (gens, preds) = *self;
716

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

721 722 723
        // Bounds in the type_params and lifetimes fields are repeated in the
        // predicates field (see rustc_typeck::collect::ty_generics), so remove
        // them.
724
        let stripped_params = gens
M
Mark Rousskov 已提交
725 726
            .params
            .iter()
727
            .filter_map(|param| match param.kind {
728
                ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
729
                ty::GenericParamDefKind::Type { synthetic, .. } => {
730
                    if param.name == kw::SelfUpper {
731 732 733 734 735 736 737 738
                        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 已提交
739
                }
740
                ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)),
M
Mark Rousskov 已提交
741 742
            })
            .collect::<Vec<GenericParamDef>>();
743

S
Shotaro Yamada 已提交
744
        // param index -> [(DefId of trait, associated type name, type)]
M
Mark Rousskov 已提交
745
        let mut impl_trait_proj = FxHashMap::<u32, Vec<(DefId, String, Ty<'tcx>)>>::default();
746

M
Mark Rousskov 已提交
747 748 749
        let where_predicates = preds
            .predicates
            .iter()
750
            .flat_map(|(p, _)| {
S
Shotaro Yamada 已提交
751
                let mut projection = None;
752
                let param_idx = (|| {
B
Bastian Kauschke 已提交
753 754
                    match p.skip_binders() {
                        ty::PredicateAtom::Trait(pred, _constness) => {
755
                            if let ty::Param(param) = pred.self_ty().kind() {
B
rustdoc  
Bastian Kauschke 已提交
756 757
                                return Some(param.index);
                            }
758
                        }
B
Bastian Kauschke 已提交
759
                        ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
760
                            if let ty::Param(param) = ty.kind() {
B
rustdoc  
Bastian Kauschke 已提交
761 762
                                return Some(param.index);
                            }
763
                        }
B
Bastian Kauschke 已提交
764
                        ty::PredicateAtom::Projection(p) => {
765
                            if let ty::Param(param) = p.projection_ty.self_ty().kind() {
B
rustdoc  
Bastian Kauschke 已提交
766 767 768
                                projection = Some(ty::Binder::bind(p));
                                return Some(param.index);
                            }
769
                        }
B
rustdoc  
Bastian Kauschke 已提交
770
                        _ => (),
771
                    }
772

773
                    None
774
                })();
775

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

780 781 782 783 784
                        b.extend(
                            p.get_bounds()
                                .into_iter()
                                .flatten()
                                .cloned()
M
Mark Rousskov 已提交
785
                                .filter(|b| !b.is_sized_bound(cx)),
786 787
                        );

S
Shotaro Yamada 已提交
788 789 790 791 792
                        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)))
                        {
M
Mark Rousskov 已提交
793 794 795 796 797
                            impl_trait_proj.entry(param_idx).or_default().push((
                                trait_did,
                                name.to_string(),
                                rhs,
                            ));
798 799 800 801
                        }

                        return None;
                    }
802 803 804 805
                }

                Some(p)
            })
806
            .collect::<Vec<_>>();
807

808 809
        for (param, mut bounds) in impl_trait {
            // Move trait bounds to the front.
M
Mark Rousskov 已提交
810
            bounds.sort_by_key(|b| if let GenericBound::TraitBound(..) = b { false } else { true });
811

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

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

825 826
        // Now that `cx.impl_trait_bounds` is populated, we can process
        // remaining predicates which could contain `impl Trait`.
M
Mark Rousskov 已提交
827 828
        let mut where_predicates =
            where_predicates.into_iter().flat_map(|p| p.clean(cx)).collect::<Vec<_>>();
829

A
Anthony Ramine 已提交
830
        // Type parameters have a Sized bound by default unless removed with
831
        // ?Sized. Scan through the predicates and mark any type parameter with
832
        // a Sized bound, removing the bounds as we find them.
833 834
        //
        // Note that associated types also have a sized bound by default, but we
835
        // don't actually know the set of associated types right here so that's
836
        // handled in cleaning associated types
837
        let mut sized_params = FxHashSet::default();
M
Mark Rousskov 已提交
838 839 840 841 842 843 844
        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
845 846
                }
            }
M
Mark Rousskov 已提交
847
            _ => true,
848
        });
849

850
        // Run through the type parameters again and insert a ?Sized
851
        // unbound for any we didn't find to be Sized.
852 853 854 855
        for tp in &stripped_params {
            if matches!(tp.kind, types::GenericParamDefKind::Type { .. })
                && !sized_params.contains(&tp.name)
            {
856 857
                where_predicates.push(WP::BoundPredicate {
                    ty: Type::Generic(tp.name.clone()),
V
varkor 已提交
858
                    bounds: vec![GenericBound::maybe_sized(cx)],
859 860 861 862 863
                })
            }
        }

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

867
        Generics {
868
            params: stripped_params,
869
            where_predicates: simplify::where_clauses(cx, where_predicates),
870 871 872 873
        }
    }
}

J
Joshua Nelson 已提交
874 875
impl<'a> Clean<Function> for (&'a hir::FnSig<'a>, &'a hir::Generics<'a>, hir::BodyId) {
    fn clean(&self, cx: &DocContext<'_>) -> Function {
M
Mark Rousskov 已提交
876 877
        let (generics, decl) =
            enter_impl_trait(cx, || (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx)));
878
        let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
J
Joshua Nelson 已提交
879
        Function { decl, generics, header: self.0.header, all_types, ret_types }
C
Corey Richardson 已提交
880 881 882
    }
}

883
impl Clean<Item> for doctree::Function<'_> {
884
    fn clean(&self, cx: &DocContext<'_>) -> Item {
M
Mark Rousskov 已提交
885 886
        let (generics, decl) =
            enter_impl_trait(cx, || (self.generics.clean(cx), (self.decl, self.body).clean(cx)));
G
Guillaume Gomez 已提交
887

888 889
        let did = cx.tcx.hir().local_def_id(self.id).to_def_id();
        let constness = if is_const_fn(cx.tcx, did) && !is_unstable_const_fn(cx.tcx, did).is_some()
S
SlightlyOutOfPhase 已提交
890
        {
G
Guillaume Gomez 已提交
891 892 893 894
            hir::Constness::Const
        } else {
            hir::Constness::NotConst
        };
895
        let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
896 897 898 899
        Item::from_def_id_and_parts(
            did,
            Some(self.name),
            FunctionItem(Function {
900 901
                decl,
                generics,
G
Guillaume Gomez 已提交
902
                header: hir::FnHeader { constness, ..self.header },
903
                all_types,
904
                ret_types,
C
Corey Richardson 已提交
905
            }),
906 907
            cx,
        )
C
Corey Richardson 已提交
908 909 910
    }
}

911
impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], &'a [Ident]) {
912
    fn clean(&self, cx: &DocContext<'_>) -> Arguments {
913
        Arguments {
M
Mark Rousskov 已提交
914 915 916 917 918
            values: self
                .0
                .iter()
                .enumerate()
                .map(|(i, ty)| {
919
                    let mut name = self.1.get(i).map(|ident| ident.to_string()).unwrap_or_default();
M
Mark Rousskov 已提交
920 921 922 923 924 925
                    if name.is_empty() {
                        name = "_".to_string();
                    }
                    Argument { name, type_: ty.clean(cx) }
                })
                .collect(),
926 927 928 929
        }
    }
}

C
Camille GILLOT 已提交
930
impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], hir::BodyId) {
931
    fn clean(&self, cx: &DocContext<'_>) -> Arguments {
932
        let body = cx.tcx.hir().body(self.1);
933 934

        Arguments {
M
Mark Rousskov 已提交
935 936 937 938 939
            values: self
                .0
                .iter()
                .enumerate()
                .map(|(i, ty)| Argument {
940
                    name: name_from_pat(&body.params[i].pat),
941
                    type_: ty.clean(cx),
M
Mark Rousskov 已提交
942 943
                })
                .collect(),
944 945 946 947
        }
    }
}

C
Camille GILLOT 已提交
948
impl<'a, A: Copy> Clean<FnDecl> for (&'a hir::FnDecl<'a>, A)
M
Mark Rousskov 已提交
949
where
C
Camille GILLOT 已提交
950
    (&'a [hir::Ty<'a>], A): Clean<Arguments>,
951
{
952
    fn clean(&self, cx: &DocContext<'_>) -> FnDecl {
C
Corey Richardson 已提交
953
        FnDecl {
954 955
            inputs: (&self.0.inputs[..], self.1).clean(cx),
            output: self.0.output.clean(cx),
956
            c_variadic: self.0.c_variadic,
957
            attrs: Attributes::default(),
C
Corey Richardson 已提交
958 959 960 961
        }
    }
}

962
impl<'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
963
    fn clean(&self, cx: &DocContext<'_>) -> FnDecl {
964
        let (did, sig) = *self;
965
        let mut names = if did.is_local() { &[] } else { cx.tcx.fn_arg_names(did) }.iter();
S
Cleanup  
Shotaro Yamada 已提交
966

967
        FnDecl {
968
            output: Return(sig.skip_binder().output().clean(cx)),
969
            attrs: Attributes::default(),
970
            c_variadic: sig.skip_binder().c_variadic,
971
            inputs: Arguments {
M
Mark Rousskov 已提交
972 973 974 975 976
                values: sig
                    .skip_binder()
                    .inputs()
                    .iter()
                    .map(|t| Argument {
977
                        type_: t.clean(cx),
978
                        name: names.next().map_or(String::new(), |name| name.to_string()),
M
Mark Rousskov 已提交
979 980
                    })
                    .collect(),
981 982 983 984 985
            },
        }
    }
}

986 987
impl Clean<FnRetTy> for hir::FnRetTy<'_> {
    fn clean(&self, cx: &DocContext<'_>) -> FnRetTy {
C
Corey Richardson 已提交
988
        match *self {
989 990
            Self::Return(ref typ) => Return(typ.clean(cx)),
            Self::DefaultReturn(..) => DefaultReturn,
C
Corey Richardson 已提交
991 992 993 994
        }
    }
}

995
impl Clean<Item> for doctree::Trait<'_> {
996
    fn clean(&self, cx: &DocContext<'_>) -> Item {
997
        let attrs = self.attrs.clean(cx);
998
        let is_spotlight = attrs.has_doc_flag(sym::spotlight);
999 1000 1001 1002
        Item::from_hir_id_and_parts(
            self.id,
            Some(self.name),
            TraitItem(Trait {
1003
                unsafety: self.unsafety,
1004
                items: self.items.iter().map(|ti| ti.clean(cx)).collect(),
1005 1006
                generics: self.generics.clean(cx),
                bounds: self.bounds.clean(cx),
1007
                is_spotlight,
1008
                is_auto: self.is_auto.clean(cx),
C
Corey Richardson 已提交
1009
            }),
1010 1011
            cx,
        )
C
Corey Richardson 已提交
1012 1013 1014
    }
}

1015
impl Clean<bool> for hir::IsAuto {
1016
    fn clean(&self, _: &DocContext<'_>) -> bool {
1017 1018 1019 1020 1021 1022 1023
        match *self {
            hir::IsAuto::Yes => true,
            hir::IsAuto::No => false,
        }
    }
}

C
Camille GILLOT 已提交
1024
impl Clean<Type> for hir::TraitRef<'_> {
1025
    fn clean(&self, cx: &DocContext<'_>) -> Type {
L
ljedrz 已提交
1026
        resolve_type(cx, self.path.clean(cx), self.hir_ref_id)
C
Corey Richardson 已提交
1027 1028 1029
    }
}

C
Camille GILLOT 已提交
1030
impl Clean<PolyTrait> for hir::PolyTraitRef<'_> {
1031
    fn clean(&self, cx: &DocContext<'_>) -> PolyTrait {
1032 1033
        PolyTrait {
            trait_: self.trait_ref.clean(cx),
M
Mark Rousskov 已提交
1034
            generic_params: self.bound_generic_params.clean(cx),
1035
        }
N
Niko Matsakis 已提交
1036 1037 1038
    }
}

1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058
impl Clean<TypeKind> for hir::def::DefKind {
    fn clean(&self, _: &DocContext<'_>) -> TypeKind {
        match *self {
            hir::def::DefKind::Mod => TypeKind::Module,
            hir::def::DefKind::Struct => TypeKind::Struct,
            hir::def::DefKind::Union => TypeKind::Union,
            hir::def::DefKind::Enum => TypeKind::Enum,
            hir::def::DefKind::Trait => TypeKind::Trait,
            hir::def::DefKind::TyAlias => TypeKind::Typedef,
            hir::def::DefKind::ForeignTy => TypeKind::Foreign,
            hir::def::DefKind::TraitAlias => TypeKind::TraitAlias,
            hir::def::DefKind::Fn => TypeKind::Function,
            hir::def::DefKind::Const => TypeKind::Const,
            hir::def::DefKind::Static => TypeKind::Static,
            hir::def::DefKind::Macro(_) => TypeKind::Macro,
            _ => TypeKind::Foreign,
        }
    }
}

C
Camille GILLOT 已提交
1059
impl Clean<Item> for hir::TraitItem<'_> {
1060
    fn clean(&self, cx: &DocContext<'_>) -> Item {
1061 1062
        let local_did = cx.tcx.hir().local_def_id(self.hir_id).to_def_id();
        let inner = match self.kind {
1063
            hir::TraitItemKind::Const(ref ty, default) => {
M
Mark Rousskov 已提交
1064
                AssocConstItem(ty.clean(cx), default.map(|e| print_const_expr(cx, e)))
1065
            }
M
Mark Mansi 已提交
1066
            hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
J
Joshua Nelson 已提交
1067
                let mut m = (sig, &self.generics, body).clean(cx);
1068
                if m.header.constness == hir::Constness::Const
1069
                    && is_unstable_const_fn(cx.tcx, local_did).is_some()
1070 1071 1072
                {
                    m.header.constness = hir::Constness::NotConst;
                }
J
Joshua Nelson 已提交
1073
                MethodItem(m, None)
1074
            }
M
Mark Mansi 已提交
1075
            hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref names)) => {
1076 1077 1078
                let (generics, decl) = enter_impl_trait(cx, || {
                    (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
                });
1079
                let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
J
Joshua Nelson 已提交
1080
                let mut t = Function { header: sig.header, decl, generics, all_types, ret_types };
1081
                if t.header.constness == hir::Constness::Const
1082
                    && is_unstable_const_fn(cx.tcx, local_did).is_some()
1083 1084 1085 1086
                {
                    t.header.constness = hir::Constness::NotConst;
                }
                TyMethodItem(t)
1087
            }
1088
            hir::TraitItemKind::Type(ref bounds, ref default) => {
A
Andrew Xu 已提交
1089
                AssocTypeItem(bounds.clean(cx), default.clean(cx))
1090 1091
            }
        };
1092
        Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx)
1093 1094 1095
    }
}

C
Camille GILLOT 已提交
1096
impl Clean<Item> for hir::ImplItem<'_> {
1097
    fn clean(&self, cx: &DocContext<'_>) -> Item {
1098 1099
        let local_did = cx.tcx.hir().local_def_id(self.hir_id).to_def_id();
        let inner = match self.kind {
1100
            hir::ImplItemKind::Const(ref ty, expr) => {
M
Mark Rousskov 已提交
1101
                AssocConstItem(ty.clean(cx), Some(print_const_expr(cx, expr)))
1102
            }
M
Mark Mansi 已提交
1103
            hir::ImplItemKind::Fn(ref sig, body) => {
J
Joshua Nelson 已提交
1104
                let mut m = (sig, &self.generics, body).clean(cx);
1105
                if m.header.constness == hir::Constness::Const
1106
                    && is_unstable_const_fn(cx.tcx, local_did).is_some()
1107 1108 1109
                {
                    m.header.constness = hir::Constness::NotConst;
                }
J
Joshua Nelson 已提交
1110
                MethodItem(m, Some(self.defaultness))
1111
            }
M
Mark Rousskov 已提交
1112
            hir::ImplItemKind::TyAlias(ref ty) => {
G
Guillaume Gomez 已提交
1113 1114
                let type_ = ty.clean(cx);
                let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
G
Guillaume Gomez 已提交
1115
                TypedefItem(Typedef { type_, generics: Generics::default(), item_type }, true)
M
Mark Rousskov 已提交
1116
            }
1117
        };
1118
        Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx)
C
Corey Richardson 已提交
1119 1120 1121
    }
}

1122
impl Clean<Item> for ty::AssocItem {
1123
    fn clean(&self, cx: &DocContext<'_>) -> Item {
1124
        let kind = match self.kind {
A
Andrew Xu 已提交
1125
            ty::AssocKind::Const => {
1126
                let ty = cx.tcx.type_of(self.def_id);
1127 1128 1129 1130 1131
                let default = if self.defaultness.has_value() {
                    Some(inline::print_inlined_const(cx, self.def_id))
                } else {
                    None
                };
A
Andrew Xu 已提交
1132
                AssocConstItem(ty.clean(cx), default)
1133
            }
1134
            ty::AssocKind::Fn => {
M
Mark Rousskov 已提交
1135 1136 1137
                let generics =
                    (cx.tcx.generics_of(self.def_id), cx.tcx.explicit_predicates_of(self.def_id))
                        .clean(cx);
1138
                let sig = cx.tcx.fn_sig(self.def_id);
1139
                let mut decl = (self.def_id, sig).clean(cx);
1140

1141
                if self.fn_has_self_parameter {
1142
                    let self_ty = match self.container {
M
Mark Rousskov 已提交
1143
                        ty::ImplContainer(def_id) => cx.tcx.type_of(def_id),
1144
                        ty::TraitContainer(_) => cx.tcx.types.self_param,
1145
                    };
1146
                    let self_arg_ty = sig.input(0).skip_binder();
1147
                    if self_arg_ty == self_ty {
1148
                        decl.inputs.values[0].type_ = Generic(String::from("Self"));
1149
                    } else if let ty::Ref(_, ty, _) = *self_arg_ty.kind() {
1150
                        if ty == self_ty {
1151
                            match decl.inputs.values[0].type_ {
M
Mark Rousskov 已提交
1152
                                BorrowedRef { ref mut type_, .. } => {
1153 1154
                                    **type_ = Generic(String::from("Self"))
                                }
1155 1156 1157 1158 1159
                                _ => unreachable!(),
                            }
                        }
                    }
                }
1160

1161
                let provided = match self.container {
1162
                    ty::ImplContainer(_) => true,
M
Mark Rousskov 已提交
1163
                    ty::TraitContainer(_) => self.defaultness.has_value(),
1164
                };
1165
                let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
1166
                if provided {
1167
                    let constness = if is_min_const_fn(cx.tcx, self.def_id) {
1168 1169 1170 1171
                        hir::Constness::Const
                    } else {
                        hir::Constness::NotConst
                    };
C
csmoe 已提交
1172
                    let asyncness = cx.tcx.asyncness(self.def_id);
1173 1174 1175 1176
                    let defaultness = match self.container {
                        ty::ImplContainer(_) => Some(self.defaultness),
                        ty::TraitContainer(_) => None,
                    };
J
Joshua Nelson 已提交
1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188
                    MethodItem(
                        Function {
                            generics,
                            decl,
                            header: hir::FnHeader {
                                unsafety: sig.unsafety(),
                                abi: sig.abi(),
                                constness,
                                asyncness,
                            },
                            all_types,
                            ret_types,
1189
                        },
1190
                        defaultness,
J
Joshua Nelson 已提交
1191
                    )
1192
                } else {
J
Joshua Nelson 已提交
1193
                    TyMethodItem(Function {
1194 1195
                        generics,
                        decl,
W
Without Boats 已提交
1196 1197 1198
                        header: hir::FnHeader {
                            unsafety: sig.unsafety(),
                            abi: sig.abi(),
1199 1200
                            constness: hir::Constness::NotConst,
                            asyncness: hir::IsAsync::NotAsync,
1201 1202
                        },
                        all_types,
1203
                        ret_types,
1204
                    })
1205 1206
                }
            }
A
Andrew Xu 已提交
1207
            ty::AssocKind::Type => {
1208
                let my_name = self.ident.name.clean(cx);
1209

M
Matthew Jasper 已提交
1210 1211 1212 1213
                if let ty::TraitContainer(_) = self.container {
                    let bounds = cx.tcx.explicit_item_bounds(self.def_id);
                    let predicates = ty::GenericPredicates { parent: None, predicates: bounds };
                    let generics = (cx.tcx.generics_of(self.def_id), predicates).clean(cx);
M
Mark Rousskov 已提交
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239
                    let mut bounds = generics
                        .where_predicates
                        .iter()
                        .filter_map(|pred| {
                            let (name, self_type, trait_, bounds) = match *pred {
                                WherePredicate::BoundPredicate {
                                    ty: QPath { ref name, ref self_type, ref trait_ },
                                    ref bounds,
                                } => (name, self_type, trait_, bounds),
                                _ => return None,
                            };
                            if *name != my_name {
                                return None;
                            }
                            match **trait_ {
                                ResolvedPath { did, .. } if did == self.container.id() => {}
                                _ => return None,
                            }
                            match **self_type {
                                Generic(ref s) if *s == "Self" => {}
                                _ => return None,
                            }
                            Some(bounds)
                        })
                        .flat_map(|i| i.iter().cloned())
                        .collect::<Vec<_>>();
1240 1241 1242 1243 1244 1245
                    // 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)) {
M
Mark Rousskov 已提交
1246 1247 1248
                        Some(i) => {
                            bounds.remove(i);
                        }
V
varkor 已提交
1249
                        None => bounds.push(GenericBound::maybe_sized(cx)),
1250
                    }
1251

1252 1253 1254 1255 1256
                    let ty = if self.defaultness.has_value() {
                        Some(cx.tcx.type_of(self.def_id))
                    } else {
                        None
                    };
1257

A
Andrew Xu 已提交
1258
                    AssocTypeItem(bounds, ty.clean(cx))
1259
                } else {
G
Guillaume Gomez 已提交
1260 1261
                    let type_ = cx.tcx.type_of(self.def_id).clean(cx);
                    let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
M
Mark Rousskov 已提交
1262 1263
                    TypedefItem(
                        Typedef {
G
Guillaume Gomez 已提交
1264
                            type_,
M
Mark Rousskov 已提交
1265
                            generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
G
Guillaume Gomez 已提交
1266
                            item_type,
1267
                        },
M
Mark Rousskov 已提交
1268 1269
                        true,
                    )
1270
                }
1271 1272 1273
            }
        };

1274
        Item::from_def_id_and_parts(self.def_id, Some(self.ident.name), kind, cx)
1275 1276 1277
    }
}

C
Camille GILLOT 已提交
1278
impl Clean<Type> for hir::Ty<'_> {
1279
    fn clean(&self, cx: &DocContext<'_>) -> Type {
1280
        use rustc_hir::*;
1281

V
varkor 已提交
1282
        match self.kind {
C
csmoe 已提交
1283
            TyKind::Never => Never,
G
Guillaume Gomez 已提交
1284
            TyKind::Ptr(ref m) => RawPointer(m.mutbl, box m.ty.clean(cx)),
C
csmoe 已提交
1285
            TyKind::Rptr(ref l, ref m) => {
M
Mark Rousskov 已提交
1286 1287
                let lifetime = if l.is_elided() { None } else { Some(l.clean(cx)) };
                BorrowedRef { lifetime, mutability: m.mutbl, type_: box m.ty.clean(cx) }
1288
            }
C
csmoe 已提交
1289 1290
            TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
            TyKind::Array(ref ty, ref length) => {
1291
                let def_id = cx.tcx.hir().local_def_id(length.hir_id);
1292 1293 1294 1295 1296 1297 1298 1299 1300 1301
                // NOTE(min_const_generics): We can't use `const_eval_poly` for constants
                // as we currently do not supply the parent generics to anonymous constants
                // but do allow `ConstKind::Param`.
                //
                // `const_eval_poly` tries to to first substitute generic parameters which
                // results in an ICE while manually constructing the constant and using `eval`
                // does nothing for `ConstKind::Param`.
                let ct = ty::Const::from_anon_const(cx.tcx, def_id);
                let param_env = cx.tcx.param_env(def_id);
                let length = print_const(cx, ct.eval(cx.tcx, param_env));
1302
                Array(box ty.clean(cx), length)
M
Mark Rousskov 已提交
1303
            }
C
csmoe 已提交
1304
            TyKind::Tup(ref tys) => Tuple(tys.clean(cx)),
1305
            TyKind::OpaqueDef(item_id, _) => {
1306
                let item = cx.tcx.hir().expect_item(item_id.id);
V
varkor 已提交
1307
                if let hir::ItemKind::OpaqueTy(ref ty) = item.kind {
O
Oliver Schneider 已提交
1308 1309 1310 1311 1312
                    ImplTrait(ty.bounds.clean(cx))
                } else {
                    unreachable!()
                }
            }
C
csmoe 已提交
1313
            TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
1314
                if let Res::Def(DefKind::TyParam, did) = path.res {
1315 1316 1317
                    if let Some(new_ty) = cx.ty_substs.borrow().get(&did).cloned() {
                        return new_ty;
                    }
1318
                    if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did.into()) {
1319 1320 1321 1322
                        return ImplTrait(bounds);
                    }
                }

1323
                let mut alias = None;
1324
                if let Res::Def(DefKind::TyAlias, def_id) = path.res {
1325
                    // Substitute private type aliases
M
marmeladema 已提交
1326
                    if let Some(def_id) = def_id.as_local() {
1327
                        let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
M
marmeladema 已提交
1328
                        if !cx.renderinfo.borrow().access_levels.is_exported(def_id.to_def_id()) {
V
varkor 已提交
1329
                            alias = Some(&cx.tcx.hir().expect_item(hir_id).kind);
1330
                        }
E
Eduard Burtescu 已提交
1331
                    }
1332 1333
                };

1334
                if let Some(&hir::ItemKind::TyAlias(ref ty, ref generics)) = alias {
G
Guillaume Gomez 已提交
1335
                    let provided_params = &path.segments.last().expect("segments were empty");
1336 1337
                    let mut ty_substs = FxHashMap::default();
                    let mut lt_substs = FxHashMap::default();
1338
                    let mut ct_substs = FxHashMap::default();
1339 1340
                    let generic_args = provided_params.generic_args();
                    {
V
varkor 已提交
1341
                        let mut indices: GenericParamCount = Default::default();
1342
                        for param in generics.params.iter() {
V
varkor 已提交
1343 1344
                            match param.kind {
                                hir::GenericParamKind::Lifetime { .. } => {
1345
                                    let mut j = 0;
M
Mark Rousskov 已提交
1346 1347
                                    let lifetime =
                                        generic_args.args.iter().find_map(|arg| match arg {
V
varkor 已提交
1348
                                            hir::GenericArg::Lifetime(lt) => {
1349 1350 1351 1352 1353 1354 1355
                                                if indices.lifetimes == j {
                                                    return Some(lt);
                                                }
                                                j += 1;
                                                None
                                            }
                                            _ => None,
M
Mark Rousskov 已提交
1356
                                        });
1357
                                    if let Some(lt) = lifetime.cloned() {
1358 1359 1360 1361 1362 1363 1364
                                        let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
                                        let cleaned = if !lt.is_elided() {
                                            lt.clean(cx)
                                        } else {
                                            self::types::Lifetime::elided()
                                        };
                                        lt_substs.insert(lt_def_id.to_def_id(), cleaned);
1365 1366 1367
                                    }
                                    indices.lifetimes += 1;
                                }
V
varkor 已提交
1368
                                hir::GenericParamKind::Type { ref default, .. } => {
M
Mark Rousskov 已提交
1369
                                    let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
1370
                                    let mut j = 0;
M
Mark Rousskov 已提交
1371 1372
                                    let type_ =
                                        generic_args.args.iter().find_map(|arg| match arg {
V
varkor 已提交
1373
                                            hir::GenericArg::Type(ty) => {
1374 1375 1376 1377 1378 1379 1380
                                                if indices.types == j {
                                                    return Some(ty);
                                                }
                                                j += 1;
                                                None
                                            }
                                            _ => None,
M
Mark Rousskov 已提交
1381
                                        });
1382
                                    if let Some(ty) = type_ {
1383
                                        ty_substs.insert(ty_param_def_id.to_def_id(), ty.clean(cx));
1384
                                    } else if let Some(default) = *default {
1385 1386
                                        ty_substs
                                            .insert(ty_param_def_id.to_def_id(), default.clean(cx));
1387
                                    }
1388
                                    indices.types += 1;
1389
                                }
V
varkor 已提交
1390
                                hir::GenericParamKind::Const { .. } => {
1391
                                    let const_param_def_id =
1392
                                        cx.tcx.hir().local_def_id(param.hir_id);
V
varkor 已提交
1393
                                    let mut j = 0;
M
Mark Rousskov 已提交
1394 1395
                                    let const_ =
                                        generic_args.args.iter().find_map(|arg| match arg {
V
varkor 已提交
1396 1397 1398 1399 1400 1401 1402 1403
                                            hir::GenericArg::Const(ct) => {
                                                if indices.consts == j {
                                                    return Some(ct);
                                                }
                                                j += 1;
                                                None
                                            }
                                            _ => None,
M
Mark Rousskov 已提交
1404
                                        });
1405
                                    if let Some(ct) = const_ {
1406 1407
                                        ct_substs
                                            .insert(const_param_def_id.to_def_id(), ct.clean(cx));
V
varkor 已提交
1408 1409 1410 1411
                                    }
                                    // FIXME(const_generics:defaults)
                                    indices.consts += 1;
                                }
1412
                            }
1413
                        }
1414
                    }
1415
                    return cx.enter_alias(ty_substs, lt_substs, ct_substs, || ty.clean(cx));
1416
                }
L
ljedrz 已提交
1417
                resolve_type(cx, path.clean(cx), self.hir_id)
N
Niko Matsakis 已提交
1418
            }
C
csmoe 已提交
1419
            TyKind::Path(hir::QPath::Resolved(Some(ref qself), ref p)) => {
1420 1421 1422 1423
                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(),
1424
                    res: Res::Def(
1425
                        DefKind::Trait,
1426
                        cx.tcx.associated_item(p.res.def_id()).container.id(),
1427
                    ),
1428
                    segments: trait_segments.clean(cx),
1429
                };
1430
                Type::QPath {
G
Guillaume Gomez 已提交
1431
                    name: p.segments.last().expect("segments were empty").ident.name.clean(cx),
1432
                    self_type: box qself.clean(cx),
M
Mark Rousskov 已提交
1433
                    trait_: box resolve_type(cx, trait_path, self.hir_id),
1434 1435
                }
            }
C
csmoe 已提交
1436
            TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
1437
                let mut res = Res::Err;
1438
                let ty = hir_ty_to_ty(cx.tcx, self);
1439
                if let ty::Projection(proj) = ty.kind() {
1440
                    res = Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id);
1441
                }
C
Camille GILLOT 已提交
1442
                let trait_path = hir::Path { span: self.span, res, segments: &[] };
1443
                Type::QPath {
1444
                    name: segment.ident.name.clean(cx),
1445
                    self_type: box qself.clean(cx),
M
Mark Rousskov 已提交
1446
                    trait_: box resolve_type(cx, trait_path.clean(cx), self.hir_id),
1447 1448
                }
            }
D
David Wood 已提交
1449 1450 1451
            TyKind::Path(hir::QPath::LangItem(..)) => {
                bug!("clean: requiring documentation of lang item")
            }
C
csmoe 已提交
1452
            TyKind::TraitObject(ref bounds, ref lifetime) => {
1453
                match bounds[0].clean(cx).trait_ {
V
varkor 已提交
1454
                    ResolvedPath { path, param_names: None, did, is_generic } => {
M
Mark Rousskov 已提交
1455 1456 1457 1458 1459 1460 1461 1462 1463
                        let mut bounds: Vec<self::GenericBound> = bounds[1..]
                            .iter()
                            .map(|bound| {
                                self::GenericBound::TraitBound(
                                    bound.clean(cx),
                                    hir::TraitBoundModifier::None,
                                )
                            })
                            .collect();
1464
                        if !lifetime.is_elided() {
V
varkor 已提交
1465
                            bounds.push(self::GenericBound::Outlives(lifetime.clean(cx)));
1466
                        }
M
Mark Rousskov 已提交
1467
                        ResolvedPath { path, param_names: Some(bounds), did, is_generic }
N
Niko Matsakis 已提交
1468
                    }
1469
                    _ => Infer, // shouldn't happen
N
Niko Matsakis 已提交
1470
                }
1471
            }
C
csmoe 已提交
1472 1473
            TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
            TyKind::Infer | TyKind::Err => Infer,
V
varkor 已提交
1474
            TyKind::Typeof(..) => panic!("unimplemented type {:?}", self.kind),
1475
        }
C
Corey Richardson 已提交
1476 1477 1478
    }
}

D
Douglas Campos 已提交
1479
impl<'tcx> Clean<Type> for Ty<'tcx> {
1480
    fn clean(&self, cx: &DocContext<'_>) -> Type {
1481
        debug!("cleaning type: {:?}", self);
1482
        match *self.kind() {
V
varkor 已提交
1483
            ty::Never => Never,
1484 1485 1486 1487 1488 1489
            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 已提交
1490 1491
            ty::Slice(ty) => Slice(box ty.clean(cx)),
            ty::Array(ty, n) => {
B
Bastian Kauschke 已提交
1492
                let mut n = cx.tcx.lift(n).expect("array lift failed");
1493
                n = n.eval(cx.tcx, ty::ParamEnv::reveal_all());
O
Oliver Schneider 已提交
1494
                let n = print_const(cx, n);
1495 1496
                Array(box ty.clean(cx), n)
            }
G
Guillaume Gomez 已提交
1497
            ty::RawPtr(mt) => RawPointer(mt.mutbl, box mt.ty.clean(cx)),
M
Mark Rousskov 已提交
1498 1499 1500 1501
            ty::Ref(r, ty, mutbl) => {
                BorrowedRef { lifetime: r.clean(cx), mutability: mutbl, type_: box ty.clean(cx) }
            }
            ty::FnDef(..) | ty::FnPtr(_) => {
B
Bastian Kauschke 已提交
1502
                let ty = cx.tcx.lift(*self).expect("FnPtr lift failed");
1503
                let sig = ty.fn_sig(cx.tcx);
1504
                let def_id = DefId::local(CRATE_DEF_INDEX);
1505 1506
                BareFunction(box BareFunctionDecl {
                    unsafety: sig.unsafety(),
1507
                    generic_params: Vec::new(),
1508
                    decl: (def_id, sig).clean(cx),
1509 1510 1511
                    abi: sig.abi(),
                })
            }
V
varkor 已提交
1512
            ty::Adt(def, substs) => {
1513
                let did = def.did;
1514
                let kind = match def.adt_kind() {
1515 1516 1517
                    AdtKind::Struct => TypeKind::Struct,
                    AdtKind::Union => TypeKind::Union,
                    AdtKind::Enum => TypeKind::Enum,
1518
                };
M
mitaa 已提交
1519
                inline::record_extern_fqn(cx, did, kind);
1520
                let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], substs);
M
Mark Rousskov 已提交
1521
                ResolvedPath { path, param_names: None, did, is_generic: false }
1522
            }
V
varkor 已提交
1523
            ty::Foreign(did) => {
P
Paul Lietar 已提交
1524
                inline::record_extern_fqn(cx, did, TypeKind::Foreign);
M
Mark Rousskov 已提交
1525 1526 1527 1528 1529 1530 1531 1532 1533
                let path = external_path(
                    cx,
                    cx.tcx.item_name(did),
                    None,
                    false,
                    vec![],
                    InternalSubsts::empty(),
                );
                ResolvedPath { path, param_names: None, did, is_generic: false }
P
Paul Lietar 已提交
1534
            }
V
varkor 已提交
1535
            ty::Dynamic(ref obj, ref reg) => {
A
Ariel Ben-Yehuda 已提交
1536 1537 1538 1539
                // 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());
M
Mark Rousskov 已提交
1540 1541 1542
                let did = dids
                    .next()
                    .unwrap_or_else(|| panic!("found trait object `{:?}` with no traits?", self));
A
Ariel Ben-Yehuda 已提交
1543 1544 1545
                let substs = match obj.principal() {
                    Some(principal) => principal.skip_binder().substs,
                    // marker traits have no substs.
M
Mark Rousskov 已提交
1546
                    _ => cx.tcx.intern_substs(&[]),
A
Ariel Ben-Yehuda 已提交
1547 1548
                };

1549 1550
                inline::record_extern_fqn(cx, did, TypeKind::Trait);

V
varkor 已提交
1551
                let mut param_names = vec![];
J
Josh Stone 已提交
1552 1553 1554
                if let Some(b) = reg.clean(cx) {
                    param_names.push(GenericBound::Outlives(b));
                }
A
Ariel Ben-Yehuda 已提交
1555
                for did in dids {
1556
                    let empty = cx.tcx.intern_substs(&[]);
M
Mark Rousskov 已提交
1557 1558
                    let path =
                        external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
1559
                    inline::record_extern_fqn(cx, did, TypeKind::Trait);
M
Mark Rousskov 已提交
1560 1561 1562 1563 1564 1565 1566 1567 1568
                    let bound = GenericBound::TraitBound(
                        PolyTrait {
                            trait_: ResolvedPath {
                                path,
                                param_names: None,
                                did,
                                is_generic: false,
                            },
                            generic_params: Vec::new(),
1569
                        },
M
Mark Rousskov 已提交
1570 1571
                        hir::TraitBoundModifier::None,
                    );
V
varkor 已提交
1572
                    param_names.push(bound);
1573
                }
1574

1575 1576 1577 1578
                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),
M
Mark Rousskov 已提交
1579
                        kind: TypeBindingKind::Equality { ty: pb.skip_binder().ty.clean(cx) },
1580 1581
                    });
                }
1582

M
Mark Rousskov 已提交
1583 1584 1585
                let path =
                    external_path(cx, cx.tcx.item_name(did), Some(did), false, bindings, substs);
                ResolvedPath { path, param_names: Some(param_names), did, is_generic: false }
1586
            }
V
varkor 已提交
1587 1588 1589
            ty::Tuple(ref t) => {
                Tuple(t.iter().map(|t| t.expect_ty()).collect::<Vec<_>>().clean(cx))
            }
1590

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

1593 1594 1595 1596 1597 1598 1599
            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())
                }
            }
1600

1601
            ty::Opaque(def_id, substs) => {
1602
                // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
M
Matthew Jasper 已提交
1603
                // by looking up the bounds associated with the def_id.
B
Bastian Kauschke 已提交
1604
                let substs = cx.tcx.lift(substs).expect("Opaque lift failed");
M
Matthew Jasper 已提交
1605 1606 1607 1608 1609 1610
                let bounds = cx
                    .tcx
                    .explicit_item_bounds(def_id)
                    .iter()
                    .map(|(bound, _)| bound.subst(cx.tcx, substs))
                    .collect::<Vec<_>>();
1611 1612
                let mut regions = vec![];
                let mut has_sized = false;
M
Mark Rousskov 已提交
1613 1614
                let mut bounds = bounds
                    .iter()
M
Matthew Jasper 已提交
1615
                    .filter_map(|bound| {
B
Bastian Kauschke 已提交
1616
                        // Note: The substs of opaque types can contain unbound variables,
1617
                        // meaning that we have to use `ignore_quantifiers_with_unbound_vars` here.
J
Jack Huey 已提交
1618 1619 1620 1621
                        let trait_ref = match bound
                            .bound_atom_with_opt_escaping(cx.tcx)
                            .skip_binder()
                        {
B
Bastian Kauschke 已提交
1622
                            ty::PredicateAtom::Trait(tr, _constness) => {
B
Bastian Kauschke 已提交
1623 1624
                                ty::Binder::bind(tr.trait_ref)
                            }
B
Bastian Kauschke 已提交
1625 1626
                            ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
                                if let Some(r) = reg.clean(cx) {
B
Bastian Kauschke 已提交
1627 1628 1629
                                    regions.push(GenericBound::Outlives(r));
                                }
                                return None;
J
Josh Stone 已提交
1630
                            }
B
Bastian Kauschke 已提交
1631
                            _ => return None,
M
Mark Rousskov 已提交
1632
                        };
1633

M
Mark Rousskov 已提交
1634 1635 1636 1637
                        if let Some(sized) = cx.tcx.lang_items().sized_trait() {
                            if trait_ref.def_id() == sized {
                                has_sized = true;
                                return None;
1638 1639 1640
                            }
                        }

1641
                        let bounds: Vec<_> = bounds
M
Mark Rousskov 已提交
1642
                            .iter()
M
Matthew Jasper 已提交
1643
                            .filter_map(|bound| {
B
Bastian Kauschke 已提交
1644
                                if let ty::PredicateAtom::Projection(proj) =
J
Jack Huey 已提交
1645
                                    bound.bound_atom_with_opt_escaping(cx.tcx).skip_binder()
B
rustdoc  
Bastian Kauschke 已提交
1646
                                {
M
Mark Rousskov 已提交
1647
                                    if proj.projection_ty.trait_ref(cx.tcx)
1648
                                        == trait_ref.skip_binder()
M
Mark Rousskov 已提交
1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669
                                    {
                                        Some(TypeBinding {
                                            name: cx
                                                .tcx
                                                .associated_item(proj.projection_ty.item_def_id)
                                                .ident
                                                .name
                                                .clean(cx),
                                            kind: TypeBindingKind::Equality {
                                                ty: proj.ty.clean(cx),
                                            },
                                        })
                                    } else {
                                        None
                                    }
                                } else {
                                    None
                                }
                            })
                            .collect();

1670
                        Some((trait_ref, &bounds[..]).clean(cx))
M
Mark Rousskov 已提交
1671 1672
                    })
                    .collect::<Vec<_>>();
1673 1674
                bounds.extend(regions);
                if !has_sized && !bounds.is_empty() {
V
varkor 已提交
1675
                    bounds.insert(0, GenericBound::maybe_sized(cx));
1676 1677
                }
                ImplTrait(bounds)
1678 1679
            }

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

S
scalexm 已提交
1682
            ty::Bound(..) => panic!("Bound"),
S
scalexm 已提交
1683
            ty::Placeholder(..) => panic!("Placeholder"),
V
varkor 已提交
1684 1685
            ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
            ty::Infer(..) => panic!("Infer"),
1686
            ty::Error(_) => panic!("Error"),
1687 1688 1689 1690
        }
    }
}

V
varkor 已提交
1691 1692
impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
    fn clean(&self, cx: &DocContext<'_>) -> Constant {
1693 1694 1695 1696 1697 1698
        Constant {
            type_: self.ty.clean(cx),
            expr: format!("{}", self),
            value: None,
            is_literal: false,
        }
V
varkor 已提交
1699 1700 1701
    }
}

1702
impl Clean<Item> for hir::StructField<'_> {
1703
    fn clean(&self, cx: &DocContext<'_>) -> Item {
1704 1705 1706 1707 1708 1709 1710 1711
        let what_rustc_thinks = Item::from_hir_id_and_parts(
            self.hir_id,
            Some(self.ident.name),
            StructFieldItem(self.ty.clean(cx)),
            cx,
        );
        // Don't show `pub` for fields on enum variants; they are always public
        Item { visibility: self.vis.clean(cx), ..what_rustc_thinks }
C
Corey Richardson 已提交
1712 1713 1714
    }
}

1715
impl Clean<Item> for ty::FieldDef {
1716
    fn clean(&self, cx: &DocContext<'_>) -> Item {
1717 1718 1719 1720 1721 1722 1723 1724
        let what_rustc_thinks = Item::from_def_id_and_parts(
            self.did,
            Some(self.ident.name),
            StructFieldItem(cx.tcx.type_of(self.did).clean(cx)),
            cx,
        );
        // Don't show `pub` for fields on enum variants; they are always public
        Item { visibility: self.vis.clean(cx), ..what_rustc_thinks }
1725 1726 1727
    }
}

C
Camille GILLOT 已提交
1728
impl Clean<Visibility> for hir::Visibility<'_> {
M
Mark Rousskov 已提交
1729 1730
    fn clean(&self, cx: &DocContext<'_>) -> Visibility {
        match self.node {
1731 1732
            hir::VisibilityKind::Public => Visibility::Public,
            hir::VisibilityKind::Inherited => Visibility::Inherited,
1733 1734 1735 1736
            hir::VisibilityKind::Crate(_) => {
                let krate = DefId::local(CRATE_DEF_INDEX);
                Visibility::Restricted(krate, cx.tcx.def_path(krate))
            }
1737
            hir::VisibilityKind::Restricted { ref path, .. } => {
1738
                let path = path.clean(cx);
1739
                let did = register_res(cx, path.res);
1740
                Visibility::Restricted(did, cx.tcx.def_path(did))
1741
            }
M
Mark Rousskov 已提交
1742
        }
1743 1744 1745
    }
}

M
Mark Rousskov 已提交
1746
impl Clean<Visibility> for ty::Visibility {
1747 1748 1749 1750 1751 1752 1753 1754
    fn clean(&self, cx: &DocContext<'_>) -> Visibility {
        match *self {
            ty::Visibility::Public => Visibility::Public,
            ty::Visibility::Invisible => Visibility::Inherited,
            ty::Visibility::Restricted(module) => {
                Visibility::Restricted(module, cx.tcx.def_path(module))
            }
        }
C
Corey Richardson 已提交
1755 1756 1757
    }
}

1758
impl Clean<VariantStruct> for rustc_hir::VariantData<'_> {
1759
    fn clean(&self, cx: &DocContext<'_>) -> VariantStruct {
C
Corey Richardson 已提交
1760 1761
        VariantStruct {
            struct_type: doctree::struct_type_from_def(self),
1762
            fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
S
Steven Fackler 已提交
1763
            fields_stripped: false,
C
Corey Richardson 已提交
1764 1765 1766 1767
        }
    }
}

1768
impl Clean<Item> for doctree::Variant<'_> {
1769
    fn clean(&self, cx: &DocContext<'_>) -> Item {
1770 1771 1772 1773 1774 1775 1776 1777
        let what_rustc_thinks = Item::from_hir_id_and_parts(
            self.id,
            Some(self.name),
            VariantItem(Variant { kind: self.def.clean(cx) }),
            cx,
        );
        // don't show `pub` for variants, which are always public
        Item { visibility: Inherited, ..what_rustc_thinks }
C
Corey Richardson 已提交
1778 1779 1780
    }
}

1781
impl Clean<Item> for ty::VariantDef {
1782
    fn clean(&self, cx: &DocContext<'_>) -> Item {
1783 1784
        let kind = match self.ctor_kind {
            CtorKind::Const => VariantKind::CLike,
M
Mark Rousskov 已提交
1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797
            CtorKind::Fn => VariantKind::Tuple(
                self.fields.iter().map(|f| cx.tcx.type_of(f.did).clean(cx)).collect(),
            ),
            CtorKind::Fictive => VariantKind::Struct(VariantStruct {
                struct_type: doctree::Plain,
                fields_stripped: false,
                fields: self
                    .fields
                    .iter()
                    .map(|field| Item {
                        source: cx.tcx.def_span(field.did).clean(cx),
                        name: Some(field.ident.name.clean(cx)),
                        attrs: cx.tcx.get_attrs(field.did).clean(cx),
1798
                        visibility: Visibility::Inherited,
M
Mark Rousskov 已提交
1799 1800 1801
                        def_id: field.did,
                        stability: get_stability(cx, field.did),
                        deprecation: get_deprecation(cx, field.did),
1802
                        kind: StructFieldItem(cx.tcx.type_of(field.did).clean(cx)),
M
Mark Rousskov 已提交
1803 1804 1805
                    })
                    .collect(),
            }),
1806
        };
1807 1808 1809 1810 1811 1812 1813 1814
        let what_rustc_thinks = Item::from_def_id_and_parts(
            self.def_id,
            Some(self.ident.name),
            VariantItem(Variant { kind }),
            cx,
        );
        // don't show `pub` for fields, which are always public
        Item { visibility: Inherited, ..what_rustc_thinks }
1815 1816 1817
    }
}

C
Camille GILLOT 已提交
1818
impl Clean<VariantKind> for hir::VariantData<'_> {
1819
    fn clean(&self, cx: &DocContext<'_>) -> VariantKind {
1820 1821
        match self {
            hir::VariantData::Struct(..) => VariantKind::Struct(self.clean(cx)),
M
Mark Rousskov 已提交
1822 1823 1824
            hir::VariantData::Tuple(..) => {
                VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect())
            }
1825
            hir::VariantData::Unit(..) => VariantKind::CLike,
1826
        }
1827 1828 1829
    }
}

1830
impl Clean<Span> for rustc_span::Span {
1831
    fn clean(&self, cx: &DocContext<'_>) -> Span {
V
Vadim Petrochenkov 已提交
1832
        if self.is_dummy() {
1833 1834 1835
            return Span::empty();
        }

1836 1837 1838 1839 1840
        // Get the macro invocation instead of the definition,
        // in case the span is result of a macro expansion.
        // (See rust-lang/rust#39726)
        let span = self.source_callsite();

1841
        let sm = cx.sess().source_map();
1842 1843 1844
        let filename = sm.span_to_filename(span);
        let lo = sm.lookup_char_pos(span.lo());
        let hi = sm.lookup_char_pos(span.hi());
1845
        Span {
1846
            filename,
1847
            cnum: lo.file.cnum,
1848
            loline: lo.line,
1849
            locol: lo.col.to_usize(),
1850
            hiline: hi.line,
1851
            hicol: hi.col.to_usize(),
1852
            original: span,
1853
        }
C
Corey Richardson 已提交
1854 1855 1856
    }
}

C
Camille GILLOT 已提交
1857
impl Clean<Path> for hir::Path<'_> {
1858
    fn clean(&self, cx: &DocContext<'_>) -> Path {
C
Corey Richardson 已提交
1859
        Path {
1860
            global: self.is_global(),
1861
            res: self.res,
1862
            segments: if self.is_global() { &self.segments[1..] } else { &self.segments }.clean(cx),
1863 1864 1865 1866
        }
    }
}

C
Camille GILLOT 已提交
1867
impl Clean<GenericArgs> for hir::GenericArgs<'_> {
1868
    fn clean(&self, cx: &DocContext<'_>) -> GenericArgs {
1869
        if self.parenthesized {
1870
            let output = self.bindings[0].ty().clean(cx);
1871
            GenericArgs::Parenthesized {
1872
                inputs: self.inputs().clean(cx),
M
Mark Rousskov 已提交
1873
                output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None },
1874
            }
1875
        } else {
1876
            GenericArgs::AngleBracketed {
M
Mark Rousskov 已提交
1877 1878 1879
                args: self
                    .args
                    .iter()
1880 1881 1882
                    .map(|arg| match arg {
                        hir::GenericArg::Lifetime(lt) if !lt.is_elided() => {
                            GenericArg::Lifetime(lt.clean(cx))
M
Mark Rousskov 已提交
1883
                        }
1884 1885 1886
                        hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
                        hir::GenericArg::Type(ty) => GenericArg::Type(ty.clean(cx)),
                        hir::GenericArg::Const(ct) => GenericArg::Const(ct.clean(cx)),
M
Mark Rousskov 已提交
1887 1888
                    })
                    .collect(),
1889
                bindings: self.bindings.clean(cx),
1890
            }
1891 1892 1893
        }
    }
}
1894

C
Camille GILLOT 已提交
1895
impl Clean<PathSegment> for hir::PathSegment<'_> {
1896
    fn clean(&self, cx: &DocContext<'_>) -> PathSegment {
M
Mark Rousskov 已提交
1897
        PathSegment { name: self.ident.name.clean(cx), args: self.generic_args().clean(cx) }
C
Corey Richardson 已提交
1898 1899 1900
    }
}

1901 1902
impl Clean<String> for Ident {
    #[inline]
1903
    fn clean(&self, cx: &DocContext<'_>) -> String {
1904 1905 1906 1907
        self.name.clean(cx)
    }
}

1908
impl Clean<String> for Symbol {
1909
    #[inline]
1910
    fn clean(&self, _: &DocContext<'_>) -> String {
1911
        self.to_string()
1912 1913 1914
    }
}

C
Camille GILLOT 已提交
1915
impl Clean<BareFunctionDecl> for hir::BareFnTy<'_> {
1916
    fn clean(&self, cx: &DocContext<'_>) -> BareFunctionDecl {
1917
        let (generic_params, decl) = enter_impl_trait(cx, || {
1918
            (self.generic_params.clean(cx), (&*self.decl, &self.param_names[..]).clean(cx))
1919
        });
M
Mark Rousskov 已提交
1920
        BareFunctionDecl { unsafety: self.unsafety, abi: self.abi, decl, generic_params }
C
Corey Richardson 已提交
1921 1922 1923
    }
}

J
Joshua Nelson 已提交
1924 1925
impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Ident>) {
    fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
J
Joshua Nelson 已提交
1926 1927
        use hir::ItemKind;

J
Joshua Nelson 已提交
1928 1929 1930 1931 1932 1933 1934
        let (item, renamed) = self;
        let def_id = cx.tcx.hir().local_def_id(item.hir_id).to_def_id();
        let name = match renamed {
            Some(ident) => ident.name,
            None => cx.tcx.hir().name(item.hir_id),
        };
        let kind = match item.kind {
J
Joshua Nelson 已提交
1935 1936 1937 1938
            ItemKind::Static(ty, mutability, body_id) => StaticItem(Static {
                type_: ty.clean(cx),
                mutability,
                expr: print_const_expr(cx, body_id),
C
Corey Richardson 已提交
1939
            }),
J
Joshua Nelson 已提交
1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978
            ItemKind::Const(ty, body_id) => ConstantItem(Constant {
                type_: ty.clean(cx),
                expr: print_const_expr(cx, body_id),
                value: print_evaluated_const(cx, def_id),
                is_literal: is_literal_expr(cx, body_id.hir_id),
            }),
            ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
                bounds: ty.bounds.clean(cx),
                generics: ty.generics.clean(cx),
            }),
            ItemKind::TyAlias(ty, ref generics) => {
                let rustdoc_ty = ty.clean(cx);
                let item_type = rustdoc_ty.def_id().and_then(|did| inline::build_ty(cx, did));
                TypedefItem(
                    Typedef { type_: rustdoc_ty, generics: generics.clean(cx), item_type },
                    false,
                )
            }
            ItemKind::Enum(ref def, ref generics) => EnumItem(Enum {
                variants: def.variants.iter().map(|v| v.clean(cx)).collect(),
                generics: generics.clean(cx),
                variants_stripped: false,
            }),
            ItemKind::TraitAlias(ref generics, bounds) => TraitAliasItem(TraitAlias {
                generics: generics.clean(cx),
                bounds: bounds.clean(cx),
            }),
            ItemKind::Union(ref variant_data, ref generics) => UnionItem(Union {
                struct_type: doctree::struct_type_from_def(&variant_data),
                generics: generics.clean(cx),
                fields: variant_data.fields().clean(cx),
                fields_stripped: false,
            }),
            ItemKind::Struct(ref variant_data, ref generics) => StructItem(Struct {
                struct_type: doctree::struct_type_from_def(&variant_data),
                generics: generics.clean(cx),
                fields: variant_data.fields().clean(cx),
                fields_stripped: false,
            }),
J
Joshua Nelson 已提交
1979
            ItemKind::Impl { .. } => return clean_impl(item, cx),
J
Joshua Nelson 已提交
1980 1981 1982
            _ => unreachable!("not yet converted"),
        };

J
Joshua Nelson 已提交
1983
        vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)]
C
Corey Richardson 已提交
1984 1985 1986
    }
}

J
Joshua Nelson 已提交
1987
impl Clean<Item> for hir::Variant<'_> {
1988
    fn clean(&self, cx: &DocContext<'_>) -> Item {
J
Joshua Nelson 已提交
1989 1990 1991 1992 1993
        let kind = VariantItem(Variant { kind: self.data.clean(cx) });
        let what_rustc_thinks =
            Item::from_hir_id_and_parts(self.id, Some(self.ident.name), kind, cx);
        // don't show `pub` for variants, which are always public
        Item { visibility: Inherited, ..what_rustc_thinks }
1994 1995 1996
    }
}

1997
impl Clean<ImplPolarity> for ty::ImplPolarity {
1998
    fn clean(&self, _: &DocContext<'_>) -> ImplPolarity {
1999
        match self {
2000 2001 2002 2003
            &ty::ImplPolarity::Positive |
            // FIXME: do we want to do something else here?
            &ty::ImplPolarity::Reservation => ImplPolarity::Positive,
            &ty::ImplPolarity::Negative => ImplPolarity::Negative,
2004 2005 2006 2007
        }
    }
}

J
Joshua Nelson 已提交
2008 2009 2010 2011 2012
fn clean_impl(impl_: &hir::Item<'_>, cx: &DocContext<'_>) -> Vec<Item> {
    let mut ret = Vec::new();
    let (trait_, items, for_, unsafety, generics) = match &impl_.kind {
        hir::ItemKind::Impl { of_trait, items, self_ty, unsafety, generics, .. } => {
            (of_trait, items, self_ty, *unsafety, generics)
2013
        }
J
Joshua Nelson 已提交
2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046
        _ => unreachable!(),
    };
    let trait_ = trait_.clean(cx);
    let items = items.iter().map(|ii| cx.tcx.hir().impl_item(ii.id).clean(cx)).collect::<Vec<_>>();
    let def_id = cx.tcx.hir().local_def_id(impl_.hir_id);

    // If this impl block is an implementation of the Deref trait, then we
    // need to try inlining the target's inherent impl blocks as well.
    if trait_.def_id() == cx.tcx.lang_items().deref_trait() {
        build_deref_target_impls(cx, &items, &mut ret);
    }

    let provided: FxHashSet<String> = trait_
        .def_id()
        .map(|did| cx.tcx.provided_trait_methods(did).map(|meth| meth.ident.to_string()).collect())
        .unwrap_or_default();

    let for_ = for_.clean(cx);
    let type_alias = for_.def_id().and_then(|did| match cx.tcx.def_kind(did) {
        DefKind::TyAlias => Some(cx.tcx.type_of(did).clean(cx)),
        _ => None,
    });
    let make_item = |trait_: Option<Type>, for_: Type, items: Vec<Item>| {
        let kind = ImplItem(Impl {
            unsafety,
            generics: generics.clean(cx),
            provided_trait_methods: provided.clone(),
            trait_,
            for_,
            items,
            polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)),
            synthetic: false,
            blanket_impl: None,
2047
        });
J
Joshua Nelson 已提交
2048 2049 2050 2051
        Item::from_hir_id_and_parts(impl_.hir_id, None, kind, cx)
    };
    if let Some(type_alias) = type_alias {
        ret.push(make_item(trait_.clone(), type_alias, items.clone()));
2052
    }
J
Joshua Nelson 已提交
2053 2054
    ret.push(make_item(trait_, for_, items));
    ret
2055 2056
}

2057
impl Clean<Vec<Item>> for doctree::ExternCrate<'_> {
2058
    fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
M
Mark Rousskov 已提交
2059 2060
        let please_inline = self.vis.node.is_pub()
            && self.attrs.iter().any(|a| {
2061
                a.has_name(sym::doc)
M
Mark Rousskov 已提交
2062 2063 2064 2065 2066
                    && match a.meta_item_list() {
                        Some(l) => attr::list_contains_name(&l, sym::inline),
                        None => false,
                    }
            });
D
DebugSteven 已提交
2067 2068 2069 2070

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

M
Mark Rousskov 已提交
2071
            let res = Res::Def(DefKind::Mod, DefId { krate: self.cnum, index: CRATE_DEF_INDEX });
D
DebugSteven 已提交
2072

2073 2074 2075 2076 2077 2078 2079 2080
            if let Some(items) = inline::try_inline(
                cx,
                cx.tcx.parent_module(self.hir_id).to_def_id(),
                res,
                self.name,
                Some(self.attrs),
                &mut visited,
            ) {
D
DebugSteven 已提交
2081 2082 2083 2084 2085
                return items;
            }
        }

        vec![Item {
2086 2087
            name: None,
            attrs: self.attrs.clean(cx),
C
Camelid 已提交
2088
            source: self.span.clean(cx),
M
mitaa 已提交
2089
            def_id: DefId { krate: self.cnum, index: CRATE_DEF_INDEX },
2090 2091
            visibility: self.vis.clean(cx),
            stability: None,
2092
            deprecation: None,
2093
            kind: ExternCrateItem(self.name.clean(cx), self.path.clone()),
D
DebugSteven 已提交
2094
        }]
2095
    }
C
Corey Richardson 已提交
2096 2097
}

2098
impl Clean<Vec<Item>> for doctree::Import<'_> {
2099
    fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
2100 2101 2102 2103 2104 2105 2106
        // We need this comparison because some imports (for std types for example)
        // are "inserted" as well but directly by the compiler and they should not be
        // taken into account.
        if self.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::StdImports) {
            return Vec::new();
        }

J
Joseph Crail 已提交
2107
        // We consider inlining the documentation of `pub use` statements, but we
2108 2109
        // forcefully don't inline if this is not public or if the
        // #[doc(no_inline)] attribute is present.
2110
        // Don't inline doc(hidden) imports so they can be stripped at a later stage.
M
Mark Rousskov 已提交
2111 2112
        let mut denied = !self.vis.node.is_pub()
            || self.attrs.iter().any(|a| {
2113
                a.has_name(sym::doc)
M
Mark Rousskov 已提交
2114 2115 2116 2117 2118 2119 2120 2121
                    && match a.meta_item_list() {
                        Some(l) => {
                            attr::list_contains_name(&l, sym::no_inline)
                                || attr::list_contains_name(&l, sym::hidden)
                        }
                        None => false,
                    }
            });
2122 2123
        // Also check whether imports were asked to be inlined, in case we're trying to re-export a
        // crate in Rust 2018+
2124
        let please_inline = self.attrs.lists(sym::doc).has_word(sym::inline);
2125 2126
        let path = self.path.clean(cx);
        let inner = if self.glob {
2127
            if !denied {
2128
                let mut visited = FxHashSet::default();
2129
                if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) {
2130 2131 2132
                    return items;
                }
            }
2133
            Import::new_glob(resolve_use_source(cx, path), true)
2134 2135
        } else {
            let name = self.name;
2136
            if !please_inline {
M
Matthias Krüger 已提交
2137 2138 2139 2140 2141
                if let Res::Def(DefKind::Mod, did) = path.res {
                    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;
2142 2143 2144
                    }
                }
            }
2145
            if !denied {
2146
                let mut visited = FxHashSet::default();
2147 2148

                if let Some(mut items) = inline::try_inline(
2149 2150 2151 2152 2153 2154 2155
                    cx,
                    cx.tcx.parent_module(self.id).to_def_id(),
                    path.res,
                    name,
                    Some(self.attrs),
                    &mut visited,
                ) {
2156 2157 2158 2159 2160 2161 2162 2163
                    items.push(Item {
                        name: None,
                        attrs: self.attrs.clean(cx),
                        source: self.span.clean(cx),
                        def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(),
                        visibility: self.vis.clean(cx),
                        stability: None,
                        deprecation: None,
2164
                        kind: ImportItem(Import::new_simple(
2165 2166
                            self.name.clean(cx),
                            resolve_use_source(cx, path),
2167
                            false,
2168 2169
                        )),
                    });
2170
                    return items;
2171
                }
2172
            }
2173
            Import::new_simple(name.clean(cx), resolve_use_source(cx, path), true)
2174
        };
G
Guillaume Gomez 已提交
2175

2176
        vec![Item {
2177 2178
            name: None,
            attrs: self.attrs.clean(cx),
C
Camelid 已提交
2179
            source: self.span.clean(cx),
2180
            def_id: DefId::local(CRATE_DEF_INDEX),
2181 2182
            visibility: self.vis.clean(cx),
            stability: None,
2183
            deprecation: None,
2184
            kind: ImportItem(inner),
2185
        }]
C
Corey Richardson 已提交
2186 2187 2188
    }
}

2189
impl Clean<Item> for doctree::ForeignItem<'_> {
2190
    fn clean(&self, cx: &DocContext<'_>) -> Item {
2191
        let kind = match self.kind {
C
csmoe 已提交
2192
            hir::ForeignItemKind::Fn(ref decl, ref names, ref generics) => {
2193
                let abi = cx.tcx.hir().get_foreign_abi(self.id);
M
Mark Rousskov 已提交
2194 2195
                let (generics, decl) =
                    enter_impl_trait(cx, || (generics.clean(cx), (&**decl, &names[..]).clean(cx)));
2196
                let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
2197
                ForeignFunctionItem(Function {
2198
                    decl,
2199
                    generics,
2200 2201
                    header: hir::FnHeader {
                        unsafety: hir::Unsafety::Unsafe,
2202
                        abi,
2203 2204 2205
                        constness: hir::Constness::NotConst,
                        asyncness: hir::IsAsync::NotAsync,
                    },
2206
                    all_types,
2207
                    ret_types,
2208 2209
                })
            }
M
Mark Rousskov 已提交
2210 2211 2212 2213 2214 2215
            hir::ForeignItemKind::Static(ref ty, mutbl) => ForeignStaticItem(Static {
                type_: ty.clean(cx),
                mutability: *mutbl,
                expr: String::new(),
            }),
            hir::ForeignItemKind::Type => ForeignTypeItem,
2216
        };
G
Guillaume Gomez 已提交
2217

2218
        Item::from_hir_id_and_parts(self.id, Some(self.name), kind, cx)
2219 2220 2221
    }
}

2222
impl Clean<Item> for doctree::Macro {
2223
    fn clean(&self, cx: &DocContext<'_>) -> Item {
2224 2225 2226 2227
        Item::from_def_id_and_parts(
            self.def_id,
            Some(self.name),
            MacroItem(Macro {
M
Mark Rousskov 已提交
2228 2229
                source: format!(
                    "macro_rules! {} {{\n{}}}",
2230
                    self.name,
M
Mark Rousskov 已提交
2231 2232 2233 2234 2235
                    self.matchers
                        .iter()
                        .map(|span| { format!("    {} => {{ ... }};\n", span.to_src(cx)) })
                        .collect::<String>()
                ),
2236
                imported_from: self.imported_from.clean(cx),
2237
            }),
2238 2239
            cx,
        )
2240 2241
    }
}
2242

2243
impl Clean<Item> for doctree::ProcMacro {
2244
    fn clean(&self, cx: &DocContext<'_>) -> Item {
2245 2246 2247 2248 2249 2250
        Item::from_hir_id_and_parts(
            self.id,
            Some(self.name),
            ProcMacroItem(ProcMacro { kind: self.kind, helpers: self.helpers.clean(cx) }),
            cx,
        )
2251 2252 2253
    }
}

2254
impl Clean<Deprecation> for attr::Deprecation {
2255
    fn clean(&self, _: &DocContext<'_>) -> Deprecation {
2256
        Deprecation {
2257 2258
            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()),
2259
            is_since_rustc_version: self.is_since_rustc_version,
2260 2261 2262 2263
        }
    }
}

C
Camille GILLOT 已提交
2264
impl Clean<TypeBinding> for hir::TypeBinding<'_> {
2265
    fn clean(&self, cx: &DocContext<'_>) -> TypeBinding {
M
Mark Rousskov 已提交
2266
        TypeBinding { name: self.ident.name.clean(cx), kind: self.kind.clean(cx) }
2267 2268 2269
    }
}

C
Camille GILLOT 已提交
2270
impl Clean<TypeBindingKind> for hir::TypeBindingKind<'_> {
2271 2272
    fn clean(&self, cx: &DocContext<'_>) -> TypeBindingKind {
        match *self {
M
Mark Rousskov 已提交
2273 2274 2275
            hir::TypeBindingKind::Equality { ref ty } => {
                TypeBindingKind::Equality { ty: ty.clean(cx) }
            }
2276 2277 2278
            hir::TypeBindingKind::Constraint { ref bounds } => {
                TypeBindingKind::Constraint { bounds: bounds.iter().map(|b| b.clean(cx)).collect() }
            }
2279 2280 2281
        }
    }
}
2282 2283

enum SimpleBound {
V
varkor 已提交
2284 2285
    TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier),
    Outlives(Lifetime),
2286 2287
}

V
varkor 已提交
2288 2289
impl From<GenericBound> for SimpleBound {
    fn from(bound: GenericBound) -> Self {
2290
        match bound.clone() {
V
varkor 已提交
2291 2292
            GenericBound::Outlives(l) => SimpleBound::Outlives(l),
            GenericBound::TraitBound(t, mod_) => match t.trait_ {
M
Mark Rousskov 已提交
2293 2294
                Type::ResolvedPath { path, param_names, .. } => SimpleBound::TraitBound(
                    path.segments,
M
Matthias Krüger 已提交
2295 2296 2297
                    param_names.map_or_else(Vec::new, |v| {
                        v.iter().map(|p| SimpleBound::from(p.clone())).collect()
                    }),
M
Mark Rousskov 已提交
2298 2299 2300
                    t.generic_params,
                    mod_,
                ),
A
Aaron Hill 已提交
2301
                _ => panic!("Unexpected bound {:?}", bound),
M
Mark Rousskov 已提交
2302
            },
2303 2304 2305
        }
    }
}