]> git.proxmox.com Git - rustc.git/blame - src/librustdoc/clean/mod.rs
New upstream version 1.44.1+dfsg1
[rustc.git] / src / librustdoc / clean / mod.rs
CommitLineData
1a4d82fc
JJ
1//! This module contains the "cleaned" pieces of the AST, and the functions
2//! that clean them.
3
0731742a
XL
4mod auto_trait;
5mod blanket_impl;
dfeec247
XL
6pub mod cfg;
7pub mod inline;
60c5eb7d
XL
8mod simplify;
9pub mod types;
dfeec247 10pub mod utils;
1a4d82fc 11
74b04a01
XL
12use rustc_ast::ast::{self, Ident};
13use rustc_attr as attr;
dfeec247
XL
14use rustc_data_structures::fx::{FxHashMap, FxHashSet};
15use rustc_hir as hir;
16use rustc_hir::def::{CtorKind, DefKind, Res};
17use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
18use rustc_index::vec::{Idx, IndexVec};
74b04a01 19use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
ba9703b0
XL
20use rustc_middle::middle::resolve_lifetime as rl;
21use rustc_middle::middle::stability;
22use rustc_middle::ty::fold::TypeFolder;
23use rustc_middle::ty::subst::InternalSubsts;
24use rustc_middle::ty::{self, AdtKind, Lift, Ty, TyCtxt};
dfeec247
XL
25use rustc_mir::const_eval::is_min_const_fn;
26use rustc_span::hygiene::MacroKind;
27use rustc_span::symbol::{kw, sym};
28use rustc_span::{self, Pos};
29use rustc_typeck::hir_ty_to_ty;
94b46f34 30
0531ce1d 31use std::collections::hash_map::Entry;
ff7c6d11 32use std::default::Default;
dfeec247 33use std::hash::Hash;
1a4d82fc 34use std::rc::Rc;
dfeec247 35use std::{mem, vec};
1a4d82fc 36
e1599b0c 37use crate::core::{self, DocContext, ImplTraitParam};
9fa01778 38use crate::doctree;
9fa01778 39
60c5eb7d 40use utils::*;
1a4d82fc 41
60c5eb7d 42pub use utils::{get_auto_trait_and_blanket_impls, krate, register_res};
0531ce1d 43
74b04a01 44pub use self::types::FnRetTy::*;
60c5eb7d
XL
45pub use self::types::ItemEnum::*;
46pub use self::types::SelfTy::*;
dfeec247
XL
47pub use self::types::Type::*;
48pub use self::types::Visibility::{Inherited, Public};
49pub use self::types::*;
0531ce1d 50
74b04a01 51const FN_OUTPUT_NAME: &str = "Output";
3b2f2976 52
1a4d82fc 53pub trait Clean<T> {
532ac7d7 54 fn clean(&self, cx: &DocContext<'_>) -> T;
1a4d82fc
JJ
55}
56
c34b1796 57impl<T: Clean<U>, U> Clean<Vec<U>> for [T] {
532ac7d7 58 fn clean(&self, cx: &DocContext<'_>) -> Vec<U> {
1a4d82fc
JJ
59 self.iter().map(|x| x.clean(cx)).collect()
60 }
61}
62
a1dfa0c6 63impl<T: Clean<U>, U, V: Idx> Clean<IndexVec<V, U>> for IndexVec<V, T> {
532ac7d7 64 fn clean(&self, cx: &DocContext<'_>) -> IndexVec<V, U> {
a1dfa0c6
XL
65 self.iter().map(|x| x.clean(cx)).collect()
66 }
67}
68
dfeec247 69impl<T: Clean<U>, U> Clean<U> for &T {
532ac7d7 70 fn clean(&self, cx: &DocContext<'_>) -> U {
1a4d82fc
JJ
71 (**self).clean(cx)
72 }
73}
74
75impl<T: Clean<U>, U> Clean<U> for Rc<T> {
532ac7d7 76 fn clean(&self, cx: &DocContext<'_>) -> U {
1a4d82fc
JJ
77 (**self).clean(cx)
78 }
79}
80
81impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
532ac7d7 82 fn clean(&self, cx: &DocContext<'_>) -> Option<U> {
54a0048b 83 self.as_ref().map(|v| v.clean(cx))
1a4d82fc
JJ
84 }
85}
86
92a42be0 87impl Clean<ExternalCrate> for CrateNum {
532ac7d7 88 fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate {
476ff2be
SL
89 let root = DefId { krate: *self, index: CRATE_DEF_INDEX };
90 let krate_span = cx.tcx.def_span(root);
b7449926 91 let krate_src = cx.sess().source_map().span_to_filename(krate_span);
476ff2be
SL
92
93 // Collect all inner modules which are tagged as implementations of
94 // primitives.
95 //
96 // Note that this loop only searches the top-level items of the crate,
97 // and this is intentional. If we were to search the entire crate for an
98 // item tagged with `#[doc(primitive)]` then we would also have to
99 // search the entirety of external modules for items tagged
100 // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
101 // all that metadata unconditionally).
102 //
103 // In order to keep the metadata load under control, the
104 // `#[doc(primitive)]` feature is explicitly designed to only allow the
105 // primitive tags to show up as the top level items in a crate.
106 //
107 // Also note that this does not attempt to deal with modules tagged
108 // duplicately for the same primitive. This is handled later on when
109 // rendering by delegating everything to a hash map.
48663c56
XL
110 let as_primitive = |res: Res| {
111 if let Res::Def(DefKind::Mod, def_id) = res {
476ff2be
SL
112 let attrs = cx.tcx.get_attrs(def_id).clean(cx);
113 let mut prim = None;
48663c56 114 for attr in attrs.lists(sym::doc) {
476ff2be 115 if let Some(v) = attr.value_str() {
48663c56 116 if attr.check_name(sym::primitive) {
476ff2be
SL
117 prim = PrimitiveType::from_str(&v.as_str());
118 if prim.is_some() {
119 break;
120 }
abe05a73 121 // FIXME: should warn on unknown primitives?
476ff2be
SL
122 }
123 }
124 }
125 return prim.map(|p| (def_id, p, attrs));
92a42be0 126 }
476ff2be
SL
127 None
128 };
129 let primitives = if root.is_local() {
dfeec247
XL
130 cx.tcx
131 .hir()
132 .krate()
ba9703b0 133 .item
dfeec247
XL
134 .module
135 .item_ids
136 .iter()
137 .filter_map(|&id| {
138 let item = cx.tcx.hir().expect_item(id.id);
139 match item.kind {
140 hir::ItemKind::Mod(_) => {
141 as_primitive(Res::Def(DefKind::Mod, cx.tcx.hir().local_def_id(id.id)))
142 }
143 hir::ItemKind::Use(ref path, hir::UseKind::Single)
144 if item.vis.node.is_pub() =>
145 {
146 as_primitive(path.res).map(|(_, prim, attrs)| {
147 // Pretend the primitive is local.
148 (cx.tcx.hir().local_def_id(id.id), prim, attrs)
149 })
150 }
151 _ => None,
476ff2be 152 }
dfeec247
XL
153 })
154 .collect()
476ff2be 155 } else {
dfeec247
XL
156 cx.tcx
157 .item_children(root)
158 .iter()
159 .map(|item| item.res)
160 .filter_map(as_primitive)
161 .collect()
476ff2be
SL
162 };
163
48663c56
XL
164 let as_keyword = |res: Res| {
165 if let Res::Def(DefKind::Mod, def_id) = res {
94b46f34
XL
166 let attrs = cx.tcx.get_attrs(def_id).clean(cx);
167 let mut keyword = None;
48663c56 168 for attr in attrs.lists(sym::doc) {
94b46f34 169 if let Some(v) = attr.value_str() {
48663c56 170 if attr.check_name(sym::keyword) {
dc9dc135
XL
171 if v.is_doc_keyword() {
172 keyword = Some(v.to_string());
173 break;
94b46f34
XL
174 }
175 // FIXME: should warn on unknown keywords?
176 }
177 }
178 }
179 return keyword.map(|p| (def_id, p, attrs));
180 }
181 None
182 };
183 let keywords = if root.is_local() {
dfeec247
XL
184 cx.tcx
185 .hir()
186 .krate()
ba9703b0 187 .item
dfeec247
XL
188 .module
189 .item_ids
190 .iter()
191 .filter_map(|&id| {
192 let item = cx.tcx.hir().expect_item(id.id);
193 match item.kind {
194 hir::ItemKind::Mod(_) => {
195 as_keyword(Res::Def(DefKind::Mod, cx.tcx.hir().local_def_id(id.id)))
196 }
197 hir::ItemKind::Use(ref path, hir::UseKind::Single)
198 if item.vis.node.is_pub() =>
199 {
200 as_keyword(path.res).map(|(_, prim, attrs)| {
201 (cx.tcx.hir().local_def_id(id.id), prim, attrs)
202 })
203 }
204 _ => None,
94b46f34 205 }
dfeec247
XL
206 })
207 .collect()
94b46f34 208 } else {
dfeec247 209 cx.tcx.item_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect()
94b46f34
XL
210 };
211
1a4d82fc 212 ExternalCrate {
476ff2be 213 name: cx.tcx.crate_name(*self).to_string(),
ff7c6d11 214 src: krate_src,
476ff2be 215 attrs: cx.tcx.get_attrs(root).clean(cx),
3b2f2976 216 primitives,
94b46f34 217 keywords,
1a4d82fc
JJ
218 }
219 }
220}
221
dc9dc135 222impl Clean<Item> for doctree::Module<'_> {
532ac7d7 223 fn clean(&self, cx: &DocContext<'_>) -> Item {
1a4d82fc 224 let name = if self.name.is_some() {
b7449926 225 self.name.expect("No name provided").clean(cx)
1a4d82fc 226 } else {
b7449926 227 String::new()
1a4d82fc 228 };
85aaf69f 229
2c00a5a8
XL
230 // maintain a stack of mod ids, for doc comment path resolution
231 // but we also need to resolve the module's own docs based on whether its docs were written
232 // inside or outside the module, so check for that
b7449926 233 let attrs = self.attrs.clean(cx);
2c00a5a8 234
85aaf69f 235 let mut items: Vec<Item> = vec![];
0731742a 236 items.extend(self.extern_crates.iter().flat_map(|x| x.clean(cx)));
62682a34 237 items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
0bf4aa26
XL
238 items.extend(self.structs.iter().map(|x| x.clean(cx)));
239 items.extend(self.unions.iter().map(|x| x.clean(cx)));
240 items.extend(self.enums.iter().map(|x| x.clean(cx)));
85aaf69f 241 items.extend(self.fns.iter().map(|x| x.clean(cx)));
dc9dc135 242 items.extend(self.foreigns.iter().map(|x| x.clean(cx)));
85aaf69f
SL
243 items.extend(self.mods.iter().map(|x| x.clean(cx)));
244 items.extend(self.typedefs.iter().map(|x| x.clean(cx)));
416331ca 245 items.extend(self.opaque_tys.iter().map(|x| x.clean(cx)));
85aaf69f
SL
246 items.extend(self.statics.iter().map(|x| x.clean(cx)));
247 items.extend(self.constants.iter().map(|x| x.clean(cx)));
248 items.extend(self.traits.iter().map(|x| x.clean(cx)));
62682a34 249 items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
85aaf69f 250 items.extend(self.macros.iter().map(|x| x.clean(cx)));
0bf4aa26 251 items.extend(self.proc_macros.iter().map(|x| x.clean(cx)));
9fa01778 252 items.extend(self.trait_aliases.iter().map(|x| x.clean(cx)));
2c00a5a8 253
1a4d82fc
JJ
254 // determine if we should display the inner contents or
255 // the outer `mod` item for the source code.
256 let whence = {
74b04a01
XL
257 let sm = cx.sess().source_map();
258 let outer = sm.lookup_char_pos(self.where_outer.lo());
259 let inner = sm.lookup_char_pos(self.where_inner.lo());
1a4d82fc
JJ
260 if outer.file.start_pos == inner.file.start_pos {
261 // mod foo { ... }
262 self.where_outer
263 } else {
b7449926 264 // mod foo; (and a separate SourceFile for the contents)
1a4d82fc
JJ
265 self.where_inner
266 }
267 };
268
269 Item {
270 name: Some(name),
2c00a5a8 271 attrs,
1a4d82fc
JJ
272 source: whence.clean(cx),
273 visibility: self.vis.clean(cx),
416331ca
XL
274 stability: cx.stability(self.id).clean(cx),
275 deprecation: cx.deprecation(self.id).clean(cx),
0731742a 276 def_id: cx.tcx.hir().local_def_id(self.id),
dfeec247 277 inner: ModuleItem(Module { is_crate: self.is_crate, items }),
1a4d82fc
JJ
278 }
279 }
280}
281
476ff2be 282impl Clean<Attributes> for [ast::Attribute] {
532ac7d7 283 fn clean(&self, cx: &DocContext<'_>) -> Attributes {
b7449926 284 Attributes::from_ast(cx.sess().diagnostic(), self)
1a4d82fc
JJ
285 }
286}
287
dfeec247 288impl Clean<GenericBound> for hir::GenericBound<'_> {
532ac7d7 289 fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
1a4d82fc 290 match *self {
8faf50e0
XL
291 hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)),
292 hir::GenericBound::Trait(ref t, modifier) => {
293 GenericBound::TraitBound(t.clean(cx), modifier)
294 }
1a4d82fc
JJ
295 }
296 }
297}
298
ba9703b0
XL
299impl Clean<Type> for (ty::TraitRef<'_>, &[TypeBinding]) {
300 fn clean(&self, cx: &DocContext<'_>) -> Type {
301 let (trait_ref, bounds) = *self;
0531ce1d 302 inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait);
dfeec247
XL
303 let path = external_path(
304 cx,
305 cx.tcx.item_name(trait_ref.def_id),
306 Some(trait_ref.def_id),
307 true,
ba9703b0 308 bounds.to_vec(),
dfeec247
XL
309 trait_ref.substs,
310 );
1a4d82fc 311
0531ce1d 312 debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs);
1a4d82fc 313
ba9703b0
XL
314 ResolvedPath { path, param_names: None, did: trait_ref.def_id, is_generic: false }
315 }
316}
317
318impl<'tcx> Clean<GenericBound> for ty::TraitRef<'tcx> {
319 fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
320 GenericBound::TraitBound(
321 PolyTrait { trait_: (*self, &[][..]).clean(cx), generic_params: vec![] },
322 hir::TraitBoundModifier::None,
323 )
324 }
325}
326
327impl Clean<GenericBound> for (ty::PolyTraitRef<'_>, &[TypeBinding]) {
328 fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
329 let (poly_trait_ref, bounds) = *self;
330 let poly_trait_ref = poly_trait_ref.lift_to_tcx(cx.tcx).unwrap();
331
1a4d82fc 332 // collect any late bound regions
ba9703b0
XL
333 let late_bound_regions: Vec<_> = cx
334 .tcx
335 .collect_referenced_late_bound_regions(&poly_trait_ref)
336 .into_iter()
337 .filter_map(|br| match br {
338 ty::BrNamed(_, name) => Some(GenericParamDef {
339 name: name.to_string(),
340 kind: GenericParamDefKind::Lifetime,
341 }),
342 _ => None,
343 })
344 .collect();
1a4d82fc 345
8faf50e0 346 GenericBound::TraitBound(
54a0048b 347 PolyTrait {
ba9703b0
XL
348 trait_: (*poly_trait_ref.skip_binder(), bounds).clean(cx),
349 generic_params: late_bound_regions,
62682a34 350 },
dfeec247 351 hir::TraitBoundModifier::None,
54a0048b 352 )
1a4d82fc
JJ
353 }
354}
355
ba9703b0 356impl<'tcx> Clean<GenericBound> for ty::PolyTraitRef<'tcx> {
532ac7d7 357 fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
ba9703b0 358 (*self, &[][..]).clean(cx)
0531ce1d
XL
359 }
360}
361
532ac7d7
XL
362impl<'tcx> Clean<Option<Vec<GenericBound>>> for InternalSubsts<'tcx> {
363 fn clean(&self, cx: &DocContext<'_>) -> Option<Vec<GenericBound>> {
1a4d82fc 364 let mut v = Vec::new();
8faf50e0 365 v.extend(self.regions().filter_map(|r| r.clean(cx)).map(GenericBound::Outlives));
dfeec247
XL
366 v.extend(self.types().map(|t| {
367 GenericBound::TraitBound(
368 PolyTrait { trait_: t.clean(cx), generic_params: Vec::new() },
369 hir::TraitBoundModifier::None,
370 )
371 }));
372 if !v.is_empty() { Some(v) } else { None }
1a4d82fc
JJ
373 }
374}
375
e9174d1e 376impl Clean<Lifetime> for hir::Lifetime {
532ac7d7 377 fn clean(&self, cx: &DocContext<'_>) -> Lifetime {
ba9703b0
XL
378 let def = cx.tcx.named_region(self.hir_id);
379 match def {
380 Some(
381 rl::Region::EarlyBound(_, node_id, _)
382 | rl::Region::LateBound(_, node_id, _)
383 | rl::Region::Free(_, node_id),
384 ) => {
385 if let Some(lt) = cx.lt_substs.borrow().get(&node_id).cloned() {
386 return lt;
9e0c209e 387 }
9e0c209e 388 }
ba9703b0 389 _ => {}
9e0c209e 390 }
8faf50e0 391 Lifetime(self.name.ident().to_string())
1a4d82fc
JJ
392 }
393}
394
dfeec247 395impl Clean<Lifetime> for hir::GenericParam<'_> {
532ac7d7 396 fn clean(&self, _: &DocContext<'_>) -> Lifetime {
8faf50e0
XL
397 match self.kind {
398 hir::GenericParamKind::Lifetime { .. } => {
74b04a01 399 if !self.bounds.is_empty() {
8faf50e0
XL
400 let mut bounds = self.bounds.iter().map(|bound| match bound {
401 hir::GenericBound::Outlives(lt) => lt,
402 _ => panic!(),
403 });
b7449926 404 let name = bounds.next().expect("no more bounds").name.ident();
8faf50e0
XL
405 let mut s = format!("{}: {}", self.name.ident(), name);
406 for bound in bounds {
407 s.push_str(&format!(" + {}", bound.name.ident()));
408 }
409 Lifetime(s)
410 } else {
411 Lifetime(self.name.ident().to_string())
412 }
a7813a04 413 }
8faf50e0 414 _ => panic!(),
a7813a04 415 }
1a4d82fc
JJ
416 }
417}
418
9fa01778 419impl Clean<Constant> for hir::ConstArg {
532ac7d7 420 fn clean(&self, cx: &DocContext<'_>) -> Constant {
9fa01778 421 Constant {
ba9703b0
XL
422 type_: cx
423 .tcx
424 .type_of(cx.tcx.hir().body_owner_def_id(self.value.body).to_def_id())
425 .clean(cx),
9fa01778 426 expr: print_const_expr(cx, self.value.body),
dfeec247
XL
427 value: None,
428 is_literal: is_literal_expr(cx, self.value.body.hir_id),
9fa01778
XL
429 }
430 }
431}
432
dc9dc135 433impl Clean<Lifetime> for ty::GenericParamDef {
532ac7d7 434 fn clean(&self, _cx: &DocContext<'_>) -> Lifetime {
c1a9b12d 435 Lifetime(self.name.to_string())
1a4d82fc
JJ
436 }
437}
438
7cac9316 439impl Clean<Option<Lifetime>> for ty::RegionKind {
532ac7d7 440 fn clean(&self, cx: &DocContext<'_>) -> Option<Lifetime> {
1a4d82fc
JJ
441 match *self {
442 ty::ReStatic => Some(Lifetime::statik()),
8bb4bdeb 443 ty::ReLateBound(_, ty::BrNamed(_, name)) => Some(Lifetime(name.to_string())),
9346a6ac 444 ty::ReEarlyBound(ref data) => Some(Lifetime(data.name.clean(cx))),
1a4d82fc 445
dfeec247
XL
446 ty::ReLateBound(..)
447 | ty::ReFree(..)
448 | ty::ReScope(..)
449 | ty::ReVar(..)
450 | ty::RePlaceholder(..)
74b04a01 451 | ty::ReEmpty(_)
dfeec247 452 | ty::ReErased => {
416331ca 453 debug!("cannot clean region {:?}", self);
9fa01778
XL
454 None
455 }
1a4d82fc
JJ
456 }
457 }
458}
459
dfeec247 460impl Clean<WherePredicate> for hir::WherePredicate<'_> {
532ac7d7 461 fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
1a4d82fc 462 match *self {
dfeec247
XL
463 hir::WherePredicate::BoundPredicate(ref wbp) => WherePredicate::BoundPredicate {
464 ty: wbp.bounded_ty.clean(cx),
465 bounds: wbp.bounds.clean(cx),
466 },
1a4d82fc 467
dfeec247
XL
468 hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
469 lifetime: wrp.lifetime.clean(cx),
470 bounds: wrp.bounds.clean(cx),
471 },
1a4d82fc 472
32a655c1 473 hir::WherePredicate::EqPredicate(ref wrp) => {
dfeec247 474 WherePredicate::EqPredicate { lhs: wrp.lhs_ty.clean(cx), rhs: wrp.rhs_ty.clean(cx) }
1a4d82fc
JJ
475 }
476 }
477 }
478}
479
9fa01778 480impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
532ac7d7 481 fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
ba9703b0 482 use rustc_middle::ty::Predicate;
85aaf69f
SL
483
484 match *self {
dfeec247 485 Predicate::Trait(ref pred, _) => Some(pred.clean(cx)),
9fa01778 486 Predicate::Subtype(ref pred) => Some(pred.clean(cx)),
85aaf69f
SL
487 Predicate::RegionOutlives(ref pred) => pred.clean(cx),
488 Predicate::TypeOutlives(ref pred) => pred.clean(cx),
9fa01778 489 Predicate::Projection(ref pred) => Some(pred.clean(cx)),
a1dfa0c6 490
dfeec247
XL
491 Predicate::WellFormed(..)
492 | Predicate::ObjectSafe(..)
493 | Predicate::ClosureKind(..)
494 | Predicate::ConstEvaluatable(..) => panic!("not user writable"),
85aaf69f
SL
495 }
496 }
497}
498
ba9703b0 499impl<'a> Clean<WherePredicate> for ty::PolyTraitPredicate<'a> {
532ac7d7 500 fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
ba9703b0 501 let poly_trait_ref = self.map_bound(|pred| pred.trait_ref);
85aaf69f 502 WherePredicate::BoundPredicate {
ba9703b0
XL
503 ty: poly_trait_ref.self_ty().clean(cx),
504 bounds: vec![poly_trait_ref.clean(cx)],
85aaf69f
SL
505 }
506 }
507}
508
ba9703b0 509impl<'tcx> Clean<WherePredicate> for ty::PolySubtypePredicate<'tcx> {
532ac7d7 510 fn clean(&self, _cx: &DocContext<'_>) -> WherePredicate {
dfeec247
XL
511 panic!(
512 "subtype predicates are an internal rustc artifact \
513 and should not be seen by rustdoc"
514 )
cc61c64b
XL
515 }
516}
517
dfeec247 518impl<'tcx> Clean<Option<WherePredicate>>
ba9703b0 519 for ty::PolyOutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
dfeec247 520{
532ac7d7 521 fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
ba9703b0 522 let ty::OutlivesPredicate(a, b) = self.skip_binder();
9fa01778 523
ba9703b0
XL
524 if let (ty::ReEmpty(_), ty::ReEmpty(_)) = (a, b) {
525 return None;
9fa01778
XL
526 }
527
528 Some(WherePredicate::RegionPredicate {
b7449926 529 lifetime: a.clean(cx).expect("failed to clean lifetime"),
dfeec247 530 bounds: vec![GenericBound::Outlives(b.clean(cx).expect("failed to clean bounds"))],
9fa01778 531 })
85aaf69f
SL
532 }
533}
534
ba9703b0 535impl<'tcx> Clean<Option<WherePredicate>> for ty::PolyOutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>> {
532ac7d7 536 fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
ba9703b0 537 let ty::OutlivesPredicate(ty, lt) = self.skip_binder();
85aaf69f 538
ba9703b0
XL
539 if let ty::ReEmpty(_) = lt {
540 return None;
9fa01778
XL
541 }
542
543 Some(WherePredicate::BoundPredicate {
85aaf69f 544 ty: ty.clean(cx),
dfeec247 545 bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))],
9fa01778 546 })
85aaf69f
SL
547 }
548}
549
ba9703b0 550impl<'tcx> Clean<WherePredicate> for ty::PolyProjectionPredicate<'tcx> {
532ac7d7 551 fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
ba9703b0
XL
552 let ty::ProjectionPredicate { projection_ty, ty } = *self.skip_binder();
553 WherePredicate::EqPredicate { lhs: projection_ty.clean(cx), rhs: ty.clean(cx) }
85aaf69f
SL
554 }
555}
556
557impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
532ac7d7 558 fn clean(&self, cx: &DocContext<'_>) -> Type {
dfeec247
XL
559 let lifted = self.lift_to_tcx(cx.tcx).unwrap();
560 let trait_ = match lifted.trait_ref(cx.tcx).clean(cx) {
8faf50e0
XL
561 GenericBound::TraitBound(t, _) => t.trait_,
562 GenericBound::Outlives(_) => panic!("cleaning a trait got a lifetime"),
85aaf69f
SL
563 };
564 Type::QPath {
8faf50e0 565 name: cx.tcx.associated_item(self.item_def_id).ident.name.clean(cx),
041b39d2 566 self_type: box self.self_ty().clean(cx),
dfeec247 567 trait_: box trait_,
85aaf69f
SL
568 }
569 }
570}
571
532ac7d7
XL
572impl Clean<GenericParamDef> for ty::GenericParamDef {
573 fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
8faf50e0
XL
574 let (name, kind) = match self.kind {
575 ty::GenericParamDefKind::Lifetime => {
576 (self.name.to_string(), GenericParamDefKind::Lifetime)
577 }
e1599b0c 578 ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
dfeec247
XL
579 let default =
580 if has_default { Some(cx.tcx.type_of(self.def_id).clean(cx)) } else { None };
581 (
582 self.name.clean(cx),
583 GenericParamDefKind::Type {
584 did: self.def_id,
585 bounds: vec![], // These are filled in from the where-clauses.
586 default,
587 synthetic,
588 },
589 )
8faf50e0 590 }
dfeec247
XL
591 ty::GenericParamDefKind::Const { .. } => (
592 self.name.clean(cx),
593 GenericParamDefKind::Const {
532ac7d7
XL
594 did: self.def_id,
595 ty: cx.tcx.type_of(self.def_id).clean(cx),
dfeec247
XL
596 },
597 ),
8faf50e0
XL
598 };
599
dfeec247 600 GenericParamDef { name, kind }
0531ce1d
XL
601 }
602}
603
dfeec247 604impl Clean<GenericParamDef> for hir::GenericParam<'_> {
532ac7d7 605 fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
8faf50e0
XL
606 let (name, kind) = match self.kind {
607 hir::GenericParamKind::Lifetime { .. } => {
74b04a01 608 let name = if !self.bounds.is_empty() {
8faf50e0
XL
609 let mut bounds = self.bounds.iter().map(|bound| match bound {
610 hir::GenericBound::Outlives(lt) => lt,
611 _ => panic!(),
612 });
b7449926 613 let name = bounds.next().expect("no more bounds").name.ident();
8faf50e0
XL
614 let mut s = format!("{}: {}", self.name.ident(), name);
615 for bound in bounds {
616 s.push_str(&format!(" + {}", bound.name.ident()));
617 }
618 s
619 } else {
620 self.name.ident().to_string()
621 };
622 (name, GenericParamDefKind::Lifetime)
623 }
dfeec247
XL
624 hir::GenericParamKind::Type { ref default, synthetic } => (
625 self.name.ident().name.clean(cx),
626 GenericParamDefKind::Type {
416331ca 627 did: cx.tcx.hir().local_def_id(self.hir_id),
8faf50e0
XL
628 bounds: self.bounds.clean(cx),
629 default: default.clean(cx),
e74abb32 630 synthetic,
dfeec247
XL
631 },
632 ),
633 hir::GenericParamKind::Const { ref ty } => (
634 self.name.ident().name.clean(cx),
635 GenericParamDefKind::Const {
416331ca 636 did: cx.tcx.hir().local_def_id(self.hir_id),
9fa01778 637 ty: ty.clean(cx),
dfeec247
XL
638 },
639 ),
8faf50e0
XL
640 };
641
dfeec247 642 GenericParamDef { name, kind }
ff7c6d11
XL
643 }
644}
645
dfeec247 646impl Clean<Generics> for hir::Generics<'_> {
532ac7d7 647 fn clean(&self, cx: &DocContext<'_>) -> Generics {
94b46f34
XL
648 // Synthetic type-parameters are inserted after normal ones.
649 // In order for normal parameters to be able to refer to synthetic ones,
650 // scans them first.
dfeec247 651 fn is_impl_trait(param: &hir::GenericParam<'_>) -> bool {
8faf50e0
XL
652 match param.kind {
653 hir::GenericParamKind::Type { synthetic, .. } => {
654 synthetic == Some(hir::SyntheticTyParamKind::ImplTrait)
655 }
656 _ => false,
94b46f34
XL
657 }
658 }
dfeec247
XL
659 let impl_trait_params = self
660 .params
94b46f34 661 .iter()
8faf50e0
XL
662 .filter(|param| is_impl_trait(param))
663 .map(|param| {
664 let param: GenericParamDef = param.clean(cx);
665 match param.kind {
666 GenericParamDefKind::Lifetime => unreachable!(),
667 GenericParamDefKind::Type { did, ref bounds, .. } => {
e1599b0c 668 cx.impl_trait_bounds.borrow_mut().insert(did.into(), bounds.clone());
8faf50e0 669 }
9fa01778 670 GenericParamDefKind::Const { .. } => unreachable!(),
94b46f34 671 }
8faf50e0 672 param
94b46f34
XL
673 })
674 .collect::<Vec<_>>();
675
0531ce1d 676 let mut params = Vec::with_capacity(self.params.len());
94b46f34 677 for p in self.params.iter().filter(|p| !is_impl_trait(p)) {
0531ce1d 678 let p = p.clean(cx);
0531ce1d
XL
679 params.push(p);
680 }
94b46f34
XL
681 params.extend(impl_trait_params);
682
dfeec247
XL
683 let mut generics =
684 Generics { params, where_predicates: self.where_clause.predicates.clean(cx) };
ff7c6d11
XL
685
686 // Some duplicates are generated for ?Sized bounds between type params and where
687 // predicates. The point in here is to move the bounds definitions from type params
688 // to where predicates when such cases occur.
8faf50e0 689 for where_pred in &mut generics.where_predicates {
ff7c6d11
XL
690 match *where_pred {
691 WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => {
692 if bounds.is_empty() {
8faf50e0
XL
693 for param in &mut generics.params {
694 match param.kind {
695 GenericParamDefKind::Lifetime => {}
696 GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
697 if &param.name == name {
698 mem::swap(bounds, ty_bounds);
dfeec247 699 break;
8faf50e0 700 }
ff7c6d11 701 }
9fa01778 702 GenericParamDefKind::Const { .. } => {}
ff7c6d11
XL
703 }
704 }
705 }
706 }
707 _ => continue,
708 }
1a4d82fc 709 }
8faf50e0 710 generics
1a4d82fc
JJ
711 }
712}
713
e74abb32 714impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx>) {
532ac7d7 715 fn clean(&self, cx: &DocContext<'_>) -> Generics {
85aaf69f 716 use self::WherePredicate as WP;
e1599b0c 717 use std::collections::BTreeMap;
85aaf69f 718
9e0c209e 719 let (gens, preds) = *self;
85aaf69f 720
e1599b0c
XL
721 // Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
722 // since `Clean for ty::Predicate` would consume them.
723 let mut impl_trait = BTreeMap::<ImplTraitParam, Vec<GenericBound>>::default();
724
9346a6ac
AL
725 // Bounds in the type_params and lifetimes fields are repeated in the
726 // predicates field (see rustc_typeck::collect::ty_generics), so remove
727 // them.
dfeec247
XL
728 let stripped_typarams = gens
729 .params
730 .iter()
e1599b0c
XL
731 .filter_map(|param| match param.kind {
732 ty::GenericParamDefKind::Lifetime => None,
733 ty::GenericParamDefKind::Type { synthetic, .. } => {
e74abb32 734 if param.name == kw::SelfUpper {
e1599b0c
XL
735 assert_eq!(param.index, 0);
736 return None;
737 }
738 if synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) {
739 impl_trait.insert(param.index.into(), vec![]);
740 return None;
741 }
742 Some(param.clean(cx))
743 }
744 ty::GenericParamDefKind::Const { .. } => None,
dfeec247
XL
745 })
746 .collect::<Vec<GenericParamDef>>();
e1599b0c
XL
747
748 // param index -> [(DefId of trait, associated type name, type)]
dfeec247 749 let mut impl_trait_proj = FxHashMap::<u32, Vec<(DefId, String, Ty<'tcx>)>>::default();
e1599b0c 750
dfeec247
XL
751 let where_predicates = preds
752 .predicates
753 .iter()
e1599b0c
XL
754 .flat_map(|(p, _)| {
755 let mut projection = None;
756 let param_idx = (|| {
757 if let Some(trait_ref) = p.to_opt_poly_trait_ref() {
e74abb32 758 if let ty::Param(param) = trait_ref.self_ty().kind {
e1599b0c
XL
759 return Some(param.index);
760 }
761 } else if let Some(outlives) = p.to_opt_type_outlives() {
e74abb32 762 if let ty::Param(param) = outlives.skip_binder().0.kind {
e1599b0c
XL
763 return Some(param.index);
764 }
765 } else if let ty::Predicate::Projection(p) = p {
e74abb32 766 if let ty::Param(param) = p.skip_binder().projection_ty.self_ty().kind {
e1599b0c
XL
767 projection = Some(p);
768 return Some(param.index);
769 }
770 }
771
772 None
773 })();
774
775 if let Some(param_idx) = param_idx {
776 if let Some(b) = impl_trait.get_mut(&param_idx.into()) {
777 let p = p.clean(cx)?;
778
779 b.extend(
780 p.get_bounds()
781 .into_iter()
782 .flatten()
783 .cloned()
dfeec247 784 .filter(|b| !b.is_sized_bound(cx)),
e1599b0c
XL
785 );
786
787 let proj = projection
788 .map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().ty));
789 if let Some(((_, trait_did, name), rhs)) =
790 proj.as_ref().and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs)))
791 {
dfeec247
XL
792 impl_trait_proj.entry(param_idx).or_default().push((
793 trait_did,
794 name.to_string(),
795 rhs,
796 ));
e1599b0c
XL
797 }
798
799 return None;
800 }
801 }
802
803 Some(p)
804 })
805 .collect::<Vec<_>>();
806
807 for (param, mut bounds) in impl_trait {
808 // Move trait bounds to the front.
dfeec247 809 bounds.sort_by_key(|b| if let GenericBound::TraitBound(..) = b { false } else { true });
e1599b0c
XL
810
811 if let crate::core::ImplTraitParam::ParamIndex(idx) = param {
812 if let Some(proj) = impl_trait_proj.remove(&idx) {
813 for (trait_did, name, rhs) in proj {
dfeec247 814 simplify::merge_bounds(cx, &mut bounds, trait_did, &name, &rhs.clean(cx));
e1599b0c 815 }
94b46f34 816 }
e1599b0c
XL
817 } else {
818 unreachable!();
9e0c209e 819 }
85aaf69f 820
e1599b0c
XL
821 cx.impl_trait_bounds.borrow_mut().insert(param, bounds);
822 }
823
824 // Now that `cx.impl_trait_bounds` is populated, we can process
825 // remaining predicates which could contain `impl Trait`.
dfeec247
XL
826 let mut where_predicates =
827 where_predicates.into_iter().flat_map(|p| p.clean(cx)).collect::<Vec<_>>();
85aaf69f 828
9346a6ac 829 // Type parameters and have a Sized bound by default unless removed with
ff7c6d11 830 // ?Sized. Scan through the predicates and mark any type parameter with
9346a6ac
AL
831 // a Sized bound, removing the bounds as we find them.
832 //
833 // Note that associated types also have a sized bound by default, but we
d9579d0f 834 // don't actually know the set of associated types right here so that's
9346a6ac 835 // handled in cleaning associated types
0bf4aa26 836 let mut sized_params = FxHashSet::default();
dfeec247
XL
837 where_predicates.retain(|pred| match *pred {
838 WP::BoundPredicate { ty: Generic(ref g), ref bounds } => {
839 if bounds.iter().any(|b| b.is_sized_bound(cx)) {
840 sized_params.insert(g.clone());
841 false
842 } else {
843 true
85aaf69f
SL
844 }
845 }
dfeec247 846 _ => true,
9346a6ac 847 });
85aaf69f 848
9346a6ac
AL
849 // Run through the type parameters again and insert a ?Sized
850 // unbound for any we didn't find to be Sized.
85aaf69f
SL
851 for tp in &stripped_typarams {
852 if !sized_params.contains(&tp.name) {
85aaf69f
SL
853 where_predicates.push(WP::BoundPredicate {
854 ty: Type::Generic(tp.name.clone()),
8faf50e0 855 bounds: vec![GenericBound::maybe_sized(cx)],
85aaf69f
SL
856 })
857 }
858 }
859
860 // It would be nice to collect all of the bounds on a type and recombine
0731742a 861 // them if possible, to avoid e.g., `where T: Foo, T: Bar, T: Sized, T: 'a`
85aaf69f
SL
862 // and instead see `where T: Foo + Bar + Sized + 'a`
863
1a4d82fc 864 Generics {
dfeec247
XL
865 params: gens
866 .params
867 .iter()
868 .flat_map(|param| match param.kind {
869 ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
870 ty::GenericParamDefKind::Type { .. } => None,
871 ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)),
872 })
873 .chain(simplify::ty_params(stripped_typarams).into_iter())
874 .collect(),
9346a6ac 875 where_predicates: simplify::where_clauses(cx, where_predicates),
1a4d82fc
JJ
876 }
877 }
878}
879
dfeec247
XL
880impl<'a> Clean<Method>
881 for (&'a hir::FnSig<'a>, &'a hir::Generics<'a>, hir::BodyId, Option<hir::Defaultness>)
882{
532ac7d7 883 fn clean(&self, cx: &DocContext<'_>) -> Method {
dfeec247
XL
884 let (generics, decl) =
885 enter_impl_trait(cx, || (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx)));
532ac7d7 886 let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
dfeec247 887 Method { decl, generics, header: self.0.header, defaultness: self.3, all_types, ret_types }
1a4d82fc
JJ
888 }
889}
890
dc9dc135 891impl Clean<Item> for doctree::Function<'_> {
532ac7d7 892 fn clean(&self, cx: &DocContext<'_>) -> Item {
dfeec247
XL
893 let (generics, decl) =
894 enter_impl_trait(cx, || (self.generics.clean(cx), (self.decl, self.body).clean(cx)));
8faf50e0 895
416331ca 896 let did = cx.tcx.hir().local_def_id(self.id);
dfeec247 897 let constness = if is_min_const_fn(cx.tcx, did) {
0731742a
XL
898 hir::Constness::Const
899 } else {
900 hir::Constness::NotConst
901 };
532ac7d7 902 let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
1a4d82fc
JJ
903 Item {
904 name: Some(self.name.clean(cx)),
905 attrs: self.attrs.clean(cx),
906 source: self.whence.clean(cx),
907 visibility: self.vis.clean(cx),
416331ca
XL
908 stability: cx.stability(self.id).clean(cx),
909 deprecation: cx.deprecation(self.id).clean(cx),
0731742a 910 def_id: did,
1a4d82fc 911 inner: FunctionItem(Function {
0531ce1d
XL
912 decl,
913 generics,
0731742a 914 header: hir::FnHeader { constness, ..self.header },
532ac7d7
XL
915 all_types,
916 ret_types,
1a4d82fc
JJ
917 }),
918 }
60c5eb7d 919 }
1a4d82fc
JJ
920}
921
dfeec247 922impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], &'a [ast::Ident]) {
532ac7d7 923 fn clean(&self, cx: &DocContext<'_>) -> Arguments {
32a655c1 924 Arguments {
dfeec247
XL
925 values: self
926 .0
927 .iter()
928 .enumerate()
929 .map(|(i, ty)| {
930 let mut name =
931 self.1.get(i).map(|ident| ident.to_string()).unwrap_or(String::new());
932 if name.is_empty() {
933 name = "_".to_string();
934 }
935 Argument { name, type_: ty.clean(cx) }
936 })
937 .collect(),
32a655c1
SL
938 }
939 }
940}
941
dfeec247 942impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], hir::BodyId) {
532ac7d7 943 fn clean(&self, cx: &DocContext<'_>) -> Arguments {
0731742a 944 let body = cx.tcx.hir().body(self.1);
32a655c1
SL
945
946 Arguments {
dfeec247
XL
947 values: self
948 .0
949 .iter()
950 .enumerate()
951 .map(|(i, ty)| Argument {
e1599b0c 952 name: name_from_pat(&body.params[i].pat),
32a655c1 953 type_: ty.clean(cx),
dfeec247
XL
954 })
955 .collect(),
32a655c1
SL
956 }
957 }
958}
959
dfeec247
XL
960impl<'a, A: Copy> Clean<FnDecl> for (&'a hir::FnDecl<'a>, A)
961where
962 (&'a [hir::Ty<'a>], A): Clean<Arguments>,
32a655c1 963{
532ac7d7 964 fn clean(&self, cx: &DocContext<'_>) -> FnDecl {
1a4d82fc 965 FnDecl {
32a655c1
SL
966 inputs: (&self.0.inputs[..], self.1).clean(cx),
967 output: self.0.output.clean(cx),
e74abb32 968 c_variadic: self.0.c_variadic,
532ac7d7 969 attrs: Attributes::default(),
1a4d82fc
JJ
970 }
971 }
972}
973
dc9dc135 974impl<'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
532ac7d7 975 fn clean(&self, cx: &DocContext<'_>) -> FnDecl {
1a4d82fc 976 let (did, sig) = *self;
532ac7d7 977 let mut names = if cx.tcx.hir().as_local_hir_id(did).is_some() {
ba9703b0 978 &[]
1a4d82fc 979 } else {
ba9703b0
XL
980 cx.tcx.fn_arg_names(did)
981 }
982 .iter();
0531ce1d 983
1a4d82fc 984 FnDecl {
476ff2be
SL
985 output: Return(sig.skip_binder().output().clean(cx)),
986 attrs: Attributes::default(),
e74abb32 987 c_variadic: sig.skip_binder().c_variadic,
1a4d82fc 988 inputs: Arguments {
dfeec247
XL
989 values: sig
990 .skip_binder()
991 .inputs()
992 .iter()
993 .map(|t| Argument {
1a4d82fc 994 type_: t.clean(cx),
b7449926 995 name: names.next().map_or(String::new(), |name| name.to_string()),
dfeec247
XL
996 })
997 .collect(),
1a4d82fc
JJ
998 },
999 }
1000 }
1001}
1002
74b04a01
XL
1003impl Clean<FnRetTy> for hir::FnRetTy<'_> {
1004 fn clean(&self, cx: &DocContext<'_>) -> FnRetTy {
1a4d82fc 1005 match *self {
dfeec247
XL
1006 Self::Return(ref typ) => Return(typ.clean(cx)),
1007 Self::DefaultReturn(..) => DefaultReturn,
1a4d82fc
JJ
1008 }
1009 }
1010}
1011
dc9dc135 1012impl Clean<Item> for doctree::Trait<'_> {
532ac7d7 1013 fn clean(&self, cx: &DocContext<'_>) -> Item {
ff7c6d11 1014 let attrs = self.attrs.clean(cx);
1a4d82fc
JJ
1015 Item {
1016 name: Some(self.name.clean(cx)),
e74abb32 1017 attrs,
1a4d82fc 1018 source: self.whence.clean(cx),
416331ca 1019 def_id: cx.tcx.hir().local_def_id(self.id),
1a4d82fc 1020 visibility: self.vis.clean(cx),
416331ca
XL
1021 stability: cx.stability(self.id).clean(cx),
1022 deprecation: cx.deprecation(self.id).clean(cx),
1a4d82fc 1023 inner: TraitItem(Trait {
0531ce1d 1024 auto: self.is_auto.clean(cx),
1a4d82fc 1025 unsafety: self.unsafety,
dc9dc135 1026 items: self.items.iter().map(|ti| ti.clean(cx)).collect(),
1a4d82fc
JJ
1027 generics: self.generics.clean(cx),
1028 bounds: self.bounds.clean(cx),
2c00a5a8 1029 is_auto: self.is_auto.clean(cx),
1a4d82fc
JJ
1030 }),
1031 }
1032 }
1033}
1034
dc9dc135 1035impl Clean<Item> for doctree::TraitAlias<'_> {
532ac7d7 1036 fn clean(&self, cx: &DocContext<'_>) -> Item {
9fa01778
XL
1037 let attrs = self.attrs.clean(cx);
1038 Item {
1039 name: Some(self.name.clean(cx)),
1040 attrs,
1041 source: self.whence.clean(cx),
416331ca 1042 def_id: cx.tcx.hir().local_def_id(self.id),
9fa01778 1043 visibility: self.vis.clean(cx),
416331ca
XL
1044 stability: cx.stability(self.id).clean(cx),
1045 deprecation: cx.deprecation(self.id).clean(cx),
9fa01778
XL
1046 inner: TraitAliasItem(TraitAlias {
1047 generics: self.generics.clean(cx),
1048 bounds: self.bounds.clean(cx),
1049 }),
1050 }
1051 }
1052}
1053
2c00a5a8 1054impl Clean<bool> for hir::IsAuto {
532ac7d7 1055 fn clean(&self, _: &DocContext<'_>) -> bool {
2c00a5a8
XL
1056 match *self {
1057 hir::IsAuto::Yes => true,
1058 hir::IsAuto::No => false,
1059 }
1060 }
1061}
1062
dfeec247 1063impl Clean<Type> for hir::TraitRef<'_> {
532ac7d7
XL
1064 fn clean(&self, cx: &DocContext<'_>) -> Type {
1065 resolve_type(cx, self.path.clean(cx), self.hir_ref_id)
1a4d82fc
JJ
1066 }
1067}
1068
dfeec247 1069impl Clean<PolyTrait> for hir::PolyTraitRef<'_> {
532ac7d7 1070 fn clean(&self, cx: &DocContext<'_>) -> PolyTrait {
1a4d82fc
JJ
1071 PolyTrait {
1072 trait_: self.trait_ref.clean(cx),
dfeec247 1073 generic_params: self.bound_generic_params.clean(cx),
1a4d82fc
JJ
1074 }
1075 }
1076}
1077
ba9703b0
XL
1078impl Clean<TypeKind> for hir::def::DefKind {
1079 fn clean(&self, _: &DocContext<'_>) -> TypeKind {
1080 match *self {
1081 hir::def::DefKind::Mod => TypeKind::Module,
1082 hir::def::DefKind::Struct => TypeKind::Struct,
1083 hir::def::DefKind::Union => TypeKind::Union,
1084 hir::def::DefKind::Enum => TypeKind::Enum,
1085 hir::def::DefKind::Trait => TypeKind::Trait,
1086 hir::def::DefKind::TyAlias => TypeKind::Typedef,
1087 hir::def::DefKind::ForeignTy => TypeKind::Foreign,
1088 hir::def::DefKind::TraitAlias => TypeKind::TraitAlias,
1089 hir::def::DefKind::Fn => TypeKind::Function,
1090 hir::def::DefKind::Const => TypeKind::Const,
1091 hir::def::DefKind::Static => TypeKind::Static,
1092 hir::def::DefKind::Macro(_) => TypeKind::Macro,
1093 _ => TypeKind::Foreign,
1094 }
1095 }
1096}
1097
dfeec247 1098impl Clean<Item> for hir::TraitItem<'_> {
532ac7d7 1099 fn clean(&self, cx: &DocContext<'_>) -> Item {
e74abb32 1100 let inner = match self.kind {
32a655c1 1101 hir::TraitItemKind::Const(ref ty, default) => {
dfeec247 1102 AssocConstItem(ty.clean(cx), default.map(|e| print_const_expr(cx, e)))
d9579d0f 1103 }
ba9703b0 1104 hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
532ac7d7 1105 MethodItem((sig, &self.generics, body, None).clean(cx))
c34b1796 1106 }
ba9703b0 1107 hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref names)) => {
0531ce1d
XL
1108 let (generics, decl) = enter_impl_trait(cx, || {
1109 (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
1110 });
532ac7d7 1111 let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
dfeec247 1112 TyMethodItem(TyMethod { header: sig.header, decl, generics, all_types, ret_types })
c34b1796 1113 }
32a655c1 1114 hir::TraitItemKind::Type(ref bounds, ref default) => {
dc9dc135 1115 AssocTypeItem(bounds.clean(cx), default.clean(cx))
c34b1796
AL
1116 }
1117 };
416331ca 1118 let local_did = cx.tcx.hir().local_def_id(self.hir_id);
c34b1796 1119 Item {
8faf50e0 1120 name: Some(self.ident.name.clean(cx)),
c34b1796
AL
1121 attrs: self.attrs.clean(cx),
1122 source: self.span.clean(cx),
532ac7d7 1123 def_id: local_did,
e74abb32 1124 visibility: Visibility::Inherited,
532ac7d7
XL
1125 stability: get_stability(cx, local_did),
1126 deprecation: get_deprecation(cx, local_did),
3b2f2976 1127 inner,
1a4d82fc
JJ
1128 }
1129 }
1130}
1131
dfeec247 1132impl Clean<Item> for hir::ImplItem<'_> {
532ac7d7 1133 fn clean(&self, cx: &DocContext<'_>) -> Item {
e74abb32 1134 let inner = match self.kind {
32a655c1 1135 hir::ImplItemKind::Const(ref ty, expr) => {
dfeec247 1136 AssocConstItem(ty.clean(cx), Some(print_const_expr(cx, expr)))
d9579d0f 1137 }
ba9703b0 1138 hir::ImplItemKind::Fn(ref sig, body) => {
532ac7d7 1139 MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx))
c34b1796 1140 }
dfeec247
XL
1141 hir::ImplItemKind::TyAlias(ref ty) => {
1142 let type_ = ty.clean(cx);
1143 let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
1144 TypedefItem(Typedef { type_, generics: Generics::default(), item_type }, true)
1145 }
1146 hir::ImplItemKind::OpaqueTy(ref bounds) => OpaqueTyItem(
1147 OpaqueTy { bounds: bounds.clean(cx), generics: Generics::default() },
1148 true,
1149 ),
c34b1796 1150 };
416331ca 1151 let local_did = cx.tcx.hir().local_def_id(self.hir_id);
c34b1796 1152 Item {
8faf50e0 1153 name: Some(self.ident.name.clean(cx)),
c34b1796
AL
1154 source: self.span.clean(cx),
1155 attrs: self.attrs.clean(cx),
532ac7d7 1156 def_id: local_did,
c34b1796 1157 visibility: self.vis.clean(cx),
532ac7d7
XL
1158 stability: get_stability(cx, local_did),
1159 deprecation: get_deprecation(cx, local_did),
3b2f2976 1160 inner,
1a4d82fc
JJ
1161 }
1162 }
1163}
1164
dc9dc135 1165impl Clean<Item> for ty::AssocItem {
532ac7d7 1166 fn clean(&self, cx: &DocContext<'_>) -> Item {
476ff2be 1167 let inner = match self.kind {
dc9dc135 1168 ty::AssocKind::Const => {
7cac9316 1169 let ty = cx.tcx.type_of(self.def_id);
ff7c6d11
XL
1170 let default = if self.defaultness.has_value() {
1171 Some(inline::print_inlined_const(cx, self.def_id))
1172 } else {
1173 None
1174 };
dc9dc135 1175 AssocConstItem(ty.clean(cx), default)
a7813a04 1176 }
ba9703b0 1177 ty::AssocKind::Fn => {
dfeec247
XL
1178 let generics =
1179 (cx.tcx.generics_of(self.def_id), cx.tcx.explicit_predicates_of(self.def_id))
1180 .clean(cx);
041b39d2 1181 let sig = cx.tcx.fn_sig(self.def_id);
8bb4bdeb 1182 let mut decl = (self.def_id, sig).clean(cx);
476ff2be 1183
ba9703b0 1184 if self.fn_has_self_parameter {
476ff2be 1185 let self_ty = match self.container {
dfeec247 1186 ty::ImplContainer(def_id) => cx.tcx.type_of(def_id),
e1599b0c 1187 ty::TraitContainer(_) => cx.tcx.types.self_param,
476ff2be 1188 };
8bb4bdeb 1189 let self_arg_ty = *sig.input(0).skip_binder();
476ff2be 1190 if self_arg_ty == self_ty {
32a655c1 1191 decl.inputs.values[0].type_ = Generic(String::from("Self"));
e74abb32 1192 } else if let ty::Ref(_, ty, _) = self_arg_ty.kind {
94b46f34 1193 if ty == self_ty {
476ff2be 1194 match decl.inputs.values[0].type_ {
dfeec247 1195 BorrowedRef { ref mut type_, .. } => {
32a655c1
SL
1196 **type_ = Generic(String::from("Self"))
1197 }
476ff2be
SL
1198 _ => unreachable!(),
1199 }
1200 }
1201 }
1202 }
1203
1204 let provided = match self.container {
ff7c6d11 1205 ty::ImplContainer(_) => true,
dfeec247 1206 ty::TraitContainer(_) => self.defaultness.has_value(),
476ff2be 1207 };
532ac7d7 1208 let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
476ff2be 1209 if provided {
dfeec247 1210 let constness = if is_min_const_fn(cx.tcx, self.def_id) {
ff7c6d11
XL
1211 hir::Constness::Const
1212 } else {
1213 hir::Constness::NotConst
1214 };
e1599b0c 1215 let asyncness = cx.tcx.asyncness(self.def_id);
532ac7d7
XL
1216 let defaultness = match self.container {
1217 ty::ImplContainer(_) => Some(self.defaultness),
1218 ty::TraitContainer(_) => None,
1219 };
476ff2be 1220 MethodItem(Method {
3b2f2976
XL
1221 generics,
1222 decl,
8faf50e0
XL
1223 header: hir::FnHeader {
1224 unsafety: sig.unsafety(),
1225 abi: sig.abi(),
1226 constness,
e1599b0c 1227 asyncness,
532ac7d7
XL
1228 },
1229 defaultness,
1230 all_types,
1231 ret_types,
476ff2be
SL
1232 })
1233 } else {
1234 TyMethodItem(TyMethod {
3b2f2976
XL
1235 generics,
1236 decl,
8faf50e0
XL
1237 header: hir::FnHeader {
1238 unsafety: sig.unsafety(),
1239 abi: sig.abi(),
1240 constness: hir::Constness::NotConst,
1241 asyncness: hir::IsAsync::NotAsync,
532ac7d7
XL
1242 },
1243 all_types,
1244 ret_types,
476ff2be 1245 })
a7813a04
XL
1246 }
1247 }
dc9dc135 1248 ty::AssocKind::Type => {
8faf50e0 1249 let my_name = self.ident.name.clean(cx);
476ff2be 1250
ff7c6d11 1251 if let ty::TraitContainer(did) = self.container {
476ff2be
SL
1252 // When loading a cross-crate associated type, the bounds for this type
1253 // are actually located on the trait/impl itself, so we need to load
1254 // all of the generics from there and then look for bounds that are
1255 // applied to this associated type in question.
532ac7d7 1256 let predicates = cx.tcx.explicit_predicates_of(did);
e74abb32 1257 let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
dfeec247
XL
1258 let mut bounds = generics
1259 .where_predicates
1260 .iter()
1261 .filter_map(|pred| {
1262 let (name, self_type, trait_, bounds) = match *pred {
1263 WherePredicate::BoundPredicate {
1264 ty: QPath { ref name, ref self_type, ref trait_ },
1265 ref bounds,
1266 } => (name, self_type, trait_, bounds),
1267 _ => return None,
1268 };
1269 if *name != my_name {
1270 return None;
1271 }
1272 match **trait_ {
1273 ResolvedPath { did, .. } if did == self.container.id() => {}
1274 _ => return None,
1275 }
1276 match **self_type {
1277 Generic(ref s) if *s == "Self" => {}
1278 _ => return None,
1279 }
1280 Some(bounds)
1281 })
1282 .flat_map(|i| i.iter().cloned())
1283 .collect::<Vec<_>>();
ff7c6d11
XL
1284 // Our Sized/?Sized bound didn't get handled when creating the generics
1285 // because we didn't actually get our whole set of bounds until just now
1286 // (some of them may have come from the trait). If we do have a sized
1287 // bound, we remove it, and if we don't then we add the `?Sized` bound
1288 // at the end.
1289 match bounds.iter().position(|b| b.is_sized_bound(cx)) {
dfeec247
XL
1290 Some(i) => {
1291 bounds.remove(i);
1292 }
8faf50e0 1293 None => bounds.push(GenericBound::maybe_sized(cx)),
ff7c6d11 1294 }
476ff2be 1295
ff7c6d11
XL
1296 let ty = if self.defaultness.has_value() {
1297 Some(cx.tcx.type_of(self.def_id))
1298 } else {
1299 None
1300 };
476ff2be 1301
dc9dc135 1302 AssocTypeItem(bounds, ty.clean(cx))
476ff2be 1303 } else {
dfeec247
XL
1304 let type_ = cx.tcx.type_of(self.def_id).clean(cx);
1305 let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
1306 TypedefItem(
1307 Typedef {
1308 type_,
1309 generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
1310 item_type,
ff7c6d11 1311 },
dfeec247
XL
1312 true,
1313 )
ff7c6d11 1314 }
9346a6ac 1315 }
416331ca 1316 ty::AssocKind::OpaqueTy => unimplemented!(),
9346a6ac 1317 };
9346a6ac 1318
ff7c6d11
XL
1319 let visibility = match self.container {
1320 ty::ImplContainer(_) => self.vis.clean(cx),
e74abb32 1321 ty::TraitContainer(_) => Inherited,
ff7c6d11
XL
1322 };
1323
1a4d82fc 1324 Item {
8faf50e0 1325 name: Some(self.ident.name.clean(cx)),
ff7c6d11 1326 visibility,
1a4d82fc 1327 stability: get_stability(cx, self.def_id),
9cc50fc6 1328 deprecation: get_deprecation(cx, self.def_id),
1a4d82fc 1329 def_id: self.def_id,
416331ca 1330 attrs: inline::load_attrs(cx, self.def_id).clean(cx),
476ff2be 1331 source: cx.tcx.def_span(self.def_id).clean(cx),
3b2f2976 1332 inner,
1a4d82fc
JJ
1333 }
1334 }
1335}
1336
dfeec247 1337impl Clean<Type> for hir::Ty<'_> {
532ac7d7 1338 fn clean(&self, cx: &DocContext<'_>) -> Type {
dfeec247 1339 use rustc_hir::*;
b7449926 1340
e74abb32 1341 match self.kind {
8faf50e0 1342 TyKind::Never => Never,
dfeec247 1343 TyKind::Ptr(ref m) => RawPointer(m.mutbl, box m.ty.clean(cx)),
8faf50e0 1344 TyKind::Rptr(ref l, ref m) => {
dfeec247
XL
1345 let lifetime = if l.is_elided() { None } else { Some(l.clean(cx)) };
1346 BorrowedRef { lifetime, mutability: m.mutbl, type_: box m.ty.clean(cx) }
32a655c1 1347 }
8faf50e0
XL
1348 TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
1349 TyKind::Array(ref ty, ref length) => {
416331ca 1350 let def_id = cx.tcx.hir().local_def_id(length.hir_id);
dfeec247 1351 let length = match cx.tcx.const_eval_poly(def_id) {
74b04a01
XL
1352 Ok(length) => {
1353 print_const(cx, ty::Const::from_value(cx.tcx, length, cx.tcx.types.usize))
1354 }
dfeec247
XL
1355 Err(_) => cx
1356 .sess()
1357 .source_map()
1358 .span_to_snippet(cx.tcx.def_span(def_id))
1359 .unwrap_or_else(|_| "_".to_string()),
0731742a 1360 };
94b46f34 1361 Array(box ty.clean(cx), length)
dfeec247 1362 }
8faf50e0 1363 TyKind::Tup(ref tys) => Tuple(tys.clean(cx)),
0bf4aa26 1364 TyKind::Def(item_id, _) => {
dc9dc135 1365 let item = cx.tcx.hir().expect_item(item_id.id);
e74abb32 1366 if let hir::ItemKind::OpaqueTy(ref ty) = item.kind {
0bf4aa26
XL
1367 ImplTrait(ty.bounds.clean(cx))
1368 } else {
1369 unreachable!()
1370 }
1371 }
8faf50e0 1372 TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
48663c56
XL
1373 if let Res::Def(DefKind::TyParam, did) = path.res {
1374 if let Some(new_ty) = cx.ty_substs.borrow().get(&did).cloned() {
1375 return new_ty;
1376 }
e1599b0c 1377 if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did.into()) {
0531ce1d
XL
1378 return ImplTrait(bounds);
1379 }
1380 }
1381
476ff2be 1382 let mut alias = None;
48663c56 1383 if let Res::Def(DefKind::TyAlias, def_id) = path.res {
476ff2be 1384 // Substitute private type aliases
9fa01778 1385 if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
0bf4aa26 1386 if !cx.renderinfo.borrow().access_levels.is_exported(def_id) {
e74abb32 1387 alias = Some(&cx.tcx.hir().expect_item(hir_id).kind);
476ff2be 1388 }
9e0c209e 1389 }
476ff2be
SL
1390 };
1391
416331ca 1392 if let Some(&hir::ItemKind::TyAlias(ref ty, ref generics)) = alias {
b7449926 1393 let provided_params = &path.segments.last().expect("segments were empty");
0bf4aa26
XL
1394 let mut ty_substs = FxHashMap::default();
1395 let mut lt_substs = FxHashMap::default();
48663c56 1396 let mut ct_substs = FxHashMap::default();
dc9dc135
XL
1397 let generic_args = provided_params.generic_args();
1398 {
b7449926 1399 let mut indices: GenericParamCount = Default::default();
94b46f34 1400 for param in generics.params.iter() {
8faf50e0
XL
1401 match param.kind {
1402 hir::GenericParamKind::Lifetime { .. } => {
1403 let mut j = 0;
dfeec247
XL
1404 let lifetime =
1405 generic_args.args.iter().find_map(|arg| match arg {
9fa01778 1406 hir::GenericArg::Lifetime(lt) => {
8faf50e0
XL
1407 if indices.lifetimes == j {
1408 return Some(lt);
1409 }
1410 j += 1;
1411 None
1412 }
1413 _ => None,
dfeec247 1414 });
8faf50e0 1415 if let Some(lt) = lifetime.cloned() {
94b46f34 1416 if !lt.is_elided() {
dfeec247 1417 let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
94b46f34
XL
1418 lt_substs.insert(lt_def_id, lt.clean(cx));
1419 }
1420 }
1421 indices.lifetimes += 1;
1422 }
8faf50e0 1423 hir::GenericParamKind::Type { ref default, .. } => {
dfeec247 1424 let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
8faf50e0 1425 let mut j = 0;
dfeec247
XL
1426 let type_ =
1427 generic_args.args.iter().find_map(|arg| match arg {
9fa01778 1428 hir::GenericArg::Type(ty) => {
8faf50e0
XL
1429 if indices.types == j {
1430 return Some(ty);
1431 }
1432 j += 1;
1433 None
1434 }
1435 _ => None,
dfeec247 1436 });
dc9dc135 1437 if let Some(ty) = type_ {
48663c56 1438 ty_substs.insert(ty_param_def_id, ty.clean(cx));
dfeec247
XL
1439 } else if let Some(default) = *default {
1440 ty_substs.insert(ty_param_def_id, default.clean(cx));
94b46f34
XL
1441 }
1442 indices.types += 1;
ea8adc8c 1443 }
9fa01778 1444 hir::GenericParamKind::Const { .. } => {
48663c56 1445 let const_param_def_id =
416331ca 1446 cx.tcx.hir().local_def_id(param.hir_id);
9fa01778 1447 let mut j = 0;
dfeec247
XL
1448 let const_ =
1449 generic_args.args.iter().find_map(|arg| match arg {
9fa01778
XL
1450 hir::GenericArg::Const(ct) => {
1451 if indices.consts == j {
1452 return Some(ct);
1453 }
1454 j += 1;
1455 None
1456 }
1457 _ => None,
dfeec247 1458 });
dc9dc135 1459 if let Some(ct) = const_ {
48663c56 1460 ct_substs.insert(const_param_def_id, ct.clean(cx));
9fa01778
XL
1461 }
1462 // FIXME(const_generics:defaults)
1463 indices.consts += 1;
1464 }
32a655c1 1465 }
9e0c209e 1466 }
dc9dc135 1467 }
48663c56 1468 return cx.enter_alias(ty_substs, lt_substs, ct_substs, || ty.clean(cx));
5bcae85e 1469 }
532ac7d7 1470 resolve_type(cx, path.clean(cx), self.hir_id)
c34b1796 1471 }
8faf50e0 1472 TyKind::Path(hir::QPath::Resolved(Some(ref qself), ref p)) => {
dc9dc135
XL
1473 let segments = if p.is_global() { &p.segments[1..] } else { &p.segments };
1474 let trait_segments = &segments[..segments.len() - 1];
1475 let trait_path = self::Path {
1476 global: p.is_global(),
48663c56
XL
1477 res: Res::Def(
1478 DefKind::Trait,
1479 cx.tcx.associated_item(p.res.def_id()).container.id(),
1480 ),
dc9dc135 1481 segments: trait_segments.clean(cx),
9cc50fc6 1482 };
c34b1796 1483 Type::QPath {
b7449926 1484 name: p.segments.last().expect("segments were empty").ident.name.clean(cx),
476ff2be 1485 self_type: box qself.clean(cx),
dfeec247 1486 trait_: box resolve_type(cx, trait_path, self.hir_id),
476ff2be
SL
1487 }
1488 }
8faf50e0 1489 TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
48663c56 1490 let mut res = Res::Err;
7cac9316 1491 let ty = hir_ty_to_ty(cx.tcx, self);
e74abb32 1492 if let ty::Projection(proj) = ty.kind {
48663c56 1493 res = Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id);
476ff2be 1494 }
dfeec247 1495 let trait_path = hir::Path { span: self.span, res, segments: &[] };
476ff2be 1496 Type::QPath {
8faf50e0 1497 name: segment.ident.name.clean(cx),
476ff2be 1498 self_type: box qself.clean(cx),
dfeec247 1499 trait_: box resolve_type(cx, trait_path.clean(cx), self.hir_id),
c34b1796 1500 }
1a4d82fc 1501 }
8faf50e0 1502 TyKind::TraitObject(ref bounds, ref lifetime) => {
32a655c1 1503 match bounds[0].clean(cx).trait_ {
532ac7d7 1504 ResolvedPath { path, param_names: None, did, is_generic } => {
dfeec247
XL
1505 let mut bounds: Vec<self::GenericBound> = bounds[1..]
1506 .iter()
1507 .map(|bound| {
1508 self::GenericBound::TraitBound(
1509 bound.clean(cx),
1510 hir::TraitBoundModifier::None,
1511 )
1512 })
1513 .collect();
32a655c1 1514 if !lifetime.is_elided() {
8faf50e0 1515 bounds.push(self::GenericBound::Outlives(lifetime.clean(cx)));
62682a34 1516 }
dfeec247 1517 ResolvedPath { path, param_names: Some(bounds), did, is_generic }
1a4d82fc 1518 }
dc9dc135 1519 _ => Infer, // shouldn't happen
1a4d82fc
JJ
1520 }
1521 }
8faf50e0
XL
1522 TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
1523 TyKind::Infer | TyKind::Err => Infer,
e74abb32 1524 TyKind::Typeof(..) => panic!("unimplemented type {:?}", self.kind),
1a4d82fc
JJ
1525 }
1526 }
1527}
1528
ea8adc8c 1529impl<'tcx> Clean<Type> for Ty<'tcx> {
532ac7d7 1530 fn clean(&self, cx: &DocContext<'_>) -> Type {
48663c56 1531 debug!("cleaning type: {:?}", self);
e74abb32 1532 match self.kind {
b7449926
XL
1533 ty::Never => Never,
1534 ty::Bool => Primitive(PrimitiveType::Bool),
1535 ty::Char => Primitive(PrimitiveType::Char),
1536 ty::Int(int_ty) => Primitive(int_ty.into()),
1537 ty::Uint(uint_ty) => Primitive(uint_ty.into()),
1538 ty::Float(float_ty) => Primitive(float_ty.into()),
1539 ty::Str => Primitive(PrimitiveType::Str),
1540 ty::Slice(ty) => Slice(box ty.clean(cx)),
1541 ty::Array(ty, n) => {
dc9dc135 1542 let mut n = cx.tcx.lift(&n).expect("array lift failed");
dfeec247 1543 n = n.eval(cx.tcx, ty::ParamEnv::reveal_all());
0531ce1d 1544 let n = print_const(cx, n);
ea8adc8c
XL
1545 Array(box ty.clean(cx), n)
1546 }
dfeec247
XL
1547 ty::RawPtr(mt) => RawPointer(mt.mutbl, box mt.ty.clean(cx)),
1548 ty::Ref(r, ty, mutbl) => {
1549 BorrowedRef { lifetime: r.clean(cx), mutability: mutbl, type_: box ty.clean(cx) }
1550 }
1551 ty::FnDef(..) | ty::FnPtr(_) => {
b7449926 1552 let ty = cx.tcx.lift(self).expect("FnPtr lift failed");
041b39d2 1553 let sig = ty.fn_sig(cx.tcx);
416331ca 1554 let local_def_id = cx.tcx.hir().local_def_id_from_node_id(ast::CRATE_NODE_ID);
041b39d2
XL
1555 BareFunction(box BareFunctionDecl {
1556 unsafety: sig.unsafety(),
ff7c6d11 1557 generic_params: Vec::new(),
ba9703b0 1558 decl: (local_def_id.to_def_id(), sig).clean(cx),
041b39d2
XL
1559 abi: sig.abi(),
1560 })
1561 }
b7449926 1562 ty::Adt(def, substs) => {
e9174d1e 1563 let did = def.did;
9e0c209e 1564 let kind = match def.adt_kind() {
c30ab7b3
SL
1565 AdtKind::Struct => TypeKind::Struct,
1566 AdtKind::Union => TypeKind::Union,
1567 AdtKind::Enum => TypeKind::Enum,
1a4d82fc 1568 };
92a42be0 1569 inline::record_extern_fqn(cx, did, kind);
e1599b0c 1570 let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], substs);
dfeec247 1571 ResolvedPath { path, param_names: None, did, is_generic: false }
1a4d82fc 1572 }
b7449926 1573 ty::Foreign(did) => {
abe05a73 1574 inline::record_extern_fqn(cx, did, TypeKind::Foreign);
dfeec247
XL
1575 let path = external_path(
1576 cx,
1577 cx.tcx.item_name(did),
1578 None,
1579 false,
1580 vec![],
1581 InternalSubsts::empty(),
1582 );
1583 ResolvedPath { path, param_names: None, did, is_generic: false }
abe05a73 1584 }
b7449926 1585 ty::Dynamic(ref obj, ref reg) => {
0731742a
XL
1586 // HACK: pick the first `did` as the `did` of the trait object. Someone
1587 // might want to implement "native" support for marker-trait-only
1588 // trait objects.
1589 let mut dids = obj.principal_def_id().into_iter().chain(obj.auto_traits());
dfeec247
XL
1590 let did = dids
1591 .next()
1592 .unwrap_or_else(|| panic!("found trait object `{:?}` with no traits?", self));
0731742a
XL
1593 let substs = match obj.principal() {
1594 Some(principal) => principal.skip_binder().substs,
1595 // marker traits have no substs.
dfeec247 1596 _ => cx.tcx.intern_substs(&[]),
0731742a
XL
1597 };
1598
0bf4aa26
XL
1599 inline::record_extern_fqn(cx, did, TypeKind::Trait);
1600
532ac7d7
XL
1601 let mut param_names = vec![];
1602 reg.clean(cx).map(|b| param_names.push(GenericBound::Outlives(b)));
0731742a 1603 for did in dids {
0bf4aa26 1604 let empty = cx.tcx.intern_substs(&[]);
dfeec247
XL
1605 let path =
1606 external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
476ff2be 1607 inline::record_extern_fqn(cx, did, TypeKind::Trait);
dfeec247
XL
1608 let bound = GenericBound::TraitBound(
1609 PolyTrait {
1610 trait_: ResolvedPath {
1611 path,
1612 param_names: None,
1613 did,
1614 is_generic: false,
1615 },
1616 generic_params: Vec::new(),
0bf4aa26 1617 },
dfeec247
XL
1618 hir::TraitBoundModifier::None,
1619 );
532ac7d7 1620 param_names.push(bound);
0bf4aa26 1621 }
476ff2be 1622
0bf4aa26
XL
1623 let mut bindings = vec![];
1624 for pb in obj.projection_bounds() {
1625 bindings.push(TypeBinding {
1626 name: cx.tcx.associated_item(pb.item_def_id()).ident.name.clean(cx),
dfeec247 1627 kind: TypeBindingKind::Equality { ty: pb.skip_binder().ty.clean(cx) },
0bf4aa26
XL
1628 });
1629 }
9e0c209e 1630
dfeec247
XL
1631 let path =
1632 external_path(cx, cx.tcx.item_name(did), Some(did), false, bindings, substs);
1633 ResolvedPath { path, param_names: Some(param_names), did, is_generic: false }
1a4d82fc 1634 }
48663c56
XL
1635 ty::Tuple(ref t) => {
1636 Tuple(t.iter().map(|t| t.expect_ty()).collect::<Vec<_>>().clean(cx))
1637 }
1a4d82fc 1638
b7449926 1639 ty::Projection(ref data) => data.clean(cx),
1a4d82fc 1640
e1599b0c
XL
1641 ty::Param(ref p) => {
1642 if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&p.index.into()) {
1643 ImplTrait(bounds)
1644 } else {
1645 Generic(p.name.to_string())
1646 }
1647 }
1a4d82fc 1648
b7449926 1649 ty::Opaque(def_id, substs) => {
5bcae85e
SL
1650 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
1651 // by looking up the projections associated with the def_id.
532ac7d7 1652 let predicates_of = cx.tcx.explicit_predicates_of(def_id);
b7449926 1653 let substs = cx.tcx.lift(&substs).expect("Opaque lift failed");
7cac9316 1654 let bounds = predicates_of.instantiate(cx.tcx, substs);
0531ce1d
XL
1655 let mut regions = vec![];
1656 let mut has_sized = false;
dfeec247
XL
1657 let mut bounds = bounds
1658 .predicates
1659 .iter()
1660 .filter_map(|predicate| {
1661 let trait_ref = if let Some(tr) = predicate.to_opt_poly_trait_ref() {
1662 tr
1663 } else if let ty::Predicate::TypeOutlives(pred) = *predicate {
1664 // these should turn up at the end
1665 pred.skip_binder()
1666 .1
1667 .clean(cx)
1668 .map(|r| regions.push(GenericBound::Outlives(r)));
0531ce1d 1669 return None;
dfeec247
XL
1670 } else {
1671 return None;
1672 };
0531ce1d 1673
dfeec247
XL
1674 if let Some(sized) = cx.tcx.lang_items().sized_trait() {
1675 if trait_ref.def_id() == sized {
1676 has_sized = true;
1677 return None;
0531ce1d 1678 }
0531ce1d 1679 }
0531ce1d 1680
ba9703b0 1681 let bounds: Vec<_> = bounds
dfeec247
XL
1682 .predicates
1683 .iter()
1684 .filter_map(|pred| {
1685 if let ty::Predicate::Projection(proj) = *pred {
1686 let proj = proj.skip_binder();
1687 if proj.projection_ty.trait_ref(cx.tcx)
1688 == *trait_ref.skip_binder()
1689 {
1690 Some(TypeBinding {
1691 name: cx
1692 .tcx
1693 .associated_item(proj.projection_ty.item_def_id)
1694 .ident
1695 .name
1696 .clean(cx),
1697 kind: TypeBindingKind::Equality {
1698 ty: proj.ty.clean(cx),
1699 },
1700 })
1701 } else {
1702 None
1703 }
1704 } else {
1705 None
1706 }
1707 })
1708 .collect();
1709
ba9703b0 1710 Some((trait_ref, &bounds[..]).clean(cx))
dfeec247
XL
1711 })
1712 .collect::<Vec<_>>();
0531ce1d
XL
1713 bounds.extend(regions);
1714 if !has_sized && !bounds.is_empty() {
8faf50e0 1715 bounds.insert(0, GenericBound::maybe_sized(cx));
0531ce1d
XL
1716 }
1717 ImplTrait(bounds)
5bcae85e
SL
1718 }
1719
b7449926 1720 ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton)
1a4d82fc 1721
a1dfa0c6
XL
1722 ty::Bound(..) => panic!("Bound"),
1723 ty::Placeholder(..) => panic!("Placeholder"),
0bf4aa26 1724 ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"),
b7449926
XL
1725 ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
1726 ty::Infer(..) => panic!("Infer"),
1727 ty::Error => panic!("Error"),
1a4d82fc
JJ
1728 }
1729 }
1730}
1731
532ac7d7
XL
1732impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
1733 fn clean(&self, cx: &DocContext<'_>) -> Constant {
1734 Constant {
1735 type_: self.ty.clean(cx),
dc9dc135 1736 expr: format!("{}", self),
dfeec247
XL
1737 value: None,
1738 is_literal: false,
532ac7d7
XL
1739 }
1740 }
1741}
1742
dfeec247 1743impl Clean<Item> for hir::StructField<'_> {
532ac7d7 1744 fn clean(&self, cx: &DocContext<'_>) -> Item {
416331ca 1745 let local_did = cx.tcx.hir().local_def_id(self.hir_id);
532ac7d7 1746
1a4d82fc 1747 Item {
94b46f34 1748 name: Some(self.ident.name).clean(cx),
54a0048b 1749 attrs: self.attrs.clean(cx),
1a4d82fc 1750 source: self.span.clean(cx),
54a0048b 1751 visibility: self.vis.clean(cx),
532ac7d7
XL
1752 stability: get_stability(cx, local_did),
1753 deprecation: get_deprecation(cx, local_did),
1754 def_id: local_did,
54a0048b 1755 inner: StructFieldItem(self.ty.clean(cx)),
1a4d82fc
JJ
1756 }
1757 }
1758}
1759
dc9dc135 1760impl Clean<Item> for ty::FieldDef {
532ac7d7 1761 fn clean(&self, cx: &DocContext<'_>) -> Item {
1a4d82fc 1762 Item {
94b46f34 1763 name: Some(self.ident.name).clean(cx),
476ff2be
SL
1764 attrs: cx.tcx.get_attrs(self.did).clean(cx),
1765 source: cx.tcx.def_span(self.did).clean(cx),
54a0048b 1766 visibility: self.vis.clean(cx),
e9174d1e 1767 stability: get_stability(cx, self.did),
9cc50fc6 1768 deprecation: get_deprecation(cx, self.did),
e9174d1e 1769 def_id: self.did,
7cac9316 1770 inner: StructFieldItem(cx.tcx.type_of(self.did).clean(cx)),
1a4d82fc
JJ
1771 }
1772 }
1773}
1774
dfeec247 1775impl Clean<Visibility> for hir::Visibility<'_> {
e74abb32
XL
1776 fn clean(&self, cx: &DocContext<'_>) -> Visibility {
1777 match self.node {
8faf50e0
XL
1778 hir::VisibilityKind::Public => Visibility::Public,
1779 hir::VisibilityKind::Inherited => Visibility::Inherited,
1780 hir::VisibilityKind::Crate(_) => Visibility::Crate,
1781 hir::VisibilityKind::Restricted { ref path, .. } => {
94b46f34 1782 let path = path.clean(cx);
48663c56 1783 let did = register_res(cx, path.res);
94b46f34
XL
1784 Visibility::Restricted(did, path)
1785 }
e74abb32 1786 }
54a0048b
SL
1787 }
1788}
1789
e74abb32
XL
1790impl Clean<Visibility> for ty::Visibility {
1791 fn clean(&self, _: &DocContext<'_>) -> Visibility {
1792 if *self == ty::Visibility::Public { Public } else { Inherited }
1a4d82fc
JJ
1793 }
1794}
1795
dc9dc135 1796impl Clean<Item> for doctree::Struct<'_> {
532ac7d7 1797 fn clean(&self, cx: &DocContext<'_>) -> Item {
0bf4aa26
XL
1798 Item {
1799 name: Some(self.name.clean(cx)),
1a4d82fc
JJ
1800 attrs: self.attrs.clean(cx),
1801 source: self.whence.clean(cx),
416331ca 1802 def_id: cx.tcx.hir().local_def_id(self.id),
1a4d82fc 1803 visibility: self.vis.clean(cx),
416331ca
XL
1804 stability: cx.stability(self.id).clean(cx),
1805 deprecation: cx.deprecation(self.id).clean(cx),
1a4d82fc
JJ
1806 inner: StructItem(Struct {
1807 struct_type: self.struct_type,
1808 generics: self.generics.clean(cx),
1809 fields: self.fields.clean(cx),
1810 fields_stripped: false,
1811 }),
0bf4aa26 1812 }
1a4d82fc
JJ
1813 }
1814}
1815
dc9dc135 1816impl Clean<Item> for doctree::Union<'_> {
532ac7d7 1817 fn clean(&self, cx: &DocContext<'_>) -> Item {
0bf4aa26
XL
1818 Item {
1819 name: Some(self.name.clean(cx)),
9e0c209e
SL
1820 attrs: self.attrs.clean(cx),
1821 source: self.whence.clean(cx),
416331ca 1822 def_id: cx.tcx.hir().local_def_id(self.id),
9e0c209e 1823 visibility: self.vis.clean(cx),
416331ca
XL
1824 stability: cx.stability(self.id).clean(cx),
1825 deprecation: cx.deprecation(self.id).clean(cx),
9e0c209e
SL
1826 inner: UnionItem(Union {
1827 struct_type: self.struct_type,
1828 generics: self.generics.clean(cx),
1829 fields: self.fields.clean(cx),
1830 fields_stripped: false,
1831 }),
0bf4aa26 1832 }
9e0c209e
SL
1833 }
1834}
1835
dfeec247 1836impl Clean<VariantStruct> for rustc_hir::VariantData<'_> {
532ac7d7 1837 fn clean(&self, cx: &DocContext<'_>) -> VariantStruct {
1a4d82fc
JJ
1838 VariantStruct {
1839 struct_type: doctree::struct_type_from_def(self),
b039eaaf 1840 fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
1a4d82fc
JJ
1841 fields_stripped: false,
1842 }
1843 }
1844}
1845
dc9dc135 1846impl Clean<Item> for doctree::Enum<'_> {
532ac7d7 1847 fn clean(&self, cx: &DocContext<'_>) -> Item {
0bf4aa26
XL
1848 Item {
1849 name: Some(self.name.clean(cx)),
1a4d82fc
JJ
1850 attrs: self.attrs.clean(cx),
1851 source: self.whence.clean(cx),
416331ca 1852 def_id: cx.tcx.hir().local_def_id(self.id),
1a4d82fc 1853 visibility: self.vis.clean(cx),
416331ca
XL
1854 stability: cx.stability(self.id).clean(cx),
1855 deprecation: cx.deprecation(self.id).clean(cx),
1a4d82fc 1856 inner: EnumItem(Enum {
a1dfa0c6 1857 variants: self.variants.iter().map(|v| v.clean(cx)).collect(),
1a4d82fc
JJ
1858 generics: self.generics.clean(cx),
1859 variants_stripped: false,
1860 }),
0bf4aa26 1861 }
1a4d82fc
JJ
1862 }
1863}
1864
dc9dc135 1865impl Clean<Item> for doctree::Variant<'_> {
532ac7d7 1866 fn clean(&self, cx: &DocContext<'_>) -> Item {
1a4d82fc
JJ
1867 Item {
1868 name: Some(self.name.clean(cx)),
1869 attrs: self.attrs.clean(cx),
1870 source: self.whence.clean(cx),
e74abb32 1871 visibility: Inherited,
416331ca
XL
1872 stability: cx.stability(self.id).clean(cx),
1873 deprecation: cx.deprecation(self.id).clean(cx),
1874 def_id: cx.tcx.hir().local_def_id(self.id),
dfeec247 1875 inner: VariantItem(Variant { kind: self.def.clean(cx) }),
1a4d82fc
JJ
1876 }
1877 }
1878}
1879
dc9dc135 1880impl Clean<Item> for ty::VariantDef {
532ac7d7 1881 fn clean(&self, cx: &DocContext<'_>) -> Item {
c30ab7b3
SL
1882 let kind = match self.ctor_kind {
1883 CtorKind::Const => VariantKind::CLike,
dfeec247
XL
1884 CtorKind::Fn => VariantKind::Tuple(
1885 self.fields.iter().map(|f| cx.tcx.type_of(f.did).clean(cx)).collect(),
1886 ),
1887 CtorKind::Fictive => VariantKind::Struct(VariantStruct {
1888 struct_type: doctree::Plain,
1889 fields_stripped: false,
1890 fields: self
1891 .fields
1892 .iter()
1893 .map(|field| Item {
1894 source: cx.tcx.def_span(field.did).clean(cx),
1895 name: Some(field.ident.name.clean(cx)),
1896 attrs: cx.tcx.get_attrs(field.did).clean(cx),
1897 visibility: field.vis.clean(cx),
1898 def_id: field.did,
1899 stability: get_stability(cx, field.did),
1900 deprecation: get_deprecation(cx, field.did),
1901 inner: StructFieldItem(cx.tcx.type_of(field.did).clean(cx)),
1902 })
1903 .collect(),
1904 }),
1a4d82fc
JJ
1905 };
1906 Item {
0731742a 1907 name: Some(self.ident.clean(cx)),
416331ca 1908 attrs: inline::load_attrs(cx, self.def_id).clean(cx),
532ac7d7 1909 source: cx.tcx.def_span(self.def_id).clean(cx),
e74abb32 1910 visibility: Inherited,
532ac7d7 1911 def_id: self.def_id,
a1dfa0c6 1912 inner: VariantItem(Variant { kind }),
532ac7d7
XL
1913 stability: get_stability(cx, self.def_id),
1914 deprecation: get_deprecation(cx, self.def_id),
1a4d82fc
JJ
1915 }
1916 }
1917}
1918
dfeec247 1919impl Clean<VariantKind> for hir::VariantData<'_> {
532ac7d7
XL
1920 fn clean(&self, cx: &DocContext<'_>) -> VariantKind {
1921 match self {
1922 hir::VariantData::Struct(..) => VariantKind::Struct(self.clean(cx)),
dfeec247
XL
1923 hir::VariantData::Tuple(..) => {
1924 VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect())
1925 }
532ac7d7 1926 hir::VariantData::Unit(..) => VariantKind::CLike,
c30ab7b3 1927 }
1a4d82fc
JJ
1928 }
1929}
1930
dfeec247 1931impl Clean<Span> for rustc_span::Span {
532ac7d7 1932 fn clean(&self, cx: &DocContext<'_>) -> Span {
8faf50e0 1933 if self.is_dummy() {
c1a9b12d
SL
1934 return Span::empty();
1935 }
1936
74b04a01
XL
1937 let sm = cx.sess().source_map();
1938 let filename = sm.span_to_filename(*self);
1939 let lo = sm.lookup_char_pos(self.lo());
1940 let hi = sm.lookup_char_pos(self.hi());
1a4d82fc 1941 Span {
ff7c6d11 1942 filename,
ba9703b0 1943 cnum: lo.file.cnum,
1a4d82fc 1944 loline: lo.line,
85aaf69f 1945 locol: lo.col.to_usize(),
1a4d82fc 1946 hiline: hi.line,
85aaf69f 1947 hicol: hi.col.to_usize(),
48663c56 1948 original: *self,
1a4d82fc
JJ
1949 }
1950 }
1951}
1952
dfeec247 1953impl Clean<Path> for hir::Path<'_> {
532ac7d7 1954 fn clean(&self, cx: &DocContext<'_>) -> Path {
1a4d82fc 1955 Path {
32a655c1 1956 global: self.is_global(),
48663c56 1957 res: self.res,
32a655c1 1958 segments: if self.is_global() { &self.segments[1..] } else { &self.segments }.clean(cx),
1a4d82fc
JJ
1959 }
1960 }
1961}
1962
dfeec247 1963impl Clean<GenericArgs> for hir::GenericArgs<'_> {
532ac7d7 1964 fn clean(&self, cx: &DocContext<'_>) -> GenericArgs {
3b2f2976 1965 if self.parenthesized {
dc9dc135 1966 let output = self.bindings[0].ty().clean(cx);
8faf50e0 1967 GenericArgs::Parenthesized {
3b2f2976 1968 inputs: self.inputs().clean(cx),
dfeec247 1969 output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None },
1a4d82fc 1970 }
3b2f2976 1971 } else {
532ac7d7
XL
1972 let elide_lifetimes = self.args.iter().all(|arg| match arg {
1973 hir::GenericArg::Lifetime(lt) => lt.is_elided(),
1974 _ => true,
1975 });
8faf50e0 1976 GenericArgs::AngleBracketed {
dfeec247
XL
1977 args: self
1978 .args
1979 .iter()
1980 .filter_map(|arg| match arg {
1981 hir::GenericArg::Lifetime(lt) if !elide_lifetimes => {
1982 Some(GenericArg::Lifetime(lt.clean(cx)))
1983 }
1984 hir::GenericArg::Lifetime(_) => None,
1985 hir::GenericArg::Type(ty) => Some(GenericArg::Type(ty.clean(cx))),
1986 hir::GenericArg::Const(ct) => Some(GenericArg::Const(ct.clean(cx))),
1987 })
1988 .collect(),
3b2f2976 1989 bindings: self.bindings.clean(cx),
1a4d82fc
JJ
1990 }
1991 }
1992 }
1993}
1994
dfeec247 1995impl Clean<PathSegment> for hir::PathSegment<'_> {
532ac7d7 1996 fn clean(&self, cx: &DocContext<'_>) -> PathSegment {
dfeec247 1997 PathSegment { name: self.ident.name.clean(cx), args: self.generic_args().clean(cx) }
1a4d82fc
JJ
1998 }
1999}
2000
0731742a
XL
2001impl Clean<String> for Ident {
2002 #[inline]
532ac7d7 2003 fn clean(&self, cx: &DocContext<'_>) -> String {
0731742a
XL
2004 self.name.clean(cx)
2005 }
2006}
2007
1a4d82fc 2008impl Clean<String> for ast::Name {
0731742a 2009 #[inline]
532ac7d7 2010 fn clean(&self, _: &DocContext<'_>) -> String {
c1a9b12d 2011 self.to_string()
1a4d82fc
JJ
2012 }
2013}
2014
dc9dc135 2015impl Clean<Item> for doctree::Typedef<'_> {
532ac7d7 2016 fn clean(&self, cx: &DocContext<'_>) -> Item {
dfeec247
XL
2017 let type_ = self.ty.clean(cx);
2018 let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
1a4d82fc
JJ
2019 Item {
2020 name: Some(self.name.clean(cx)),
2021 attrs: self.attrs.clean(cx),
2022 source: self.whence.clean(cx),
416331ca 2023 def_id: cx.tcx.hir().local_def_id(self.id),
1a4d82fc 2024 visibility: self.vis.clean(cx),
416331ca
XL
2025 stability: cx.stability(self.id).clean(cx),
2026 deprecation: cx.deprecation(self.id).clean(cx),
dfeec247 2027 inner: TypedefItem(Typedef { type_, generics: self.gen.clean(cx), item_type }, false),
1a4d82fc
JJ
2028 }
2029 }
2030}
2031
416331ca 2032impl Clean<Item> for doctree::OpaqueTy<'_> {
532ac7d7 2033 fn clean(&self, cx: &DocContext<'_>) -> Item {
8faf50e0
XL
2034 Item {
2035 name: Some(self.name.clean(cx)),
2036 attrs: self.attrs.clean(cx),
2037 source: self.whence.clean(cx),
416331ca 2038 def_id: cx.tcx.hir().local_def_id(self.id),
8faf50e0 2039 visibility: self.vis.clean(cx),
416331ca
XL
2040 stability: cx.stability(self.id).clean(cx),
2041 deprecation: cx.deprecation(self.id).clean(cx),
dfeec247
XL
2042 inner: OpaqueTyItem(
2043 OpaqueTy {
2044 bounds: self.opaque_ty.bounds.clean(cx),
2045 generics: self.opaque_ty.generics.clean(cx),
2046 },
2047 false,
2048 ),
8faf50e0
XL
2049 }
2050 }
2051}
2052
dfeec247 2053impl Clean<BareFunctionDecl> for hir::BareFnTy<'_> {
532ac7d7 2054 fn clean(&self, cx: &DocContext<'_>) -> BareFunctionDecl {
0531ce1d 2055 let (generic_params, decl) = enter_impl_trait(cx, || {
e1599b0c 2056 (self.generic_params.clean(cx), (&*self.decl, &self.param_names[..]).clean(cx))
0531ce1d 2057 });
dfeec247 2058 BareFunctionDecl { unsafety: self.unsafety, abi: self.abi, decl, generic_params }
1a4d82fc
JJ
2059 }
2060}
2061
dc9dc135 2062impl Clean<Item> for doctree::Static<'_> {
532ac7d7 2063 fn clean(&self, cx: &DocContext<'_>) -> Item {
1a4d82fc
JJ
2064 debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
2065 Item {
2066 name: Some(self.name.clean(cx)),
2067 attrs: self.attrs.clean(cx),
2068 source: self.whence.clean(cx),
416331ca 2069 def_id: cx.tcx.hir().local_def_id(self.id),
1a4d82fc 2070 visibility: self.vis.clean(cx),
416331ca
XL
2071 stability: cx.stability(self.id).clean(cx),
2072 deprecation: cx.deprecation(self.id).clean(cx),
1a4d82fc
JJ
2073 inner: StaticItem(Static {
2074 type_: self.type_.clean(cx),
dfeec247 2075 mutability: self.mutability,
32a655c1 2076 expr: print_const_expr(cx, self.expr),
1a4d82fc
JJ
2077 }),
2078 }
2079 }
2080}
2081
dc9dc135 2082impl Clean<Item> for doctree::Constant<'_> {
532ac7d7 2083 fn clean(&self, cx: &DocContext<'_>) -> Item {
dfeec247
XL
2084 let def_id = cx.tcx.hir().local_def_id(self.id);
2085
1a4d82fc
JJ
2086 Item {
2087 name: Some(self.name.clean(cx)),
2088 attrs: self.attrs.clean(cx),
2089 source: self.whence.clean(cx),
dfeec247 2090 def_id,
1a4d82fc 2091 visibility: self.vis.clean(cx),
416331ca
XL
2092 stability: cx.stability(self.id).clean(cx),
2093 deprecation: cx.deprecation(self.id).clean(cx),
1a4d82fc
JJ
2094 inner: ConstantItem(Constant {
2095 type_: self.type_.clean(cx),
32a655c1 2096 expr: print_const_expr(cx, self.expr),
dfeec247
XL
2097 value: print_evaluated_const(cx, def_id),
2098 is_literal: is_literal_expr(cx, self.expr.hir_id),
1a4d82fc
JJ
2099 }),
2100 }
2101 }
2102}
2103
e74abb32 2104impl Clean<ImplPolarity> for ty::ImplPolarity {
532ac7d7 2105 fn clean(&self, _: &DocContext<'_>) -> ImplPolarity {
85aaf69f 2106 match self {
e74abb32
XL
2107 &ty::ImplPolarity::Positive |
2108 // FIXME: do we want to do something else here?
2109 &ty::ImplPolarity::Reservation => ImplPolarity::Positive,
2110 &ty::ImplPolarity::Negative => ImplPolarity::Negative,
85aaf69f
SL
2111 }
2112 }
2113}
2114
dc9dc135 2115impl Clean<Vec<Item>> for doctree::Impl<'_> {
532ac7d7 2116 fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
d9579d0f
AL
2117 let mut ret = Vec::new();
2118 let trait_ = self.trait_.clean(cx);
dc9dc135 2119 let items = self.items.iter().map(|ii| ii.clean(cx)).collect::<Vec<_>>();
e74abb32 2120 let def_id = cx.tcx.hir().local_def_id(self.id);
d9579d0f
AL
2121
2122 // If this impl block is an implementation of the Deref trait, then we
2123 // need to try inlining the target's inherent impl blocks as well.
ea8adc8c 2124 if trait_.def_id() == cx.tcx.lang_items().deref_trait() {
54a0048b 2125 build_deref_target_impls(cx, &items, &mut ret);
d9579d0f
AL
2126 }
2127
dfeec247
XL
2128 let provided: FxHashSet<String> = trait_
2129 .def_id()
2130 .map(|did| {
74b04a01 2131 cx.tcx.provided_trait_methods(did).map(|meth| meth.ident.to_string()).collect()
dfeec247
XL
2132 })
2133 .unwrap_or_default();
54a0048b 2134
dfeec247
XL
2135 let for_ = self.for_.clean(cx);
2136 let type_alias = for_.def_id().and_then(|did| match cx.tcx.def_kind(did) {
2137 Some(DefKind::TyAlias) => Some(cx.tcx.type_of(did).clean(cx)),
2138 _ => None,
2139 });
2140 let make_item = |trait_: Option<Type>, for_: Type, items: Vec<Item>| Item {
1a4d82fc
JJ
2141 name: None,
2142 attrs: self.attrs.clean(cx),
2143 source: self.whence.clean(cx),
e74abb32 2144 def_id,
1a4d82fc 2145 visibility: self.vis.clean(cx),
416331ca
XL
2146 stability: cx.stability(self.id).clean(cx),
2147 deprecation: cx.deprecation(self.id).clean(cx),
1a4d82fc 2148 inner: ImplItem(Impl {
c34b1796 2149 unsafety: self.unsafety,
1a4d82fc 2150 generics: self.generics.clean(cx),
dfeec247 2151 provided_trait_methods: provided.clone(),
3b2f2976 2152 trait_,
dfeec247 2153 for_,
3b2f2976 2154 items,
e74abb32 2155 polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)),
0531ce1d 2156 synthetic: false,
8faf50e0 2157 blanket_impl: None,
dfeec247
XL
2158 }),
2159 };
2160 if let Some(type_alias) = type_alias {
2161 ret.push(make_item(trait_.clone(), type_alias, items.clone()));
2162 }
2163 ret.push(make_item(trait_, for_, items));
54a0048b 2164 ret
d9579d0f
AL
2165 }
2166}
2167
dc9dc135 2168impl Clean<Vec<Item>> for doctree::ExternCrate<'_> {
532ac7d7 2169 fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
dfeec247
XL
2170 let please_inline = self.vis.node.is_pub()
2171 && self.attrs.iter().any(|a| {
2172 a.check_name(sym::doc)
2173 && match a.meta_item_list() {
2174 Some(l) => attr::list_contains_name(&l, sym::inline),
2175 None => false,
2176 }
2177 });
0731742a
XL
2178
2179 if please_inline {
2180 let mut visited = FxHashSet::default();
2181
dfeec247 2182 let res = Res::Def(DefKind::Mod, DefId { krate: self.cnum, index: CRATE_DEF_INDEX });
0731742a 2183
ba9703b0
XL
2184 if let Some(items) =
2185 inline::try_inline(cx, res, self.name, Some(self.attrs), &mut visited)
2186 {
0731742a
XL
2187 return items;
2188 }
2189 }
2190
2191 vec![Item {
85aaf69f
SL
2192 name: None,
2193 attrs: self.attrs.clean(cx),
2194 source: self.whence.clean(cx),
a7813a04 2195 def_id: DefId { krate: self.cnum, index: CRATE_DEF_INDEX },
85aaf69f
SL
2196 visibility: self.vis.clean(cx),
2197 stability: None,
9cc50fc6 2198 deprecation: None,
dfeec247 2199 inner: ExternCrateItem(self.name.clean(cx), self.path.clone()),
0731742a 2200 }]
85aaf69f 2201 }
1a4d82fc
JJ
2202}
2203
dc9dc135 2204impl Clean<Vec<Item>> for doctree::Import<'_> {
532ac7d7 2205 fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
1a4d82fc
JJ
2206 // We consider inlining the documentation of `pub use` statements, but we
2207 // forcefully don't inline if this is not public or if the
2208 // #[doc(no_inline)] attribute is present.
3157f602 2209 // Don't inline doc(hidden) imports so they can be stripped at a later stage.
dfeec247
XL
2210 let mut denied = !self.vis.node.is_pub()
2211 || self.attrs.iter().any(|a| {
2212 a.check_name(sym::doc)
2213 && match a.meta_item_list() {
2214 Some(l) => {
2215 attr::list_contains_name(&l, sym::no_inline)
2216 || attr::list_contains_name(&l, sym::hidden)
2217 }
2218 None => false,
2219 }
2220 });
13cf67c4
XL
2221 // Also check whether imports were asked to be inlined, in case we're trying to re-export a
2222 // crate in Rust 2018+
48663c56 2223 let please_inline = self.attrs.lists(sym::doc).has_word(sym::inline);
476ff2be
SL
2224 let path = self.path.clean(cx);
2225 let inner = if self.glob {
94b46f34 2226 if !denied {
0bf4aa26 2227 let mut visited = FxHashSet::default();
48663c56 2228 if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) {
94b46f34
XL
2229 return items;
2230 }
2231 }
2232
476ff2be
SL
2233 Import::Glob(resolve_use_source(cx, path))
2234 } else {
2235 let name = self.name;
13cf67c4 2236 if !please_inline {
ba9703b0
XL
2237 if let Res::Def(DefKind::Mod, did) = path.res {
2238 if !did.is_local() && did.index == CRATE_DEF_INDEX {
2239 // if we're `pub use`ing an extern crate root, don't inline it unless we
2240 // were specifically asked for it
2241 denied = true;
13cf67c4 2242 }
13cf67c4
XL
2243 }
2244 }
476ff2be 2245 if !denied {
0bf4aa26 2246 let mut visited = FxHashSet::default();
ba9703b0
XL
2247 if let Some(items) =
2248 inline::try_inline(cx, path.res, name, Some(self.attrs), &mut visited)
2249 {
476ff2be 2250 return items;
85aaf69f 2251 }
1a4d82fc 2252 }
476ff2be 2253 Import::Simple(name.clean(cx), resolve_use_source(cx, path))
85aaf69f 2254 };
8faf50e0 2255
476ff2be 2256 vec![Item {
85aaf69f
SL
2257 name: None,
2258 attrs: self.attrs.clean(cx),
2259 source: self.whence.clean(cx),
ba9703b0 2260 def_id: cx.tcx.hir().local_def_id_from_node_id(ast::CRATE_NODE_ID).to_def_id(),
85aaf69f
SL
2261 visibility: self.vis.clean(cx),
2262 stability: None,
9cc50fc6 2263 deprecation: None,
dfeec247 2264 inner: ImportItem(inner),
476ff2be 2265 }]
1a4d82fc
JJ
2266 }
2267}
2268
dc9dc135 2269impl Clean<Item> for doctree::ForeignItem<'_> {
532ac7d7 2270 fn clean(&self, cx: &DocContext<'_>) -> Item {
dc9dc135 2271 let inner = match self.kind {
8faf50e0 2272 hir::ForeignItemKind::Fn(ref decl, ref names, ref generics) => {
dc9dc135 2273 let abi = cx.tcx.hir().get_foreign_abi(self.id);
dfeec247
XL
2274 let (generics, decl) =
2275 enter_impl_trait(cx, || (generics.clean(cx), (&**decl, &names[..]).clean(cx)));
532ac7d7 2276 let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
1a4d82fc 2277 ForeignFunctionItem(Function {
0531ce1d
XL
2278 decl,
2279 generics,
8faf50e0
XL
2280 header: hir::FnHeader {
2281 unsafety: hir::Unsafety::Unsafe,
dc9dc135 2282 abi,
8faf50e0
XL
2283 constness: hir::Constness::NotConst,
2284 asyncness: hir::IsAsync::NotAsync,
2285 },
532ac7d7
XL
2286 all_types,
2287 ret_types,
1a4d82fc
JJ
2288 })
2289 }
dfeec247
XL
2290 hir::ForeignItemKind::Static(ref ty, mutbl) => ForeignStaticItem(Static {
2291 type_: ty.clean(cx),
2292 mutability: *mutbl,
2293 expr: String::new(),
2294 }),
2295 hir::ForeignItemKind::Type => ForeignTypeItem,
1a4d82fc 2296 };
8faf50e0 2297
1a4d82fc 2298 Item {
dc9dc135 2299 name: Some(self.name.clean(cx)),
1a4d82fc 2300 attrs: self.attrs.clean(cx),
dc9dc135 2301 source: self.whence.clean(cx),
416331ca 2302 def_id: cx.tcx.hir().local_def_id(self.id),
1a4d82fc 2303 visibility: self.vis.clean(cx),
416331ca
XL
2304 stability: cx.stability(self.id).clean(cx),
2305 deprecation: cx.deprecation(self.id).clean(cx),
3b2f2976 2306 inner,
1a4d82fc
JJ
2307 }
2308 }
2309}
2310
dc9dc135 2311impl Clean<Item> for doctree::Macro<'_> {
532ac7d7 2312 fn clean(&self, cx: &DocContext<'_>) -> Item {
9e0c209e 2313 let name = self.name.clean(cx);
1a4d82fc 2314 Item {
92a42be0 2315 name: Some(name.clone()),
1a4d82fc
JJ
2316 attrs: self.attrs.clean(cx),
2317 source: self.whence.clean(cx),
e74abb32 2318 visibility: Public,
416331ca
XL
2319 stability: cx.stability(self.hid).clean(cx),
2320 deprecation: cx.deprecation(self.hid).clean(cx),
32a655c1 2321 def_id: self.def_id,
1a4d82fc 2322 inner: MacroItem(Macro {
dfeec247
XL
2323 source: format!(
2324 "macro_rules! {} {{\n{}}}",
2325 name,
2326 self.matchers
2327 .iter()
2328 .map(|span| { format!(" {} => {{ ... }};\n", span.to_src(cx)) })
2329 .collect::<String>()
2330 ),
d9579d0f 2331 imported_from: self.imported_from.clean(cx),
1a4d82fc
JJ
2332 }),
2333 }
2334 }
2335}
2336
dc9dc135 2337impl Clean<Item> for doctree::ProcMacro<'_> {
532ac7d7 2338 fn clean(&self, cx: &DocContext<'_>) -> Item {
0bf4aa26
XL
2339 Item {
2340 name: Some(self.name.clean(cx)),
2341 attrs: self.attrs.clean(cx),
2342 source: self.whence.clean(cx),
e74abb32 2343 visibility: Public,
416331ca
XL
2344 stability: cx.stability(self.id).clean(cx),
2345 deprecation: cx.deprecation(self.id).clean(cx),
2346 def_id: cx.tcx.hir().local_def_id(self.id),
dfeec247 2347 inner: ProcMacroItem(ProcMacro { kind: self.kind, helpers: self.helpers.clean(cx) }),
0bf4aa26
XL
2348 }
2349 }
2350}
2351
1a4d82fc 2352impl Clean<Stability> for attr::Stability {
532ac7d7 2353 fn clean(&self, _: &DocContext<'_>) -> Stability {
1a4d82fc 2354 Stability {
b039eaaf 2355 level: stability::StabilityLevel::from_attr_level(&self.level),
0731742a 2356 feature: Some(self.feature.to_string()).filter(|f| !f.is_empty()),
b039eaaf 2357 since: match self.level {
dfeec247 2358 attr::Stable { ref since } => since.to_string(),
b7449926 2359 _ => String::new(),
b039eaaf 2360 },
dfeec247
XL
2361 deprecation: self.rustc_depr.as_ref().map(|d| Deprecation {
2362 note: Some(d.reason.to_string()).filter(|r| !r.is_empty()),
2363 since: Some(d.since.to_string()).filter(|d| !d.is_empty()),
0731742a 2364 }),
476ff2be 2365 unstable_reason: match self.level {
0731742a
XL
2366 attr::Unstable { reason: Some(ref reason), .. } => Some(reason.to_string()),
2367 _ => None,
b039eaaf
SL
2368 },
2369 issue: match self.level {
dfeec247 2370 attr::Unstable { issue, .. } => issue,
b039eaaf 2371 _ => None,
dfeec247 2372 },
1a4d82fc
JJ
2373 }
2374 }
2375}
2376
9cc50fc6 2377impl Clean<Deprecation> for attr::Deprecation {
532ac7d7 2378 fn clean(&self, _: &DocContext<'_>) -> Deprecation {
9cc50fc6 2379 Deprecation {
0731742a
XL
2380 since: self.since.map(|s| s.to_string()).filter(|s| !s.is_empty()),
2381 note: self.note.map(|n| n.to_string()).filter(|n| !n.is_empty()),
9cc50fc6
SL
2382 }
2383 }
2384}
2385
dfeec247 2386impl Clean<TypeBinding> for hir::TypeBinding<'_> {
532ac7d7 2387 fn clean(&self, cx: &DocContext<'_>) -> TypeBinding {
dfeec247 2388 TypeBinding { name: self.ident.name.clean(cx), kind: self.kind.clean(cx) }
dc9dc135
XL
2389 }
2390}
2391
dfeec247 2392impl Clean<TypeBindingKind> for hir::TypeBindingKind<'_> {
dc9dc135
XL
2393 fn clean(&self, cx: &DocContext<'_>) -> TypeBindingKind {
2394 match *self {
dfeec247
XL
2395 hir::TypeBindingKind::Equality { ref ty } => {
2396 TypeBindingKind::Equality { ty: ty.clean(cx) }
2397 }
74b04a01
XL
2398 hir::TypeBindingKind::Constraint { ref bounds } => {
2399 TypeBindingKind::Constraint { bounds: bounds.iter().map(|b| b.clean(cx)).collect() }
2400 }
1a4d82fc
JJ
2401 }
2402 }
2403}
0531ce1d 2404
0531ce1d 2405enum SimpleBound {
8faf50e0
XL
2406 TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier),
2407 Outlives(Lifetime),
0531ce1d
XL
2408}
2409
8faf50e0
XL
2410impl From<GenericBound> for SimpleBound {
2411 fn from(bound: GenericBound) -> Self {
0531ce1d 2412 match bound.clone() {
8faf50e0
XL
2413 GenericBound::Outlives(l) => SimpleBound::Outlives(l),
2414 GenericBound::TraitBound(t, mod_) => match t.trait_ {
dfeec247
XL
2415 Type::ResolvedPath { path, param_names, .. } => SimpleBound::TraitBound(
2416 path.segments,
ba9703b0
XL
2417 param_names.map_or_else(Vec::new, |v| {
2418 v.iter().map(|p| SimpleBound::from(p.clone())).collect()
2419 }),
dfeec247
XL
2420 t.generic_params,
2421 mod_,
2422 ),
0531ce1d 2423 _ => panic!("Unexpected bound {:?}", bound),
dfeec247 2424 },
0531ce1d
XL
2425 }
2426 }
2427}