]> git.proxmox.com Git - rustc.git/blob - src/librustdoc/clean/mod.rs
New upstream version 1.35.0+dfsg1
[rustc.git] / src / librustdoc / clean / mod.rs
1 //! This module contains the "cleaned" pieces of the AST, and the functions
2 //! that clean them.
3
4 pub mod inline;
5 pub mod cfg;
6 mod simplify;
7 mod auto_trait;
8 mod blanket_impl;
9 pub mod def_ctor;
10
11 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
12 use rustc_data_structures::sync::Lrc;
13 use rustc_target::spec::abi::Abi;
14 use rustc_typeck::hir_ty_to_ty;
15 use rustc::infer::region_constraints::{RegionConstraintData, Constraint};
16 use rustc::middle::resolve_lifetime as rl;
17 use rustc::middle::lang_items;
18 use rustc::middle::stability;
19 use rustc::mir::interpret::{GlobalId, ConstValue};
20 use rustc::hir::{self, HirVec};
21 use rustc::hir::def::{self, Def, CtorKind};
22 use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
23 use rustc::hir::map::DisambiguatedDefPathData;
24 use rustc::ty::subst::{Kind, InternalSubsts, SubstsRef, UnpackedKind};
25 use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind};
26 use rustc::ty::fold::TypeFolder;
27 use rustc::ty::layout::VariantIdx;
28 use rustc::util::nodemap::{FxHashMap, FxHashSet};
29 use syntax::ast::{self, AttrStyle, Ident};
30 use syntax::attr;
31 use syntax::ext::base::MacroKind;
32 use syntax::source_map::{dummy_spanned, Spanned};
33 use syntax::ptr::P;
34 use syntax::symbol::keywords::{self, Keyword};
35 use syntax::symbol::InternedString;
36 use syntax_pos::{self, DUMMY_SP, Pos, FileName};
37
38 use std::collections::hash_map::Entry;
39 use std::fmt;
40 use std::hash::{Hash, Hasher};
41 use std::default::Default;
42 use std::{mem, slice, vec};
43 use std::iter::{FromIterator, once};
44 use std::rc::Rc;
45 use std::str::FromStr;
46 use std::cell::RefCell;
47 use std::sync::Arc;
48 use std::u32;
49
50 use parking_lot::ReentrantMutex;
51
52 use crate::core::{self, DocContext};
53 use crate::doctree;
54 use crate::visit_ast;
55 use crate::html::render::{cache, ExternalLocation};
56 use crate::html::item_type::ItemType;
57
58
59 use self::cfg::Cfg;
60 use self::auto_trait::AutoTraitFinder;
61 use self::blanket_impl::BlanketImplFinder;
62
63 pub use self::Type::*;
64 pub use self::Mutability::*;
65 pub use self::ItemEnum::*;
66 pub use self::SelfTy::*;
67 pub use self::FunctionRetTy::*;
68 pub use self::Visibility::{Public, Inherited};
69
70 thread_local!(pub static MAX_DEF_ID: RefCell<FxHashMap<CrateNum, DefId>> = Default::default());
71
72 const FN_OUTPUT_NAME: &'static str = "Output";
73
74 // extract the stability index for a node from tcx, if possible
75 fn get_stability(cx: &DocContext<'_>, def_id: DefId) -> Option<Stability> {
76 cx.tcx.lookup_stability(def_id).clean(cx)
77 }
78
79 fn get_deprecation(cx: &DocContext<'_>, def_id: DefId) -> Option<Deprecation> {
80 cx.tcx.lookup_deprecation(def_id).clean(cx)
81 }
82
83 pub trait Clean<T> {
84 fn clean(&self, cx: &DocContext<'_>) -> T;
85 }
86
87 impl<T: Clean<U>, U> Clean<Vec<U>> for [T] {
88 fn clean(&self, cx: &DocContext<'_>) -> Vec<U> {
89 self.iter().map(|x| x.clean(cx)).collect()
90 }
91 }
92
93 impl<T: Clean<U>, U, V: Idx> Clean<IndexVec<V, U>> for IndexVec<V, T> {
94 fn clean(&self, cx: &DocContext<'_>) -> IndexVec<V, U> {
95 self.iter().map(|x| x.clean(cx)).collect()
96 }
97 }
98
99 impl<T: Clean<U>, U> Clean<U> for P<T> {
100 fn clean(&self, cx: &DocContext<'_>) -> U {
101 (**self).clean(cx)
102 }
103 }
104
105 impl<T: Clean<U>, U> Clean<U> for Rc<T> {
106 fn clean(&self, cx: &DocContext<'_>) -> U {
107 (**self).clean(cx)
108 }
109 }
110
111 impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
112 fn clean(&self, cx: &DocContext<'_>) -> Option<U> {
113 self.as_ref().map(|v| v.clean(cx))
114 }
115 }
116
117 impl<T, U> Clean<U> for ty::Binder<T> where T: Clean<U> {
118 fn clean(&self, cx: &DocContext<'_>) -> U {
119 self.skip_binder().clean(cx)
120 }
121 }
122
123 impl<T: Clean<U>, U> Clean<Vec<U>> for P<[T]> {
124 fn clean(&self, cx: &DocContext<'_>) -> Vec<U> {
125 self.iter().map(|x| x.clean(cx)).collect()
126 }
127 }
128
129 #[derive(Clone, Debug)]
130 pub struct Crate {
131 pub name: String,
132 pub version: Option<String>,
133 pub src: FileName,
134 pub module: Option<Item>,
135 pub externs: Vec<(CrateNum, ExternalCrate)>,
136 pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
137 // These are later on moved into `CACHEKEY`, leaving the map empty.
138 // Only here so that they can be filtered through the rustdoc passes.
139 pub external_traits: Arc<ReentrantMutex<RefCell<FxHashMap<DefId, Trait>>>>,
140 pub masked_crates: FxHashSet<CrateNum>,
141 }
142
143 impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
144 fn clean(&self, cx: &DocContext<'_>) -> Crate {
145 use crate::visit_lib::LibEmbargoVisitor;
146
147 {
148 let mut r = cx.renderinfo.borrow_mut();
149 r.deref_trait_did = cx.tcx.lang_items().deref_trait();
150 r.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait();
151 r.owned_box_did = cx.tcx.lang_items().owned_box();
152 }
153
154 let mut externs = Vec::new();
155 for &cnum in cx.tcx.crates().iter() {
156 externs.push((cnum, cnum.clean(cx)));
157 // Analyze doc-reachability for extern items
158 LibEmbargoVisitor::new(cx).visit_lib(cnum);
159 }
160 externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
161
162 // Clean the crate, translating the entire libsyntax AST to one that is
163 // understood by rustdoc.
164 let mut module = self.module.clean(cx);
165 let mut masked_crates = FxHashSet::default();
166
167 match module.inner {
168 ModuleItem(ref module) => {
169 for it in &module.items {
170 // `compiler_builtins` should be masked too, but we can't apply
171 // `#[doc(masked)]` to the injected `extern crate` because it's unstable.
172 if it.is_extern_crate()
173 && (it.attrs.has_doc_flag("masked")
174 || self.cx.tcx.is_compiler_builtins(it.def_id.krate))
175 {
176 masked_crates.insert(it.def_id.krate);
177 }
178 }
179 }
180 _ => unreachable!(),
181 }
182
183 let ExternalCrate { name, src, primitives, keywords, .. } = LOCAL_CRATE.clean(cx);
184 {
185 let m = match module.inner {
186 ModuleItem(ref mut m) => m,
187 _ => unreachable!(),
188 };
189 m.items.extend(primitives.iter().map(|&(def_id, prim, ref attrs)| {
190 Item {
191 source: Span::empty(),
192 name: Some(prim.to_url_str().to_string()),
193 attrs: attrs.clone(),
194 visibility: Some(Public),
195 stability: get_stability(cx, def_id),
196 deprecation: get_deprecation(cx, def_id),
197 def_id,
198 inner: PrimitiveItem(prim),
199 }
200 }));
201 m.items.extend(keywords.into_iter().map(|(def_id, kw, attrs)| {
202 Item {
203 source: Span::empty(),
204 name: Some(kw.clone()),
205 attrs: attrs,
206 visibility: Some(Public),
207 stability: get_stability(cx, def_id),
208 deprecation: get_deprecation(cx, def_id),
209 def_id,
210 inner: KeywordItem(kw),
211 }
212 }));
213 }
214
215 Crate {
216 name,
217 version: None,
218 src,
219 module: Some(module),
220 externs,
221 primitives,
222 external_traits: cx.external_traits.clone(),
223 masked_crates,
224 }
225 }
226 }
227
228 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
229 pub struct ExternalCrate {
230 pub name: String,
231 pub src: FileName,
232 pub attrs: Attributes,
233 pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
234 pub keywords: Vec<(DefId, String, Attributes)>,
235 }
236
237 impl Clean<ExternalCrate> for CrateNum {
238 fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate {
239 let root = DefId { krate: *self, index: CRATE_DEF_INDEX };
240 let krate_span = cx.tcx.def_span(root);
241 let krate_src = cx.sess().source_map().span_to_filename(krate_span);
242
243 // Collect all inner modules which are tagged as implementations of
244 // primitives.
245 //
246 // Note that this loop only searches the top-level items of the crate,
247 // and this is intentional. If we were to search the entire crate for an
248 // item tagged with `#[doc(primitive)]` then we would also have to
249 // search the entirety of external modules for items tagged
250 // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
251 // all that metadata unconditionally).
252 //
253 // In order to keep the metadata load under control, the
254 // `#[doc(primitive)]` feature is explicitly designed to only allow the
255 // primitive tags to show up as the top level items in a crate.
256 //
257 // Also note that this does not attempt to deal with modules tagged
258 // duplicately for the same primitive. This is handled later on when
259 // rendering by delegating everything to a hash map.
260 let as_primitive = |def: Def| {
261 if let Def::Mod(def_id) = def {
262 let attrs = cx.tcx.get_attrs(def_id).clean(cx);
263 let mut prim = None;
264 for attr in attrs.lists("doc") {
265 if let Some(v) = attr.value_str() {
266 if attr.check_name("primitive") {
267 prim = PrimitiveType::from_str(&v.as_str());
268 if prim.is_some() {
269 break;
270 }
271 // FIXME: should warn on unknown primitives?
272 }
273 }
274 }
275 return prim.map(|p| (def_id, p, attrs));
276 }
277 None
278 };
279 let primitives = if root.is_local() {
280 cx.tcx.hir().krate().module.item_ids.iter().filter_map(|&id| {
281 let item = cx.tcx.hir().expect_item_by_hir_id(id.id);
282 match item.node {
283 hir::ItemKind::Mod(_) => {
284 as_primitive(Def::Mod(cx.tcx.hir().local_def_id_from_hir_id(id.id)))
285 }
286 hir::ItemKind::Use(ref path, hir::UseKind::Single)
287 if item.vis.node.is_pub() => {
288 as_primitive(path.def).map(|(_, prim, attrs)| {
289 // Pretend the primitive is local.
290 (cx.tcx.hir().local_def_id_from_hir_id(id.id), prim, attrs)
291 })
292 }
293 _ => None
294 }
295 }).collect()
296 } else {
297 cx.tcx.item_children(root).iter().map(|item| item.def)
298 .filter_map(as_primitive).collect()
299 };
300
301 let as_keyword = |def: Def| {
302 if let Def::Mod(def_id) = def {
303 let attrs = cx.tcx.get_attrs(def_id).clean(cx);
304 let mut keyword = None;
305 for attr in attrs.lists("doc") {
306 if let Some(v) = attr.value_str() {
307 if attr.check_name("keyword") {
308 keyword = Keyword::from_str(&v.as_str()).ok()
309 .map(|x| x.name().to_string());
310 if keyword.is_some() {
311 break
312 }
313 // FIXME: should warn on unknown keywords?
314 }
315 }
316 }
317 return keyword.map(|p| (def_id, p, attrs));
318 }
319 None
320 };
321 let keywords = if root.is_local() {
322 cx.tcx.hir().krate().module.item_ids.iter().filter_map(|&id| {
323 let item = cx.tcx.hir().expect_item_by_hir_id(id.id);
324 match item.node {
325 hir::ItemKind::Mod(_) => {
326 as_keyword(Def::Mod(cx.tcx.hir().local_def_id_from_hir_id(id.id)))
327 }
328 hir::ItemKind::Use(ref path, hir::UseKind::Single)
329 if item.vis.node.is_pub() => {
330 as_keyword(path.def).map(|(_, prim, attrs)| {
331 (cx.tcx.hir().local_def_id_from_hir_id(id.id), prim, attrs)
332 })
333 }
334 _ => None
335 }
336 }).collect()
337 } else {
338 cx.tcx.item_children(root).iter().map(|item| item.def)
339 .filter_map(as_keyword).collect()
340 };
341
342 ExternalCrate {
343 name: cx.tcx.crate_name(*self).to_string(),
344 src: krate_src,
345 attrs: cx.tcx.get_attrs(root).clean(cx),
346 primitives,
347 keywords,
348 }
349 }
350 }
351
352 /// Anything with a source location and set of attributes and, optionally, a
353 /// name. That is, anything that can be documented. This doesn't correspond
354 /// directly to the AST's concept of an item; it's a strict superset.
355 #[derive(Clone, RustcEncodable, RustcDecodable)]
356 pub struct Item {
357 /// Stringified span
358 pub source: Span,
359 /// Not everything has a name. E.g., impls
360 pub name: Option<String>,
361 pub attrs: Attributes,
362 pub inner: ItemEnum,
363 pub visibility: Option<Visibility>,
364 pub def_id: DefId,
365 pub stability: Option<Stability>,
366 pub deprecation: Option<Deprecation>,
367 }
368
369 impl fmt::Debug for Item {
370 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
371
372 let fake = MAX_DEF_ID.with(|m| m.borrow().get(&self.def_id.krate)
373 .map(|id| self.def_id >= *id).unwrap_or(false));
374 let def_id: &dyn fmt::Debug = if fake { &"**FAKE**" } else { &self.def_id };
375
376 fmt.debug_struct("Item")
377 .field("source", &self.source)
378 .field("name", &self.name)
379 .field("attrs", &self.attrs)
380 .field("inner", &self.inner)
381 .field("visibility", &self.visibility)
382 .field("def_id", def_id)
383 .field("stability", &self.stability)
384 .field("deprecation", &self.deprecation)
385 .finish()
386 }
387 }
388
389 impl Item {
390 /// Finds the `doc` attribute as a NameValue and returns the corresponding
391 /// value found.
392 pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
393 self.attrs.doc_value()
394 }
395 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
396 /// with newlines.
397 pub fn collapsed_doc_value(&self) -> Option<String> {
398 self.attrs.collapsed_doc_value()
399 }
400
401 pub fn links(&self) -> Vec<(String, String)> {
402 self.attrs.links(&self.def_id.krate)
403 }
404
405 pub fn is_crate(&self) -> bool {
406 match self.inner {
407 StrippedItem(box ModuleItem(Module { is_crate: true, ..})) |
408 ModuleItem(Module { is_crate: true, ..}) => true,
409 _ => false,
410 }
411 }
412 pub fn is_mod(&self) -> bool {
413 self.type_() == ItemType::Module
414 }
415 pub fn is_trait(&self) -> bool {
416 self.type_() == ItemType::Trait
417 }
418 pub fn is_struct(&self) -> bool {
419 self.type_() == ItemType::Struct
420 }
421 pub fn is_enum(&self) -> bool {
422 self.type_() == ItemType::Enum
423 }
424 pub fn is_variant(&self) -> bool {
425 self.type_() == ItemType::Variant
426 }
427 pub fn is_associated_type(&self) -> bool {
428 self.type_() == ItemType::AssociatedType
429 }
430 pub fn is_associated_const(&self) -> bool {
431 self.type_() == ItemType::AssociatedConst
432 }
433 pub fn is_method(&self) -> bool {
434 self.type_() == ItemType::Method
435 }
436 pub fn is_ty_method(&self) -> bool {
437 self.type_() == ItemType::TyMethod
438 }
439 pub fn is_typedef(&self) -> bool {
440 self.type_() == ItemType::Typedef
441 }
442 pub fn is_primitive(&self) -> bool {
443 self.type_() == ItemType::Primitive
444 }
445 pub fn is_union(&self) -> bool {
446 self.type_() == ItemType::Union
447 }
448 pub fn is_import(&self) -> bool {
449 self.type_() == ItemType::Import
450 }
451 pub fn is_extern_crate(&self) -> bool {
452 self.type_() == ItemType::ExternCrate
453 }
454 pub fn is_keyword(&self) -> bool {
455 self.type_() == ItemType::Keyword
456 }
457
458 pub fn is_stripped(&self) -> bool {
459 match self.inner { StrippedItem(..) => true, _ => false }
460 }
461 pub fn has_stripped_fields(&self) -> Option<bool> {
462 match self.inner {
463 StructItem(ref _struct) => Some(_struct.fields_stripped),
464 UnionItem(ref union) => Some(union.fields_stripped),
465 VariantItem(Variant { kind: VariantKind::Struct(ref vstruct)} ) => {
466 Some(vstruct.fields_stripped)
467 },
468 _ => None,
469 }
470 }
471
472 pub fn stability_class(&self) -> Option<String> {
473 self.stability.as_ref().and_then(|ref s| {
474 let mut classes = Vec::with_capacity(2);
475
476 if s.level == stability::Unstable {
477 classes.push("unstable");
478 }
479
480 if s.deprecation.is_some() {
481 classes.push("deprecated");
482 }
483
484 if classes.len() != 0 {
485 Some(classes.join(" "))
486 } else {
487 None
488 }
489 })
490 }
491
492 pub fn stable_since(&self) -> Option<&str> {
493 self.stability.as_ref().map(|s| &s.since[..])
494 }
495
496 pub fn is_non_exhaustive(&self) -> bool {
497 self.attrs.other_attrs.iter()
498 .any(|a| a.check_name("non_exhaustive"))
499 }
500
501 /// Returns a documentation-level item type from the item.
502 pub fn type_(&self) -> ItemType {
503 ItemType::from(self)
504 }
505
506 /// Returns the info in the item's `#[deprecated]` or `#[rustc_deprecated]` attributes.
507 ///
508 /// If the item is not deprecated, returns `None`.
509 pub fn deprecation(&self) -> Option<&Deprecation> {
510 self.deprecation
511 .as_ref()
512 .or_else(|| self.stability.as_ref().and_then(|s| s.deprecation.as_ref()))
513 }
514 pub fn is_default(&self) -> bool {
515 match self.inner {
516 ItemEnum::MethodItem(ref meth) => {
517 if let Some(defaultness) = meth.defaultness {
518 defaultness.has_value() && !defaultness.is_final()
519 } else {
520 false
521 }
522 }
523 _ => false,
524 }
525 }
526 }
527
528 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
529 pub enum ItemEnum {
530 ExternCrateItem(String, Option<String>),
531 ImportItem(Import),
532 StructItem(Struct),
533 UnionItem(Union),
534 EnumItem(Enum),
535 FunctionItem(Function),
536 ModuleItem(Module),
537 TypedefItem(Typedef, bool /* is associated type */),
538 ExistentialItem(Existential, bool /* is associated type */),
539 StaticItem(Static),
540 ConstantItem(Constant),
541 TraitItem(Trait),
542 TraitAliasItem(TraitAlias),
543 ImplItem(Impl),
544 /// A method signature only. Used for required methods in traits (ie,
545 /// non-default-methods).
546 TyMethodItem(TyMethod),
547 /// A method with a body.
548 MethodItem(Method),
549 StructFieldItem(Type),
550 VariantItem(Variant),
551 /// `fn`s from an extern block
552 ForeignFunctionItem(Function),
553 /// `static`s from an extern block
554 ForeignStaticItem(Static),
555 /// `type`s from an extern block
556 ForeignTypeItem,
557 MacroItem(Macro),
558 ProcMacroItem(ProcMacro),
559 PrimitiveItem(PrimitiveType),
560 AssociatedConstItem(Type, Option<String>),
561 AssociatedTypeItem(Vec<GenericBound>, Option<Type>),
562 /// An item that has been stripped by a rustdoc pass
563 StrippedItem(Box<ItemEnum>),
564 KeywordItem(String),
565 }
566
567 impl ItemEnum {
568 pub fn generics(&self) -> Option<&Generics> {
569 Some(match *self {
570 ItemEnum::StructItem(ref s) => &s.generics,
571 ItemEnum::EnumItem(ref e) => &e.generics,
572 ItemEnum::FunctionItem(ref f) => &f.generics,
573 ItemEnum::TypedefItem(ref t, _) => &t.generics,
574 ItemEnum::ExistentialItem(ref t, _) => &t.generics,
575 ItemEnum::TraitItem(ref t) => &t.generics,
576 ItemEnum::ImplItem(ref i) => &i.generics,
577 ItemEnum::TyMethodItem(ref i) => &i.generics,
578 ItemEnum::MethodItem(ref i) => &i.generics,
579 ItemEnum::ForeignFunctionItem(ref f) => &f.generics,
580 ItemEnum::TraitAliasItem(ref ta) => &ta.generics,
581 _ => return None,
582 })
583 }
584
585 pub fn is_associated(&self) -> bool {
586 match *self {
587 ItemEnum::TypedefItem(_, _) |
588 ItemEnum::AssociatedTypeItem(_, _) => true,
589 _ => false,
590 }
591 }
592 }
593
594 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
595 pub struct Module {
596 pub items: Vec<Item>,
597 pub is_crate: bool,
598 }
599
600 impl Clean<Item> for doctree::Module {
601 fn clean(&self, cx: &DocContext<'_>) -> Item {
602 let name = if self.name.is_some() {
603 self.name.expect("No name provided").clean(cx)
604 } else {
605 String::new()
606 };
607
608 // maintain a stack of mod ids, for doc comment path resolution
609 // but we also need to resolve the module's own docs based on whether its docs were written
610 // inside or outside the module, so check for that
611 let attrs = self.attrs.clean(cx);
612
613 let mut items: Vec<Item> = vec![];
614 items.extend(self.extern_crates.iter().flat_map(|x| x.clean(cx)));
615 items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
616 items.extend(self.structs.iter().map(|x| x.clean(cx)));
617 items.extend(self.unions.iter().map(|x| x.clean(cx)));
618 items.extend(self.enums.iter().map(|x| x.clean(cx)));
619 items.extend(self.fns.iter().map(|x| x.clean(cx)));
620 items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx)));
621 items.extend(self.mods.iter().map(|x| x.clean(cx)));
622 items.extend(self.typedefs.iter().map(|x| x.clean(cx)));
623 items.extend(self.existentials.iter().map(|x| x.clean(cx)));
624 items.extend(self.statics.iter().map(|x| x.clean(cx)));
625 items.extend(self.constants.iter().map(|x| x.clean(cx)));
626 items.extend(self.traits.iter().map(|x| x.clean(cx)));
627 items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
628 items.extend(self.macros.iter().map(|x| x.clean(cx)));
629 items.extend(self.proc_macros.iter().map(|x| x.clean(cx)));
630 items.extend(self.trait_aliases.iter().map(|x| x.clean(cx)));
631
632 // determine if we should display the inner contents or
633 // the outer `mod` item for the source code.
634 let whence = {
635 let cm = cx.sess().source_map();
636 let outer = cm.lookup_char_pos(self.where_outer.lo());
637 let inner = cm.lookup_char_pos(self.where_inner.lo());
638 if outer.file.start_pos == inner.file.start_pos {
639 // mod foo { ... }
640 self.where_outer
641 } else {
642 // mod foo; (and a separate SourceFile for the contents)
643 self.where_inner
644 }
645 };
646
647 Item {
648 name: Some(name),
649 attrs,
650 source: whence.clean(cx),
651 visibility: self.vis.clean(cx),
652 stability: self.stab.clean(cx),
653 deprecation: self.depr.clean(cx),
654 def_id: cx.tcx.hir().local_def_id(self.id),
655 inner: ModuleItem(Module {
656 is_crate: self.is_crate,
657 items,
658 })
659 }
660 }
661 }
662
663 pub struct ListAttributesIter<'a> {
664 attrs: slice::Iter<'a, ast::Attribute>,
665 current_list: vec::IntoIter<ast::NestedMetaItem>,
666 name: &'a str
667 }
668
669 impl<'a> Iterator for ListAttributesIter<'a> {
670 type Item = ast::NestedMetaItem;
671
672 fn next(&mut self) -> Option<Self::Item> {
673 if let Some(nested) = self.current_list.next() {
674 return Some(nested);
675 }
676
677 for attr in &mut self.attrs {
678 if let Some(list) = attr.meta_item_list() {
679 if attr.check_name(self.name) {
680 self.current_list = list.into_iter();
681 if let Some(nested) = self.current_list.next() {
682 return Some(nested);
683 }
684 }
685 }
686 }
687
688 None
689 }
690
691 fn size_hint(&self) -> (usize, Option<usize>) {
692 let lower = self.current_list.len();
693 (lower, None)
694 }
695 }
696
697 pub trait AttributesExt {
698 /// Finds an attribute as List and returns the list of attributes nested inside.
699 fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a>;
700 }
701
702 impl AttributesExt for [ast::Attribute] {
703 fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a> {
704 ListAttributesIter {
705 attrs: self.iter(),
706 current_list: Vec::new().into_iter(),
707 name,
708 }
709 }
710 }
711
712 pub trait NestedAttributesExt {
713 /// Returns `true` if the attribute list contains a specific `Word`
714 fn has_word(self, word: &str) -> bool;
715 }
716
717 impl<I: IntoIterator<Item=ast::NestedMetaItem>> NestedAttributesExt for I {
718 fn has_word(self, word: &str) -> bool {
719 self.into_iter().any(|attr| attr.is_word() && attr.check_name(word))
720 }
721 }
722
723 /// A portion of documentation, extracted from a `#[doc]` attribute.
724 ///
725 /// Each variant contains the line number within the complete doc-comment where the fragment
726 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
727 ///
728 /// Included files are kept separate from inline doc comments so that proper line-number
729 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
730 /// kept separate because of issue #42760.
731 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
732 pub enum DocFragment {
733 /// A doc fragment created from a `///` or `//!` doc comment.
734 SugaredDoc(usize, syntax_pos::Span, String),
735 /// A doc fragment created from a "raw" `#[doc=""]` attribute.
736 RawDoc(usize, syntax_pos::Span, String),
737 /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
738 /// given filename and the file contents.
739 Include(usize, syntax_pos::Span, String, String),
740 }
741
742 impl DocFragment {
743 pub fn as_str(&self) -> &str {
744 match *self {
745 DocFragment::SugaredDoc(_, _, ref s) => &s[..],
746 DocFragment::RawDoc(_, _, ref s) => &s[..],
747 DocFragment::Include(_, _, _, ref s) => &s[..],
748 }
749 }
750
751 pub fn span(&self) -> syntax_pos::Span {
752 match *self {
753 DocFragment::SugaredDoc(_, span, _) |
754 DocFragment::RawDoc(_, span, _) |
755 DocFragment::Include(_, span, _, _) => span,
756 }
757 }
758 }
759
760 impl<'a> FromIterator<&'a DocFragment> for String {
761 fn from_iter<T>(iter: T) -> Self
762 where
763 T: IntoIterator<Item = &'a DocFragment>
764 {
765 iter.into_iter().fold(String::new(), |mut acc, frag| {
766 if !acc.is_empty() {
767 acc.push('\n');
768 }
769 match *frag {
770 DocFragment::SugaredDoc(_, _, ref docs)
771 | DocFragment::RawDoc(_, _, ref docs)
772 | DocFragment::Include(_, _, _, ref docs) =>
773 acc.push_str(docs),
774 }
775
776 acc
777 })
778 }
779 }
780
781 #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)]
782 pub struct Attributes {
783 pub doc_strings: Vec<DocFragment>,
784 pub other_attrs: Vec<ast::Attribute>,
785 pub cfg: Option<Arc<Cfg>>,
786 pub span: Option<syntax_pos::Span>,
787 /// map from Rust paths to resolved defs and potential URL fragments
788 pub links: Vec<(String, Option<DefId>, Option<String>)>,
789 pub inner_docs: bool,
790 }
791
792 impl Attributes {
793 /// Extracts the content from an attribute `#[doc(cfg(content))]`.
794 fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
795 use syntax::ast::NestedMetaItem::MetaItem;
796
797 if let ast::MetaItemKind::List(ref nmis) = mi.node {
798 if nmis.len() == 1 {
799 if let MetaItem(ref cfg_mi) = nmis[0] {
800 if cfg_mi.check_name("cfg") {
801 if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.node {
802 if cfg_nmis.len() == 1 {
803 if let MetaItem(ref content_mi) = cfg_nmis[0] {
804 return Some(content_mi);
805 }
806 }
807 }
808 }
809 }
810 }
811 }
812
813 None
814 }
815
816 /// Reads a `MetaItem` from within an attribute, looks for whether it is a
817 /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
818 /// its expansion.
819 fn extract_include(mi: &ast::MetaItem)
820 -> Option<(String, String)>
821 {
822 mi.meta_item_list().and_then(|list| {
823 for meta in list {
824 if meta.check_name("include") {
825 // the actual compiled `#[doc(include="filename")]` gets expanded to
826 // `#[doc(include(file="filename", contents="file contents")]` so we need to
827 // look for that instead
828 return meta.meta_item_list().and_then(|list| {
829 let mut filename: Option<String> = None;
830 let mut contents: Option<String> = None;
831
832 for it in list {
833 if it.check_name("file") {
834 if let Some(name) = it.value_str() {
835 filename = Some(name.to_string());
836 }
837 } else if it.check_name("contents") {
838 if let Some(docs) = it.value_str() {
839 contents = Some(docs.to_string());
840 }
841 }
842 }
843
844 if let (Some(filename), Some(contents)) = (filename, contents) {
845 Some((filename, contents))
846 } else {
847 None
848 }
849 });
850 }
851 }
852
853 None
854 })
855 }
856
857 pub fn has_doc_flag(&self, flag: &str) -> bool {
858 for attr in &self.other_attrs {
859 if !attr.check_name("doc") { continue; }
860
861 if let Some(items) = attr.meta_item_list() {
862 if items.iter().filter_map(|i| i.meta_item()).any(|it| it.check_name(flag)) {
863 return true;
864 }
865 }
866 }
867
868 false
869 }
870
871 pub fn from_ast(diagnostic: &::errors::Handler,
872 attrs: &[ast::Attribute]) -> Attributes {
873 let mut doc_strings = vec![];
874 let mut sp = None;
875 let mut cfg = Cfg::True;
876 let mut doc_line = 0;
877
878 let other_attrs = attrs.iter().filter_map(|attr| {
879 attr.with_desugared_doc(|attr| {
880 if attr.check_name("doc") {
881 if let Some(mi) = attr.meta() {
882 if let Some(value) = mi.value_str() {
883 // Extracted #[doc = "..."]
884 let value = value.to_string();
885 let line = doc_line;
886 doc_line += value.lines().count();
887
888 if attr.is_sugared_doc {
889 doc_strings.push(DocFragment::SugaredDoc(line, attr.span, value));
890 } else {
891 doc_strings.push(DocFragment::RawDoc(line, attr.span, value));
892 }
893
894 if sp.is_none() {
895 sp = Some(attr.span);
896 }
897 return None;
898 } else if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
899 // Extracted #[doc(cfg(...))]
900 match Cfg::parse(cfg_mi) {
901 Ok(new_cfg) => cfg &= new_cfg,
902 Err(e) => diagnostic.span_err(e.span, e.msg),
903 }
904 return None;
905 } else if let Some((filename, contents)) = Attributes::extract_include(&mi)
906 {
907 let line = doc_line;
908 doc_line += contents.lines().count();
909 doc_strings.push(DocFragment::Include(line,
910 attr.span,
911 filename,
912 contents));
913 }
914 }
915 }
916 Some(attr.clone())
917 })
918 }).collect();
919
920 // treat #[target_feature(enable = "feat")] attributes as if they were
921 // #[doc(cfg(target_feature = "feat"))] attributes as well
922 for attr in attrs.lists("target_feature") {
923 if attr.check_name("enable") {
924 if let Some(feat) = attr.value_str() {
925 let meta = attr::mk_name_value_item_str(Ident::from_str("target_feature"),
926 dummy_spanned(feat));
927 if let Ok(feat_cfg) = Cfg::parse(&meta) {
928 cfg &= feat_cfg;
929 }
930 }
931 }
932 }
933
934 let inner_docs = attrs.iter()
935 .filter(|a| a.check_name("doc"))
936 .next()
937 .map_or(true, |a| a.style == AttrStyle::Inner);
938
939 Attributes {
940 doc_strings,
941 other_attrs,
942 cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) },
943 span: sp,
944 links: vec![],
945 inner_docs,
946 }
947 }
948
949 /// Finds the `doc` attribute as a NameValue and returns the corresponding
950 /// value found.
951 pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
952 self.doc_strings.first().map(|s| s.as_str())
953 }
954
955 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
956 /// with newlines.
957 pub fn collapsed_doc_value(&self) -> Option<String> {
958 if !self.doc_strings.is_empty() {
959 Some(self.doc_strings.iter().collect())
960 } else {
961 None
962 }
963 }
964
965 /// Gets links as a vector
966 ///
967 /// Cache must be populated before call
968 pub fn links(&self, krate: &CrateNum) -> Vec<(String, String)> {
969 use crate::html::format::href;
970
971 self.links.iter().filter_map(|&(ref s, did, ref fragment)| {
972 match did {
973 Some(did) => {
974 if let Some((mut href, ..)) = href(did) {
975 if let Some(ref fragment) = *fragment {
976 href.push_str("#");
977 href.push_str(fragment);
978 }
979 Some((s.clone(), href))
980 } else {
981 None
982 }
983 }
984 None => {
985 if let Some(ref fragment) = *fragment {
986 let cache = cache();
987 let url = match cache.extern_locations.get(krate) {
988 Some(&(_, ref src, ExternalLocation::Local)) =>
989 src.to_str().expect("invalid file path"),
990 Some(&(_, _, ExternalLocation::Remote(ref s))) => s,
991 Some(&(_, _, ExternalLocation::Unknown)) | None =>
992 "https://doc.rust-lang.org/nightly",
993 };
994 // This is a primitive so the url is done "by hand".
995 let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
996 Some((s.clone(),
997 format!("{}{}std/primitive.{}.html{}",
998 url,
999 if !url.ends_with('/') { "/" } else { "" },
1000 &fragment[..tail],
1001 &fragment[tail..])))
1002 } else {
1003 panic!("This isn't a primitive?!");
1004 }
1005 }
1006 }
1007 }).collect()
1008 }
1009 }
1010
1011 impl PartialEq for Attributes {
1012 fn eq(&self, rhs: &Self) -> bool {
1013 self.doc_strings == rhs.doc_strings &&
1014 self.cfg == rhs.cfg &&
1015 self.span == rhs.span &&
1016 self.links == rhs.links &&
1017 self.other_attrs.iter().map(|attr| attr.id).eq(rhs.other_attrs.iter().map(|attr| attr.id))
1018 }
1019 }
1020
1021 impl Eq for Attributes {}
1022
1023 impl Hash for Attributes {
1024 fn hash<H: Hasher>(&self, hasher: &mut H) {
1025 self.doc_strings.hash(hasher);
1026 self.cfg.hash(hasher);
1027 self.span.hash(hasher);
1028 self.links.hash(hasher);
1029 for attr in &self.other_attrs {
1030 attr.id.hash(hasher);
1031 }
1032 }
1033 }
1034
1035 impl AttributesExt for Attributes {
1036 fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a> {
1037 self.other_attrs.lists(name)
1038 }
1039 }
1040
1041 impl Clean<Attributes> for [ast::Attribute] {
1042 fn clean(&self, cx: &DocContext<'_>) -> Attributes {
1043 Attributes::from_ast(cx.sess().diagnostic(), self)
1044 }
1045 }
1046
1047 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1048 pub enum GenericBound {
1049 TraitBound(PolyTrait, hir::TraitBoundModifier),
1050 Outlives(Lifetime),
1051 }
1052
1053 impl GenericBound {
1054 fn maybe_sized(cx: &DocContext<'_>) -> GenericBound {
1055 let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem);
1056 let empty = cx.tcx.intern_substs(&[]);
1057 let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
1058 Some(did), false, vec![], empty);
1059 inline::record_extern_fqn(cx, did, TypeKind::Trait);
1060 GenericBound::TraitBound(PolyTrait {
1061 trait_: ResolvedPath {
1062 path,
1063 param_names: None,
1064 did,
1065 is_generic: false,
1066 },
1067 generic_params: Vec::new(),
1068 }, hir::TraitBoundModifier::Maybe)
1069 }
1070
1071 fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1072 use rustc::hir::TraitBoundModifier as TBM;
1073 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
1074 if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
1075 return true;
1076 }
1077 }
1078 false
1079 }
1080
1081 fn get_poly_trait(&self) -> Option<PolyTrait> {
1082 if let GenericBound::TraitBound(ref p, _) = *self {
1083 return Some(p.clone())
1084 }
1085 None
1086 }
1087
1088 fn get_trait_type(&self) -> Option<Type> {
1089 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1090 Some(trait_.clone())
1091 } else {
1092 None
1093 }
1094 }
1095 }
1096
1097 impl Clean<GenericBound> for hir::GenericBound {
1098 fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
1099 match *self {
1100 hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)),
1101 hir::GenericBound::Trait(ref t, modifier) => {
1102 GenericBound::TraitBound(t.clean(cx), modifier)
1103 }
1104 }
1105 }
1106 }
1107
1108 fn external_generic_args(
1109 cx: &DocContext<'_>,
1110 trait_did: Option<DefId>,
1111 has_self: bool,
1112 bindings: Vec<TypeBinding>,
1113 substs: SubstsRef<'_>,
1114 ) -> GenericArgs {
1115 let mut skip_self = has_self;
1116 let mut ty_sty = None;
1117 let args: Vec<_> = substs.iter().filter_map(|kind| match kind.unpack() {
1118 UnpackedKind::Lifetime(lt) => {
1119 lt.clean(cx).and_then(|lt| Some(GenericArg::Lifetime(lt)))
1120 }
1121 UnpackedKind::Type(_) if skip_self => {
1122 skip_self = false;
1123 None
1124 }
1125 UnpackedKind::Type(ty) => {
1126 ty_sty = Some(&ty.sty);
1127 Some(GenericArg::Type(ty.clean(cx)))
1128 }
1129 UnpackedKind::Const(ct) => Some(GenericArg::Const(ct.clean(cx))),
1130 }).collect();
1131
1132 match trait_did {
1133 // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
1134 Some(did) if cx.tcx.lang_items().fn_trait_kind(did).is_some() => {
1135 assert!(ty_sty.is_some());
1136 let inputs = match ty_sty {
1137 Some(ty::Tuple(ref tys)) => tys.iter().map(|t| t.clean(cx)).collect(),
1138 _ => return GenericArgs::AngleBracketed { args, bindings },
1139 };
1140 let output = None;
1141 // FIXME(#20299) return type comes from a projection now
1142 // match types[1].sty {
1143 // ty::Tuple(ref v) if v.is_empty() => None, // -> ()
1144 // _ => Some(types[1].clean(cx))
1145 // };
1146 GenericArgs::Parenthesized { inputs, output }
1147 },
1148 _ => {
1149 GenericArgs::AngleBracketed { args, bindings }
1150 }
1151 }
1152 }
1153
1154 // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
1155 // from Fn<(A, B,), C> to Fn(A, B) -> C
1156 fn external_path(cx: &DocContext<'_>, name: &str, trait_did: Option<DefId>, has_self: bool,
1157 bindings: Vec<TypeBinding>, substs: SubstsRef<'_>) -> Path {
1158 Path {
1159 global: false,
1160 def: Def::Err,
1161 segments: vec![PathSegment {
1162 name: name.to_string(),
1163 args: external_generic_args(cx, trait_did, has_self, bindings, substs)
1164 }],
1165 }
1166 }
1167
1168 impl<'a, 'tcx> Clean<GenericBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>) {
1169 fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
1170 let (trait_ref, ref bounds) = *self;
1171 inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait);
1172 let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id).as_str(),
1173 Some(trait_ref.def_id), true, bounds.clone(), trait_ref.substs);
1174
1175 debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs);
1176
1177 // collect any late bound regions
1178 let mut late_bounds = vec![];
1179 for ty_s in trait_ref.input_types().skip(1) {
1180 if let ty::Tuple(ts) = ty_s.sty {
1181 for &ty_s in ts {
1182 if let ty::Ref(ref reg, _, _) = ty_s.sty {
1183 if let &ty::RegionKind::ReLateBound(..) = *reg {
1184 debug!(" hit an ReLateBound {:?}", reg);
1185 if let Some(Lifetime(name)) = reg.clean(cx) {
1186 late_bounds.push(GenericParamDef {
1187 name,
1188 kind: GenericParamDefKind::Lifetime,
1189 });
1190 }
1191 }
1192 }
1193 }
1194 }
1195 }
1196
1197 GenericBound::TraitBound(
1198 PolyTrait {
1199 trait_: ResolvedPath {
1200 path,
1201 param_names: None,
1202 did: trait_ref.def_id,
1203 is_generic: false,
1204 },
1205 generic_params: late_bounds,
1206 },
1207 hir::TraitBoundModifier::None
1208 )
1209 }
1210 }
1211
1212 impl<'tcx> Clean<GenericBound> for ty::TraitRef<'tcx> {
1213 fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
1214 (self, vec![]).clean(cx)
1215 }
1216 }
1217
1218 impl<'tcx> Clean<Option<Vec<GenericBound>>> for InternalSubsts<'tcx> {
1219 fn clean(&self, cx: &DocContext<'_>) -> Option<Vec<GenericBound>> {
1220 let mut v = Vec::new();
1221 v.extend(self.regions().filter_map(|r| r.clean(cx)).map(GenericBound::Outlives));
1222 v.extend(self.types().map(|t| GenericBound::TraitBound(PolyTrait {
1223 trait_: t.clean(cx),
1224 generic_params: Vec::new(),
1225 }, hir::TraitBoundModifier::None)));
1226 if !v.is_empty() {Some(v)} else {None}
1227 }
1228 }
1229
1230 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1231 pub struct Lifetime(String);
1232
1233 impl Lifetime {
1234 pub fn get_ref<'a>(&'a self) -> &'a str {
1235 let Lifetime(ref s) = *self;
1236 let s: &'a str = s;
1237 s
1238 }
1239
1240 pub fn statik() -> Lifetime {
1241 Lifetime("'static".to_string())
1242 }
1243 }
1244
1245 impl Clean<Lifetime> for hir::Lifetime {
1246 fn clean(&self, cx: &DocContext<'_>) -> Lifetime {
1247 if self.hir_id != hir::DUMMY_HIR_ID {
1248 let def = cx.tcx.named_region(self.hir_id);
1249 match def {
1250 Some(rl::Region::EarlyBound(_, node_id, _)) |
1251 Some(rl::Region::LateBound(_, node_id, _)) |
1252 Some(rl::Region::Free(_, node_id)) => {
1253 if let Some(lt) = cx.lt_substs.borrow().get(&node_id).cloned() {
1254 return lt;
1255 }
1256 }
1257 _ => {}
1258 }
1259 }
1260 Lifetime(self.name.ident().to_string())
1261 }
1262 }
1263
1264 impl Clean<Lifetime> for hir::GenericParam {
1265 fn clean(&self, _: &DocContext<'_>) -> Lifetime {
1266 match self.kind {
1267 hir::GenericParamKind::Lifetime { .. } => {
1268 if self.bounds.len() > 0 {
1269 let mut bounds = self.bounds.iter().map(|bound| match bound {
1270 hir::GenericBound::Outlives(lt) => lt,
1271 _ => panic!(),
1272 });
1273 let name = bounds.next().expect("no more bounds").name.ident();
1274 let mut s = format!("{}: {}", self.name.ident(), name);
1275 for bound in bounds {
1276 s.push_str(&format!(" + {}", bound.name.ident()));
1277 }
1278 Lifetime(s)
1279 } else {
1280 Lifetime(self.name.ident().to_string())
1281 }
1282 }
1283 _ => panic!(),
1284 }
1285 }
1286 }
1287
1288 impl Clean<Constant> for hir::ConstArg {
1289 fn clean(&self, cx: &DocContext<'_>) -> Constant {
1290 Constant {
1291 type_: cx.tcx.type_of(cx.tcx.hir().body_owner_def_id(self.value.body)).clean(cx),
1292 expr: print_const_expr(cx, self.value.body),
1293 }
1294 }
1295 }
1296
1297 impl<'tcx> Clean<Lifetime> for ty::GenericParamDef {
1298 fn clean(&self, _cx: &DocContext<'_>) -> Lifetime {
1299 Lifetime(self.name.to_string())
1300 }
1301 }
1302
1303 impl Clean<Option<Lifetime>> for ty::RegionKind {
1304 fn clean(&self, cx: &DocContext<'_>) -> Option<Lifetime> {
1305 match *self {
1306 ty::ReStatic => Some(Lifetime::statik()),
1307 ty::ReLateBound(_, ty::BrNamed(_, name)) => Some(Lifetime(name.to_string())),
1308 ty::ReEarlyBound(ref data) => Some(Lifetime(data.name.clean(cx))),
1309
1310 ty::ReLateBound(..) |
1311 ty::ReFree(..) |
1312 ty::ReScope(..) |
1313 ty::ReVar(..) |
1314 ty::RePlaceholder(..) |
1315 ty::ReEmpty |
1316 ty::ReClosureBound(_) |
1317 ty::ReErased => {
1318 debug!("Cannot clean region {:?}", self);
1319 None
1320 }
1321 }
1322 }
1323 }
1324
1325 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1326 pub enum WherePredicate {
1327 BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
1328 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1329 EqPredicate { lhs: Type, rhs: Type },
1330 }
1331
1332 impl WherePredicate {
1333 pub fn get_bounds(&self) -> Option<&[GenericBound]> {
1334 match *self {
1335 WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
1336 WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
1337 _ => None,
1338 }
1339 }
1340 }
1341
1342 impl Clean<WherePredicate> for hir::WherePredicate {
1343 fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
1344 match *self {
1345 hir::WherePredicate::BoundPredicate(ref wbp) => {
1346 WherePredicate::BoundPredicate {
1347 ty: wbp.bounded_ty.clean(cx),
1348 bounds: wbp.bounds.clean(cx)
1349 }
1350 }
1351
1352 hir::WherePredicate::RegionPredicate(ref wrp) => {
1353 WherePredicate::RegionPredicate {
1354 lifetime: wrp.lifetime.clean(cx),
1355 bounds: wrp.bounds.clean(cx)
1356 }
1357 }
1358
1359 hir::WherePredicate::EqPredicate(ref wrp) => {
1360 WherePredicate::EqPredicate {
1361 lhs: wrp.lhs_ty.clean(cx),
1362 rhs: wrp.rhs_ty.clean(cx)
1363 }
1364 }
1365 }
1366 }
1367 }
1368
1369 impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
1370 fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
1371 use rustc::ty::Predicate;
1372
1373 match *self {
1374 Predicate::Trait(ref pred) => Some(pred.clean(cx)),
1375 Predicate::Subtype(ref pred) => Some(pred.clean(cx)),
1376 Predicate::RegionOutlives(ref pred) => pred.clean(cx),
1377 Predicate::TypeOutlives(ref pred) => pred.clean(cx),
1378 Predicate::Projection(ref pred) => Some(pred.clean(cx)),
1379
1380 Predicate::WellFormed(..) |
1381 Predicate::ObjectSafe(..) |
1382 Predicate::ClosureKind(..) |
1383 Predicate::ConstEvaluatable(..) => panic!("not user writable"),
1384 }
1385 }
1386 }
1387
1388 impl<'a> Clean<WherePredicate> for ty::TraitPredicate<'a> {
1389 fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
1390 WherePredicate::BoundPredicate {
1391 ty: self.trait_ref.self_ty().clean(cx),
1392 bounds: vec![self.trait_ref.clean(cx)]
1393 }
1394 }
1395 }
1396
1397 impl<'tcx> Clean<WherePredicate> for ty::SubtypePredicate<'tcx> {
1398 fn clean(&self, _cx: &DocContext<'_>) -> WherePredicate {
1399 panic!("subtype predicates are an internal rustc artifact \
1400 and should not be seen by rustdoc")
1401 }
1402 }
1403
1404 impl<'tcx> Clean<Option<WherePredicate>> for
1405 ty::OutlivesPredicate<ty::Region<'tcx>,ty::Region<'tcx>> {
1406
1407 fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
1408 let ty::OutlivesPredicate(ref a, ref b) = *self;
1409
1410 match (a, b) {
1411 (ty::ReEmpty, ty::ReEmpty) => {
1412 return None;
1413 },
1414 _ => {}
1415 }
1416
1417 Some(WherePredicate::RegionPredicate {
1418 lifetime: a.clean(cx).expect("failed to clean lifetime"),
1419 bounds: vec![GenericBound::Outlives(b.clean(cx).expect("failed to clean bounds"))]
1420 })
1421 }
1422 }
1423
1424 impl<'tcx> Clean<Option<WherePredicate>> for ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>> {
1425 fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
1426 let ty::OutlivesPredicate(ref ty, ref lt) = *self;
1427
1428 match lt {
1429 ty::ReEmpty => return None,
1430 _ => {}
1431 }
1432
1433 Some(WherePredicate::BoundPredicate {
1434 ty: ty.clean(cx),
1435 bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))]
1436 })
1437 }
1438 }
1439
1440 impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
1441 fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
1442 WherePredicate::EqPredicate {
1443 lhs: self.projection_ty.clean(cx),
1444 rhs: self.ty.clean(cx)
1445 }
1446 }
1447 }
1448
1449 impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
1450 fn clean(&self, cx: &DocContext<'_>) -> Type {
1451 let trait_ = match self.trait_ref(cx.tcx).clean(cx) {
1452 GenericBound::TraitBound(t, _) => t.trait_,
1453 GenericBound::Outlives(_) => panic!("cleaning a trait got a lifetime"),
1454 };
1455 Type::QPath {
1456 name: cx.tcx.associated_item(self.item_def_id).ident.name.clean(cx),
1457 self_type: box self.self_ty().clean(cx),
1458 trait_: box trait_
1459 }
1460 }
1461 }
1462
1463 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1464 pub enum GenericParamDefKind {
1465 Lifetime,
1466 Type {
1467 did: DefId,
1468 bounds: Vec<GenericBound>,
1469 default: Option<Type>,
1470 synthetic: Option<hir::SyntheticTyParamKind>,
1471 },
1472 Const {
1473 did: DefId,
1474 ty: Type,
1475 },
1476 }
1477
1478 impl GenericParamDefKind {
1479 pub fn is_type(&self) -> bool {
1480 match *self {
1481 GenericParamDefKind::Type { .. } => true,
1482 _ => false,
1483 }
1484 }
1485
1486 pub fn get_type(&self, cx: &DocContext<'_>) -> Option<Type> {
1487 match *self {
1488 GenericParamDefKind::Type { did, .. } => {
1489 rustc_typeck::checked_type_of(cx.tcx, did, false).map(|t| t.clean(cx))
1490 }
1491 GenericParamDefKind::Const { ref ty, .. } => Some(ty.clone()),
1492 GenericParamDefKind::Lifetime => None,
1493 }
1494 }
1495 }
1496
1497 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1498 pub struct GenericParamDef {
1499 pub name: String,
1500
1501 pub kind: GenericParamDefKind,
1502 }
1503
1504 impl GenericParamDef {
1505 pub fn is_synthetic_type_param(&self) -> bool {
1506 match self.kind {
1507 GenericParamDefKind::Lifetime |
1508 GenericParamDefKind::Const { .. } => false,
1509 GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
1510 }
1511 }
1512
1513 pub fn is_type(&self) -> bool {
1514 self.kind.is_type()
1515 }
1516
1517 pub fn get_type(&self, cx: &DocContext<'_>) -> Option<Type> {
1518 self.kind.get_type(cx)
1519 }
1520
1521 pub fn get_bounds(&self) -> Option<&[GenericBound]> {
1522 match self.kind {
1523 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1524 _ => None,
1525 }
1526 }
1527 }
1528
1529 impl Clean<GenericParamDef> for ty::GenericParamDef {
1530 fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
1531 let (name, kind) = match self.kind {
1532 ty::GenericParamDefKind::Lifetime => {
1533 (self.name.to_string(), GenericParamDefKind::Lifetime)
1534 }
1535 ty::GenericParamDefKind::Type { has_default, .. } => {
1536 cx.renderinfo.borrow_mut().external_param_names
1537 .insert(self.def_id, self.name.clean(cx));
1538 let default = if has_default {
1539 Some(cx.tcx.type_of(self.def_id).clean(cx))
1540 } else {
1541 None
1542 };
1543 (self.name.clean(cx), GenericParamDefKind::Type {
1544 did: self.def_id,
1545 bounds: vec![], // These are filled in from the where-clauses.
1546 default,
1547 synthetic: None,
1548 })
1549 }
1550 ty::GenericParamDefKind::Const { .. } => {
1551 (self.name.clean(cx), GenericParamDefKind::Const {
1552 did: self.def_id,
1553 ty: cx.tcx.type_of(self.def_id).clean(cx),
1554 })
1555 }
1556 };
1557
1558 GenericParamDef {
1559 name,
1560 kind,
1561 }
1562 }
1563 }
1564
1565 impl Clean<GenericParamDef> for hir::GenericParam {
1566 fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
1567 let (name, kind) = match self.kind {
1568 hir::GenericParamKind::Lifetime { .. } => {
1569 let name = if self.bounds.len() > 0 {
1570 let mut bounds = self.bounds.iter().map(|bound| match bound {
1571 hir::GenericBound::Outlives(lt) => lt,
1572 _ => panic!(),
1573 });
1574 let name = bounds.next().expect("no more bounds").name.ident();
1575 let mut s = format!("{}: {}", self.name.ident(), name);
1576 for bound in bounds {
1577 s.push_str(&format!(" + {}", bound.name.ident()));
1578 }
1579 s
1580 } else {
1581 self.name.ident().to_string()
1582 };
1583 (name, GenericParamDefKind::Lifetime)
1584 }
1585 hir::GenericParamKind::Type { ref default, synthetic } => {
1586 (self.name.ident().name.clean(cx), GenericParamDefKind::Type {
1587 did: cx.tcx.hir().local_def_id_from_hir_id(self.hir_id),
1588 bounds: self.bounds.clean(cx),
1589 default: default.clean(cx),
1590 synthetic: synthetic,
1591 })
1592 }
1593 hir::GenericParamKind::Const { ref ty } => {
1594 (self.name.ident().name.clean(cx), GenericParamDefKind::Const {
1595 did: cx.tcx.hir().local_def_id_from_hir_id(self.hir_id),
1596 ty: ty.clean(cx),
1597 })
1598 }
1599 };
1600
1601 GenericParamDef {
1602 name,
1603 kind,
1604 }
1605 }
1606 }
1607
1608 // maybe use a Generic enum and use Vec<Generic>?
1609 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Default, Hash)]
1610 pub struct Generics {
1611 pub params: Vec<GenericParamDef>,
1612 pub where_predicates: Vec<WherePredicate>,
1613 }
1614
1615 impl Clean<Generics> for hir::Generics {
1616 fn clean(&self, cx: &DocContext<'_>) -> Generics {
1617 // Synthetic type-parameters are inserted after normal ones.
1618 // In order for normal parameters to be able to refer to synthetic ones,
1619 // scans them first.
1620 fn is_impl_trait(param: &hir::GenericParam) -> bool {
1621 match param.kind {
1622 hir::GenericParamKind::Type { synthetic, .. } => {
1623 synthetic == Some(hir::SyntheticTyParamKind::ImplTrait)
1624 }
1625 _ => false,
1626 }
1627 }
1628 let impl_trait_params = self.params
1629 .iter()
1630 .filter(|param| is_impl_trait(param))
1631 .map(|param| {
1632 let param: GenericParamDef = param.clean(cx);
1633 match param.kind {
1634 GenericParamDefKind::Lifetime => unreachable!(),
1635 GenericParamDefKind::Type { did, ref bounds, .. } => {
1636 cx.impl_trait_bounds.borrow_mut().insert(did, bounds.clone());
1637 }
1638 GenericParamDefKind::Const { .. } => unreachable!(),
1639 }
1640 param
1641 })
1642 .collect::<Vec<_>>();
1643
1644 let mut params = Vec::with_capacity(self.params.len());
1645 for p in self.params.iter().filter(|p| !is_impl_trait(p)) {
1646 let p = p.clean(cx);
1647 params.push(p);
1648 }
1649 params.extend(impl_trait_params);
1650
1651 let mut generics = Generics {
1652 params,
1653 where_predicates: self.where_clause.predicates.clean(cx),
1654 };
1655
1656 // Some duplicates are generated for ?Sized bounds between type params and where
1657 // predicates. The point in here is to move the bounds definitions from type params
1658 // to where predicates when such cases occur.
1659 for where_pred in &mut generics.where_predicates {
1660 match *where_pred {
1661 WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => {
1662 if bounds.is_empty() {
1663 for param in &mut generics.params {
1664 match param.kind {
1665 GenericParamDefKind::Lifetime => {}
1666 GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
1667 if &param.name == name {
1668 mem::swap(bounds, ty_bounds);
1669 break
1670 }
1671 }
1672 GenericParamDefKind::Const { .. } => {}
1673 }
1674 }
1675 }
1676 }
1677 _ => continue,
1678 }
1679 }
1680 generics
1681 }
1682 }
1683
1684 impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
1685 &'a Lrc<ty::GenericPredicates<'tcx>>) {
1686 fn clean(&self, cx: &DocContext<'_>) -> Generics {
1687 use self::WherePredicate as WP;
1688
1689 let (gens, preds) = *self;
1690
1691 // Bounds in the type_params and lifetimes fields are repeated in the
1692 // predicates field (see rustc_typeck::collect::ty_generics), so remove
1693 // them.
1694 let stripped_typarams = gens.params.iter().filter_map(|param| match param.kind {
1695 ty::GenericParamDefKind::Lifetime => None,
1696 ty::GenericParamDefKind::Type { .. } => {
1697 if param.name == keywords::SelfUpper.name().as_str() {
1698 assert_eq!(param.index, 0);
1699 return None;
1700 }
1701 Some(param.clean(cx))
1702 }
1703 ty::GenericParamDefKind::Const { .. } => {
1704 unimplemented!() // FIXME(const_generics)
1705 }
1706 }).collect::<Vec<GenericParamDef>>();
1707
1708 let mut where_predicates = preds.predicates.iter()
1709 .flat_map(|(p, _)| p.clean(cx))
1710 .collect::<Vec<_>>();
1711
1712 // Type parameters and have a Sized bound by default unless removed with
1713 // ?Sized. Scan through the predicates and mark any type parameter with
1714 // a Sized bound, removing the bounds as we find them.
1715 //
1716 // Note that associated types also have a sized bound by default, but we
1717 // don't actually know the set of associated types right here so that's
1718 // handled in cleaning associated types
1719 let mut sized_params = FxHashSet::default();
1720 where_predicates.retain(|pred| {
1721 match *pred {
1722 WP::BoundPredicate { ty: Generic(ref g), ref bounds } => {
1723 if bounds.iter().any(|b| b.is_sized_bound(cx)) {
1724 sized_params.insert(g.clone());
1725 false
1726 } else {
1727 true
1728 }
1729 }
1730 _ => true,
1731 }
1732 });
1733
1734 // Run through the type parameters again and insert a ?Sized
1735 // unbound for any we didn't find to be Sized.
1736 for tp in &stripped_typarams {
1737 if !sized_params.contains(&tp.name) {
1738 where_predicates.push(WP::BoundPredicate {
1739 ty: Type::Generic(tp.name.clone()),
1740 bounds: vec![GenericBound::maybe_sized(cx)],
1741 })
1742 }
1743 }
1744
1745 // It would be nice to collect all of the bounds on a type and recombine
1746 // them if possible, to avoid e.g., `where T: Foo, T: Bar, T: Sized, T: 'a`
1747 // and instead see `where T: Foo + Bar + Sized + 'a`
1748
1749 Generics {
1750 params: gens.params
1751 .iter()
1752 .flat_map(|param| match param.kind {
1753 ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
1754 ty::GenericParamDefKind::Type { .. } => None,
1755 ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)),
1756 }).chain(simplify::ty_params(stripped_typarams).into_iter())
1757 .collect(),
1758 where_predicates: simplify::where_clauses(cx, where_predicates),
1759 }
1760 }
1761 }
1762
1763 /// The point of this function is to replace bounds with types.
1764 ///
1765 /// i.e. `[T, U]` when you have the following bounds: `T: Display, U: Option<T>` will return
1766 /// `[Display, Option]` (we just returns the list of the types, we don't care about the
1767 /// wrapped types in here).
1768 fn get_real_types(
1769 generics: &Generics,
1770 arg: &Type,
1771 cx: &DocContext<'_>,
1772 recurse: i32,
1773 ) -> FxHashSet<Type> {
1774 let arg_s = arg.to_string();
1775 let mut res = FxHashSet::default();
1776 if recurse >= 10 { // FIXME: remove this whole recurse thing when the recursion bug is fixed
1777 return res;
1778 }
1779 if arg.is_full_generic() {
1780 if let Some(where_pred) = generics.where_predicates.iter().find(|g| {
1781 match g {
1782 &WherePredicate::BoundPredicate { ref ty, .. } => ty.def_id() == arg.def_id(),
1783 _ => false,
1784 }
1785 }) {
1786 let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]);
1787 for bound in bounds.iter() {
1788 match *bound {
1789 GenericBound::TraitBound(ref poly_trait, _) => {
1790 for x in poly_trait.generic_params.iter() {
1791 if !x.is_type() {
1792 continue
1793 }
1794 if let Some(ty) = x.get_type(cx) {
1795 let adds = get_real_types(generics, &ty, cx, recurse + 1);
1796 if !adds.is_empty() {
1797 res.extend(adds);
1798 } else if !ty.is_full_generic() {
1799 res.insert(ty);
1800 }
1801 }
1802 }
1803 }
1804 _ => {}
1805 }
1806 }
1807 }
1808 if let Some(bound) = generics.params.iter().find(|g| {
1809 g.is_type() && g.name == arg_s
1810 }) {
1811 for bound in bound.get_bounds().unwrap_or_else(|| &[]) {
1812 if let Some(ty) = bound.get_trait_type() {
1813 let adds = get_real_types(generics, &ty, cx, recurse + 1);
1814 if !adds.is_empty() {
1815 res.extend(adds);
1816 } else if !ty.is_full_generic() {
1817 res.insert(ty.clone());
1818 }
1819 }
1820 }
1821 }
1822 } else {
1823 res.insert(arg.clone());
1824 if let Some(gens) = arg.generics() {
1825 for gen in gens.iter() {
1826 if gen.is_full_generic() {
1827 let adds = get_real_types(generics, gen, cx, recurse + 1);
1828 if !adds.is_empty() {
1829 res.extend(adds);
1830 }
1831 } else {
1832 res.insert(gen.clone());
1833 }
1834 }
1835 }
1836 }
1837 res
1838 }
1839
1840 /// Return the full list of types when bounds have been resolved.
1841 ///
1842 /// i.e. `fn foo<A: Display, B: Option<A>>(x: u32, y: B)` will return
1843 /// `[u32, Display, Option]`.
1844 pub fn get_all_types(
1845 generics: &Generics,
1846 decl: &FnDecl,
1847 cx: &DocContext<'_>,
1848 ) -> (Vec<Type>, Vec<Type>) {
1849 let mut all_types = FxHashSet::default();
1850 for arg in decl.inputs.values.iter() {
1851 if arg.type_.is_self_type() {
1852 continue;
1853 }
1854 let args = get_real_types(generics, &arg.type_, cx, 0);
1855 if !args.is_empty() {
1856 all_types.extend(args);
1857 } else {
1858 all_types.insert(arg.type_.clone());
1859 }
1860 }
1861
1862 let ret_types = match decl.output {
1863 FunctionRetTy::Return(ref return_type) => {
1864 let mut ret = get_real_types(generics, &return_type, cx, 0);
1865 if ret.is_empty() {
1866 ret.insert(return_type.clone());
1867 }
1868 ret.into_iter().collect()
1869 }
1870 _ => Vec::new(),
1871 };
1872 (all_types.into_iter().collect(), ret_types)
1873 }
1874
1875 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1876 pub struct Method {
1877 pub generics: Generics,
1878 pub decl: FnDecl,
1879 pub header: hir::FnHeader,
1880 pub defaultness: Option<hir::Defaultness>,
1881 pub all_types: Vec<Type>,
1882 pub ret_types: Vec<Type>,
1883 }
1884
1885 impl<'a> Clean<Method> for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId,
1886 Option<hir::Defaultness>) {
1887 fn clean(&self, cx: &DocContext<'_>) -> Method {
1888 let (generics, decl) = enter_impl_trait(cx, || {
1889 (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx))
1890 });
1891 let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
1892 Method {
1893 decl,
1894 generics,
1895 header: self.0.header,
1896 defaultness: self.3,
1897 all_types,
1898 ret_types,
1899 }
1900 }
1901 }
1902
1903 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1904 pub struct TyMethod {
1905 pub header: hir::FnHeader,
1906 pub decl: FnDecl,
1907 pub generics: Generics,
1908 pub all_types: Vec<Type>,
1909 pub ret_types: Vec<Type>,
1910 }
1911
1912 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1913 pub struct Function {
1914 pub decl: FnDecl,
1915 pub generics: Generics,
1916 pub header: hir::FnHeader,
1917 pub all_types: Vec<Type>,
1918 pub ret_types: Vec<Type>,
1919 }
1920
1921 impl Clean<Item> for doctree::Function {
1922 fn clean(&self, cx: &DocContext<'_>) -> Item {
1923 let (generics, decl) = enter_impl_trait(cx, || {
1924 (self.generics.clean(cx), (&self.decl, self.body).clean(cx))
1925 });
1926
1927 let did = cx.tcx.hir().local_def_id_from_hir_id(self.id);
1928 let constness = if cx.tcx.is_min_const_fn(did) {
1929 hir::Constness::Const
1930 } else {
1931 hir::Constness::NotConst
1932 };
1933 let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
1934 Item {
1935 name: Some(self.name.clean(cx)),
1936 attrs: self.attrs.clean(cx),
1937 source: self.whence.clean(cx),
1938 visibility: self.vis.clean(cx),
1939 stability: self.stab.clean(cx),
1940 deprecation: self.depr.clean(cx),
1941 def_id: did,
1942 inner: FunctionItem(Function {
1943 decl,
1944 generics,
1945 header: hir::FnHeader { constness, ..self.header },
1946 all_types,
1947 ret_types,
1948 }),
1949 }
1950 }
1951 }
1952
1953 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1954 pub struct FnDecl {
1955 pub inputs: Arguments,
1956 pub output: FunctionRetTy,
1957 pub attrs: Attributes,
1958 }
1959
1960 impl FnDecl {
1961 pub fn self_type(&self) -> Option<SelfTy> {
1962 self.inputs.values.get(0).and_then(|v| v.to_self())
1963 }
1964
1965 /// Returns the sugared return type for an async function.
1966 ///
1967 /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
1968 /// will return `i32`.
1969 ///
1970 /// # Panics
1971 ///
1972 /// This function will panic if the return type does not match the expected sugaring for async
1973 /// functions.
1974 pub fn sugared_async_return_type(&self) -> FunctionRetTy {
1975 match &self.output {
1976 FunctionRetTy::Return(Type::ImplTrait(bounds)) => {
1977 match &bounds[0] {
1978 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
1979 let bindings = trait_.bindings().unwrap();
1980 FunctionRetTy::Return(bindings[0].ty.clone())
1981 }
1982 _ => panic!("unexpected desugaring of async function"),
1983 }
1984 }
1985 _ => panic!("unexpected desugaring of async function"),
1986 }
1987 }
1988 }
1989
1990 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1991 pub struct Arguments {
1992 pub values: Vec<Argument>,
1993 }
1994
1995 impl<'a> Clean<Arguments> for (&'a [hir::Ty], &'a [ast::Ident]) {
1996 fn clean(&self, cx: &DocContext<'_>) -> Arguments {
1997 Arguments {
1998 values: self.0.iter().enumerate().map(|(i, ty)| {
1999 let mut name = self.1.get(i).map(|ident| ident.to_string())
2000 .unwrap_or(String::new());
2001 if name.is_empty() {
2002 name = "_".to_string();
2003 }
2004 Argument {
2005 name,
2006 type_: ty.clean(cx),
2007 }
2008 }).collect()
2009 }
2010 }
2011 }
2012
2013 impl<'a> Clean<Arguments> for (&'a [hir::Ty], hir::BodyId) {
2014 fn clean(&self, cx: &DocContext<'_>) -> Arguments {
2015 let body = cx.tcx.hir().body(self.1);
2016
2017 Arguments {
2018 values: self.0.iter().enumerate().map(|(i, ty)| {
2019 Argument {
2020 name: name_from_pat(&body.arguments[i].pat),
2021 type_: ty.clean(cx),
2022 }
2023 }).collect()
2024 }
2025 }
2026 }
2027
2028 impl<'a, A: Copy> Clean<FnDecl> for (&'a hir::FnDecl, A)
2029 where (&'a [hir::Ty], A): Clean<Arguments>
2030 {
2031 fn clean(&self, cx: &DocContext<'_>) -> FnDecl {
2032 FnDecl {
2033 inputs: (&self.0.inputs[..], self.1).clean(cx),
2034 output: self.0.output.clean(cx),
2035 attrs: Attributes::default(),
2036 }
2037 }
2038 }
2039
2040 impl<'a, 'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
2041 fn clean(&self, cx: &DocContext<'_>) -> FnDecl {
2042 let (did, sig) = *self;
2043 let mut names = if cx.tcx.hir().as_local_hir_id(did).is_some() {
2044 vec![].into_iter()
2045 } else {
2046 cx.tcx.fn_arg_names(did).into_iter()
2047 };
2048
2049 FnDecl {
2050 output: Return(sig.skip_binder().output().clean(cx)),
2051 attrs: Attributes::default(),
2052 inputs: Arguments {
2053 values: sig.skip_binder().inputs().iter().map(|t| {
2054 Argument {
2055 type_: t.clean(cx),
2056 name: names.next().map_or(String::new(), |name| name.to_string()),
2057 }
2058 }).collect(),
2059 },
2060 }
2061 }
2062 }
2063
2064 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
2065 pub struct Argument {
2066 pub type_: Type,
2067 pub name: String,
2068 }
2069
2070 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2071 pub enum SelfTy {
2072 SelfValue,
2073 SelfBorrowed(Option<Lifetime>, Mutability),
2074 SelfExplicit(Type),
2075 }
2076
2077 impl Argument {
2078 pub fn to_self(&self) -> Option<SelfTy> {
2079 if self.name != "self" {
2080 return None;
2081 }
2082 if self.type_.is_self_type() {
2083 return Some(SelfValue);
2084 }
2085 match self.type_ {
2086 BorrowedRef{ref lifetime, mutability, ref type_} if type_.is_self_type() => {
2087 Some(SelfBorrowed(lifetime.clone(), mutability))
2088 }
2089 _ => Some(SelfExplicit(self.type_.clone()))
2090 }
2091 }
2092 }
2093
2094 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
2095 pub enum FunctionRetTy {
2096 Return(Type),
2097 DefaultReturn,
2098 }
2099
2100 impl Clean<FunctionRetTy> for hir::FunctionRetTy {
2101 fn clean(&self, cx: &DocContext<'_>) -> FunctionRetTy {
2102 match *self {
2103 hir::Return(ref typ) => Return(typ.clean(cx)),
2104 hir::DefaultReturn(..) => DefaultReturn,
2105 }
2106 }
2107 }
2108
2109 impl GetDefId for FunctionRetTy {
2110 fn def_id(&self) -> Option<DefId> {
2111 match *self {
2112 Return(ref ty) => ty.def_id(),
2113 DefaultReturn => None,
2114 }
2115 }
2116 }
2117
2118 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2119 pub struct Trait {
2120 pub auto: bool,
2121 pub unsafety: hir::Unsafety,
2122 pub items: Vec<Item>,
2123 pub generics: Generics,
2124 pub bounds: Vec<GenericBound>,
2125 pub is_spotlight: bool,
2126 pub is_auto: bool,
2127 }
2128
2129 impl Clean<Item> for doctree::Trait {
2130 fn clean(&self, cx: &DocContext<'_>) -> Item {
2131 let attrs = self.attrs.clean(cx);
2132 let is_spotlight = attrs.has_doc_flag("spotlight");
2133 Item {
2134 name: Some(self.name.clean(cx)),
2135 attrs: attrs,
2136 source: self.whence.clean(cx),
2137 def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
2138 visibility: self.vis.clean(cx),
2139 stability: self.stab.clean(cx),
2140 deprecation: self.depr.clean(cx),
2141 inner: TraitItem(Trait {
2142 auto: self.is_auto.clean(cx),
2143 unsafety: self.unsafety,
2144 items: self.items.clean(cx),
2145 generics: self.generics.clean(cx),
2146 bounds: self.bounds.clean(cx),
2147 is_spotlight,
2148 is_auto: self.is_auto.clean(cx),
2149 }),
2150 }
2151 }
2152 }
2153
2154 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2155 pub struct TraitAlias {
2156 pub generics: Generics,
2157 pub bounds: Vec<GenericBound>,
2158 }
2159
2160 impl Clean<Item> for doctree::TraitAlias {
2161 fn clean(&self, cx: &DocContext<'_>) -> Item {
2162 let attrs = self.attrs.clean(cx);
2163 Item {
2164 name: Some(self.name.clean(cx)),
2165 attrs,
2166 source: self.whence.clean(cx),
2167 def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
2168 visibility: self.vis.clean(cx),
2169 stability: self.stab.clean(cx),
2170 deprecation: self.depr.clean(cx),
2171 inner: TraitAliasItem(TraitAlias {
2172 generics: self.generics.clean(cx),
2173 bounds: self.bounds.clean(cx),
2174 }),
2175 }
2176 }
2177 }
2178
2179 impl Clean<bool> for hir::IsAuto {
2180 fn clean(&self, _: &DocContext<'_>) -> bool {
2181 match *self {
2182 hir::IsAuto::Yes => true,
2183 hir::IsAuto::No => false,
2184 }
2185 }
2186 }
2187
2188 impl Clean<Type> for hir::TraitRef {
2189 fn clean(&self, cx: &DocContext<'_>) -> Type {
2190 resolve_type(cx, self.path.clean(cx), self.hir_ref_id)
2191 }
2192 }
2193
2194 impl Clean<PolyTrait> for hir::PolyTraitRef {
2195 fn clean(&self, cx: &DocContext<'_>) -> PolyTrait {
2196 PolyTrait {
2197 trait_: self.trait_ref.clean(cx),
2198 generic_params: self.bound_generic_params.clean(cx)
2199 }
2200 }
2201 }
2202
2203 impl Clean<Item> for hir::TraitItem {
2204 fn clean(&self, cx: &DocContext<'_>) -> Item {
2205 let inner = match self.node {
2206 hir::TraitItemKind::Const(ref ty, default) => {
2207 AssociatedConstItem(ty.clean(cx),
2208 default.map(|e| print_const_expr(cx, e)))
2209 }
2210 hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
2211 MethodItem((sig, &self.generics, body, None).clean(cx))
2212 }
2213 hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => {
2214 let (generics, decl) = enter_impl_trait(cx, || {
2215 (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
2216 });
2217 let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
2218 TyMethodItem(TyMethod {
2219 header: sig.header,
2220 decl,
2221 generics,
2222 all_types,
2223 ret_types,
2224 })
2225 }
2226 hir::TraitItemKind::Type(ref bounds, ref default) => {
2227 AssociatedTypeItem(bounds.clean(cx), default.clean(cx))
2228 }
2229 };
2230 let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);
2231 Item {
2232 name: Some(self.ident.name.clean(cx)),
2233 attrs: self.attrs.clean(cx),
2234 source: self.span.clean(cx),
2235 def_id: local_did,
2236 visibility: None,
2237 stability: get_stability(cx, local_did),
2238 deprecation: get_deprecation(cx, local_did),
2239 inner,
2240 }
2241 }
2242 }
2243
2244 impl Clean<Item> for hir::ImplItem {
2245 fn clean(&self, cx: &DocContext<'_>) -> Item {
2246 let inner = match self.node {
2247 hir::ImplItemKind::Const(ref ty, expr) => {
2248 AssociatedConstItem(ty.clean(cx),
2249 Some(print_const_expr(cx, expr)))
2250 }
2251 hir::ImplItemKind::Method(ref sig, body) => {
2252 MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx))
2253 }
2254 hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef {
2255 type_: ty.clean(cx),
2256 generics: Generics::default(),
2257 }, true),
2258 hir::ImplItemKind::Existential(ref bounds) => ExistentialItem(Existential {
2259 bounds: bounds.clean(cx),
2260 generics: Generics::default(),
2261 }, true),
2262 };
2263 let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);
2264 Item {
2265 name: Some(self.ident.name.clean(cx)),
2266 source: self.span.clean(cx),
2267 attrs: self.attrs.clean(cx),
2268 def_id: local_did,
2269 visibility: self.vis.clean(cx),
2270 stability: get_stability(cx, local_did),
2271 deprecation: get_deprecation(cx, local_did),
2272 inner,
2273 }
2274 }
2275 }
2276
2277 impl<'tcx> Clean<Item> for ty::AssociatedItem {
2278 fn clean(&self, cx: &DocContext<'_>) -> Item {
2279 let inner = match self.kind {
2280 ty::AssociatedKind::Const => {
2281 let ty = cx.tcx.type_of(self.def_id);
2282 let default = if self.defaultness.has_value() {
2283 Some(inline::print_inlined_const(cx, self.def_id))
2284 } else {
2285 None
2286 };
2287 AssociatedConstItem(ty.clean(cx), default)
2288 }
2289 ty::AssociatedKind::Method => {
2290 let generics = (cx.tcx.generics_of(self.def_id),
2291 &cx.tcx.explicit_predicates_of(self.def_id)).clean(cx);
2292 let sig = cx.tcx.fn_sig(self.def_id);
2293 let mut decl = (self.def_id, sig).clean(cx);
2294
2295 if self.method_has_self_argument {
2296 let self_ty = match self.container {
2297 ty::ImplContainer(def_id) => {
2298 cx.tcx.type_of(def_id)
2299 }
2300 ty::TraitContainer(_) => cx.tcx.mk_self_type()
2301 };
2302 let self_arg_ty = *sig.input(0).skip_binder();
2303 if self_arg_ty == self_ty {
2304 decl.inputs.values[0].type_ = Generic(String::from("Self"));
2305 } else if let ty::Ref(_, ty, _) = self_arg_ty.sty {
2306 if ty == self_ty {
2307 match decl.inputs.values[0].type_ {
2308 BorrowedRef{ref mut type_, ..} => {
2309 **type_ = Generic(String::from("Self"))
2310 }
2311 _ => unreachable!(),
2312 }
2313 }
2314 }
2315 }
2316
2317 let provided = match self.container {
2318 ty::ImplContainer(_) => true,
2319 ty::TraitContainer(_) => self.defaultness.has_value()
2320 };
2321 let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
2322 if provided {
2323 let constness = if cx.tcx.is_min_const_fn(self.def_id) {
2324 hir::Constness::Const
2325 } else {
2326 hir::Constness::NotConst
2327 };
2328 let defaultness = match self.container {
2329 ty::ImplContainer(_) => Some(self.defaultness),
2330 ty::TraitContainer(_) => None,
2331 };
2332 MethodItem(Method {
2333 generics,
2334 decl,
2335 header: hir::FnHeader {
2336 unsafety: sig.unsafety(),
2337 abi: sig.abi(),
2338 constness,
2339 asyncness: hir::IsAsync::NotAsync,
2340 },
2341 defaultness,
2342 all_types,
2343 ret_types,
2344 })
2345 } else {
2346 TyMethodItem(TyMethod {
2347 generics,
2348 decl,
2349 header: hir::FnHeader {
2350 unsafety: sig.unsafety(),
2351 abi: sig.abi(),
2352 constness: hir::Constness::NotConst,
2353 asyncness: hir::IsAsync::NotAsync,
2354 },
2355 all_types,
2356 ret_types,
2357 })
2358 }
2359 }
2360 ty::AssociatedKind::Type => {
2361 let my_name = self.ident.name.clean(cx);
2362
2363 if let ty::TraitContainer(did) = self.container {
2364 // When loading a cross-crate associated type, the bounds for this type
2365 // are actually located on the trait/impl itself, so we need to load
2366 // all of the generics from there and then look for bounds that are
2367 // applied to this associated type in question.
2368 let predicates = cx.tcx.explicit_predicates_of(did);
2369 let generics = (cx.tcx.generics_of(did), &predicates).clean(cx);
2370 let mut bounds = generics.where_predicates.iter().filter_map(|pred| {
2371 let (name, self_type, trait_, bounds) = match *pred {
2372 WherePredicate::BoundPredicate {
2373 ty: QPath { ref name, ref self_type, ref trait_ },
2374 ref bounds
2375 } => (name, self_type, trait_, bounds),
2376 _ => return None,
2377 };
2378 if *name != my_name { return None }
2379 match **trait_ {
2380 ResolvedPath { did, .. } if did == self.container.id() => {}
2381 _ => return None,
2382 }
2383 match **self_type {
2384 Generic(ref s) if *s == "Self" => {}
2385 _ => return None,
2386 }
2387 Some(bounds)
2388 }).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>();
2389 // Our Sized/?Sized bound didn't get handled when creating the generics
2390 // because we didn't actually get our whole set of bounds until just now
2391 // (some of them may have come from the trait). If we do have a sized
2392 // bound, we remove it, and if we don't then we add the `?Sized` bound
2393 // at the end.
2394 match bounds.iter().position(|b| b.is_sized_bound(cx)) {
2395 Some(i) => { bounds.remove(i); }
2396 None => bounds.push(GenericBound::maybe_sized(cx)),
2397 }
2398
2399 let ty = if self.defaultness.has_value() {
2400 Some(cx.tcx.type_of(self.def_id))
2401 } else {
2402 None
2403 };
2404
2405 AssociatedTypeItem(bounds, ty.clean(cx))
2406 } else {
2407 TypedefItem(Typedef {
2408 type_: cx.tcx.type_of(self.def_id).clean(cx),
2409 generics: Generics {
2410 params: Vec::new(),
2411 where_predicates: Vec::new(),
2412 },
2413 }, true)
2414 }
2415 }
2416 ty::AssociatedKind::Existential => unimplemented!(),
2417 };
2418
2419 let visibility = match self.container {
2420 ty::ImplContainer(_) => self.vis.clean(cx),
2421 ty::TraitContainer(_) => None,
2422 };
2423
2424 Item {
2425 name: Some(self.ident.name.clean(cx)),
2426 visibility,
2427 stability: get_stability(cx, self.def_id),
2428 deprecation: get_deprecation(cx, self.def_id),
2429 def_id: self.def_id,
2430 attrs: inline::load_attrs(cx, self.def_id),
2431 source: cx.tcx.def_span(self.def_id).clean(cx),
2432 inner,
2433 }
2434 }
2435 }
2436
2437 /// A trait reference, which may have higher ranked lifetimes.
2438 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
2439 pub struct PolyTrait {
2440 pub trait_: Type,
2441 pub generic_params: Vec<GenericParamDef>,
2442 }
2443
2444 /// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
2445 /// type out of the AST/TyCtxt given one of these, if more information is needed. Most importantly
2446 /// it does not preserve mutability or boxes.
2447 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
2448 pub enum Type {
2449 /// Structs/enums/traits (most that'd be an `hir::TyKind::Path`).
2450 ResolvedPath {
2451 path: Path,
2452 param_names: Option<Vec<GenericBound>>,
2453 did: DefId,
2454 /// `true` if is a `T::Name` path for associated types.
2455 is_generic: bool,
2456 },
2457 /// For parameterized types, so the consumer of the JSON don't go
2458 /// looking for types which don't exist anywhere.
2459 Generic(String),
2460 /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
2461 /// arrays, slices, and tuples.
2462 Primitive(PrimitiveType),
2463 /// extern "ABI" fn
2464 BareFunction(Box<BareFunctionDecl>),
2465 Tuple(Vec<Type>),
2466 Slice(Box<Type>),
2467 Array(Box<Type>, String),
2468 Never,
2469 CVarArgs,
2470 Unique(Box<Type>),
2471 RawPointer(Mutability, Box<Type>),
2472 BorrowedRef {
2473 lifetime: Option<Lifetime>,
2474 mutability: Mutability,
2475 type_: Box<Type>,
2476 },
2477
2478 // <Type as Trait>::Name
2479 QPath {
2480 name: String,
2481 self_type: Box<Type>,
2482 trait_: Box<Type>
2483 },
2484
2485 // _
2486 Infer,
2487
2488 // impl TraitA+TraitB
2489 ImplTrait(Vec<GenericBound>),
2490 }
2491
2492 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
2493 pub enum PrimitiveType {
2494 Isize, I8, I16, I32, I64, I128,
2495 Usize, U8, U16, U32, U64, U128,
2496 F32, F64,
2497 Char,
2498 Bool,
2499 Str,
2500 Slice,
2501 Array,
2502 Tuple,
2503 Unit,
2504 RawPointer,
2505 Reference,
2506 Fn,
2507 Never,
2508 CVarArgs,
2509 }
2510
2511 #[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
2512 pub enum TypeKind {
2513 Enum,
2514 Function,
2515 Module,
2516 Const,
2517 Static,
2518 Struct,
2519 Union,
2520 Trait,
2521 Variant,
2522 Typedef,
2523 Foreign,
2524 Macro,
2525 Attr,
2526 Derive,
2527 TraitAlias,
2528 }
2529
2530 pub trait GetDefId {
2531 fn def_id(&self) -> Option<DefId>;
2532 }
2533
2534 impl<T: GetDefId> GetDefId for Option<T> {
2535 fn def_id(&self) -> Option<DefId> {
2536 self.as_ref().and_then(|d| d.def_id())
2537 }
2538 }
2539
2540 impl Type {
2541 pub fn primitive_type(&self) -> Option<PrimitiveType> {
2542 match *self {
2543 Primitive(p) | BorrowedRef { type_: box Primitive(p), ..} => Some(p),
2544 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
2545 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
2546 Tuple(ref tys) => if tys.is_empty() {
2547 Some(PrimitiveType::Unit)
2548 } else {
2549 Some(PrimitiveType::Tuple)
2550 },
2551 RawPointer(..) => Some(PrimitiveType::RawPointer),
2552 BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
2553 BareFunction(..) => Some(PrimitiveType::Fn),
2554 Never => Some(PrimitiveType::Never),
2555 _ => None,
2556 }
2557 }
2558
2559 pub fn is_generic(&self) -> bool {
2560 match *self {
2561 ResolvedPath { is_generic, .. } => is_generic,
2562 _ => false,
2563 }
2564 }
2565
2566 pub fn is_self_type(&self) -> bool {
2567 match *self {
2568 Generic(ref name) => name == "Self",
2569 _ => false
2570 }
2571 }
2572
2573 pub fn generics(&self) -> Option<Vec<Type>> {
2574 match *self {
2575 ResolvedPath { ref path, .. } => {
2576 path.segments.last().and_then(|seg| {
2577 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2578 Some(args.iter().filter_map(|arg| match arg {
2579 GenericArg::Type(ty) => Some(ty.clone()),
2580 _ => None,
2581 }).collect())
2582 } else {
2583 None
2584 }
2585 })
2586 }
2587 _ => None,
2588 }
2589 }
2590
2591 pub fn bindings(&self) -> Option<&[TypeBinding]> {
2592 match *self {
2593 ResolvedPath { ref path, .. } => {
2594 path.segments.last().and_then(|seg| {
2595 if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
2596 Some(&**bindings)
2597 } else {
2598 None
2599 }
2600 })
2601 }
2602 _ => None
2603 }
2604 }
2605
2606 pub fn is_full_generic(&self) -> bool {
2607 match *self {
2608 Type::Generic(_) => true,
2609 _ => false,
2610 }
2611 }
2612 }
2613
2614 impl GetDefId for Type {
2615 fn def_id(&self) -> Option<DefId> {
2616 match *self {
2617 ResolvedPath { did, .. } => Some(did),
2618 Primitive(p) => crate::html::render::cache().primitive_locations.get(&p).cloned(),
2619 BorrowedRef { type_: box Generic(..), .. } =>
2620 Primitive(PrimitiveType::Reference).def_id(),
2621 BorrowedRef { ref type_, .. } => type_.def_id(),
2622 Tuple(ref tys) => if tys.is_empty() {
2623 Primitive(PrimitiveType::Unit).def_id()
2624 } else {
2625 Primitive(PrimitiveType::Tuple).def_id()
2626 },
2627 BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
2628 Never => Primitive(PrimitiveType::Never).def_id(),
2629 Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
2630 Array(..) => Primitive(PrimitiveType::Array).def_id(),
2631 RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(),
2632 QPath { ref self_type, .. } => self_type.def_id(),
2633 _ => None,
2634 }
2635 }
2636 }
2637
2638 impl PrimitiveType {
2639 fn from_str(s: &str) -> Option<PrimitiveType> {
2640 match s {
2641 "isize" => Some(PrimitiveType::Isize),
2642 "i8" => Some(PrimitiveType::I8),
2643 "i16" => Some(PrimitiveType::I16),
2644 "i32" => Some(PrimitiveType::I32),
2645 "i64" => Some(PrimitiveType::I64),
2646 "i128" => Some(PrimitiveType::I128),
2647 "usize" => Some(PrimitiveType::Usize),
2648 "u8" => Some(PrimitiveType::U8),
2649 "u16" => Some(PrimitiveType::U16),
2650 "u32" => Some(PrimitiveType::U32),
2651 "u64" => Some(PrimitiveType::U64),
2652 "u128" => Some(PrimitiveType::U128),
2653 "bool" => Some(PrimitiveType::Bool),
2654 "char" => Some(PrimitiveType::Char),
2655 "str" => Some(PrimitiveType::Str),
2656 "f32" => Some(PrimitiveType::F32),
2657 "f64" => Some(PrimitiveType::F64),
2658 "array" => Some(PrimitiveType::Array),
2659 "slice" => Some(PrimitiveType::Slice),
2660 "tuple" => Some(PrimitiveType::Tuple),
2661 "unit" => Some(PrimitiveType::Unit),
2662 "pointer" => Some(PrimitiveType::RawPointer),
2663 "reference" => Some(PrimitiveType::Reference),
2664 "fn" => Some(PrimitiveType::Fn),
2665 "never" => Some(PrimitiveType::Never),
2666 _ => None,
2667 }
2668 }
2669
2670 pub fn as_str(&self) -> &'static str {
2671 use self::PrimitiveType::*;
2672 match *self {
2673 Isize => "isize",
2674 I8 => "i8",
2675 I16 => "i16",
2676 I32 => "i32",
2677 I64 => "i64",
2678 I128 => "i128",
2679 Usize => "usize",
2680 U8 => "u8",
2681 U16 => "u16",
2682 U32 => "u32",
2683 U64 => "u64",
2684 U128 => "u128",
2685 F32 => "f32",
2686 F64 => "f64",
2687 Str => "str",
2688 Bool => "bool",
2689 Char => "char",
2690 Array => "array",
2691 Slice => "slice",
2692 Tuple => "tuple",
2693 Unit => "unit",
2694 RawPointer => "pointer",
2695 Reference => "reference",
2696 Fn => "fn",
2697 Never => "never",
2698 CVarArgs => "...",
2699 }
2700 }
2701
2702 pub fn to_url_str(&self) -> &'static str {
2703 self.as_str()
2704 }
2705 }
2706
2707 impl From<ast::IntTy> for PrimitiveType {
2708 fn from(int_ty: ast::IntTy) -> PrimitiveType {
2709 match int_ty {
2710 ast::IntTy::Isize => PrimitiveType::Isize,
2711 ast::IntTy::I8 => PrimitiveType::I8,
2712 ast::IntTy::I16 => PrimitiveType::I16,
2713 ast::IntTy::I32 => PrimitiveType::I32,
2714 ast::IntTy::I64 => PrimitiveType::I64,
2715 ast::IntTy::I128 => PrimitiveType::I128,
2716 }
2717 }
2718 }
2719
2720 impl From<ast::UintTy> for PrimitiveType {
2721 fn from(uint_ty: ast::UintTy) -> PrimitiveType {
2722 match uint_ty {
2723 ast::UintTy::Usize => PrimitiveType::Usize,
2724 ast::UintTy::U8 => PrimitiveType::U8,
2725 ast::UintTy::U16 => PrimitiveType::U16,
2726 ast::UintTy::U32 => PrimitiveType::U32,
2727 ast::UintTy::U64 => PrimitiveType::U64,
2728 ast::UintTy::U128 => PrimitiveType::U128,
2729 }
2730 }
2731 }
2732
2733 impl From<ast::FloatTy> for PrimitiveType {
2734 fn from(float_ty: ast::FloatTy) -> PrimitiveType {
2735 match float_ty {
2736 ast::FloatTy::F32 => PrimitiveType::F32,
2737 ast::FloatTy::F64 => PrimitiveType::F64,
2738 }
2739 }
2740 }
2741
2742 impl Clean<Type> for hir::Ty {
2743 fn clean(&self, cx: &DocContext<'_>) -> Type {
2744 use rustc::hir::*;
2745
2746 match self.node {
2747 TyKind::Never => Never,
2748 TyKind::CVarArgs(_) => CVarArgs,
2749 TyKind::Ptr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
2750 TyKind::Rptr(ref l, ref m) => {
2751 let lifetime = if l.is_elided() {
2752 None
2753 } else {
2754 Some(l.clean(cx))
2755 };
2756 BorrowedRef {lifetime: lifetime, mutability: m.mutbl.clean(cx),
2757 type_: box m.ty.clean(cx)}
2758 }
2759 TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
2760 TyKind::Array(ref ty, ref length) => {
2761 let def_id = cx.tcx.hir().local_def_id_from_hir_id(length.hir_id);
2762 let param_env = cx.tcx.param_env(def_id);
2763 let substs = InternalSubsts::identity_for_item(cx.tcx, def_id);
2764 let cid = GlobalId {
2765 instance: ty::Instance::new(def_id, substs),
2766 promoted: None
2767 };
2768 let length = match cx.tcx.const_eval(param_env.and(cid)) {
2769 Ok(length) => print_const(cx, length),
2770 Err(_) => "_".to_string(),
2771 };
2772 Array(box ty.clean(cx), length)
2773 },
2774 TyKind::Tup(ref tys) => Tuple(tys.clean(cx)),
2775 TyKind::Def(item_id, _) => {
2776 let item = cx.tcx.hir().expect_item_by_hir_id(item_id.id);
2777 if let hir::ItemKind::Existential(ref ty) = item.node {
2778 ImplTrait(ty.bounds.clean(cx))
2779 } else {
2780 unreachable!()
2781 }
2782 }
2783 TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
2784 if let Some(new_ty) = cx.ty_substs.borrow().get(&path.def).cloned() {
2785 return new_ty;
2786 }
2787
2788 if let Def::TyParam(did) = path.def {
2789 if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did) {
2790 return ImplTrait(bounds);
2791 }
2792 }
2793
2794 let mut alias = None;
2795 if let Def::TyAlias(def_id) = path.def {
2796 // Substitute private type aliases
2797 if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
2798 if !cx.renderinfo.borrow().access_levels.is_exported(def_id) {
2799 alias = Some(&cx.tcx.hir().expect_item_by_hir_id(hir_id).node);
2800 }
2801 }
2802 };
2803
2804 if let Some(&hir::ItemKind::Ty(ref ty, ref generics)) = alias {
2805 let provided_params = &path.segments.last().expect("segments were empty");
2806 let mut ty_substs = FxHashMap::default();
2807 let mut lt_substs = FxHashMap::default();
2808 let mut const_substs = FxHashMap::default();
2809 provided_params.with_generic_args(|generic_args| {
2810 let mut indices: GenericParamCount = Default::default();
2811 for param in generics.params.iter() {
2812 match param.kind {
2813 hir::GenericParamKind::Lifetime { .. } => {
2814 let mut j = 0;
2815 let lifetime = generic_args.args.iter().find_map(|arg| {
2816 match arg {
2817 hir::GenericArg::Lifetime(lt) => {
2818 if indices.lifetimes == j {
2819 return Some(lt);
2820 }
2821 j += 1;
2822 None
2823 }
2824 _ => None,
2825 }
2826 });
2827 if let Some(lt) = lifetime.cloned() {
2828 if !lt.is_elided() {
2829 let lt_def_id =
2830 cx.tcx.hir().local_def_id_from_hir_id(param.hir_id);
2831 lt_substs.insert(lt_def_id, lt.clean(cx));
2832 }
2833 }
2834 indices.lifetimes += 1;
2835 }
2836 hir::GenericParamKind::Type { ref default, .. } => {
2837 let ty_param_def =
2838 Def::TyParam(
2839 cx.tcx.hir().local_def_id_from_hir_id(param.hir_id));
2840 let mut j = 0;
2841 let type_ = generic_args.args.iter().find_map(|arg| {
2842 match arg {
2843 hir::GenericArg::Type(ty) => {
2844 if indices.types == j {
2845 return Some(ty);
2846 }
2847 j += 1;
2848 None
2849 }
2850 _ => None,
2851 }
2852 });
2853 if let Some(ty) = type_.cloned() {
2854 ty_substs.insert(ty_param_def, ty.clean(cx));
2855 } else if let Some(default) = default.clone() {
2856 ty_substs.insert(ty_param_def,
2857 default.into_inner().clean(cx));
2858 }
2859 indices.types += 1;
2860 }
2861 hir::GenericParamKind::Const { .. } => {
2862 let const_param_def =
2863 Def::ConstParam(
2864 cx.tcx.hir().local_def_id_from_hir_id(param.hir_id));
2865 let mut j = 0;
2866 let const_ = generic_args.args.iter().find_map(|arg| {
2867 match arg {
2868 hir::GenericArg::Const(ct) => {
2869 if indices.consts == j {
2870 return Some(ct);
2871 }
2872 j += 1;
2873 None
2874 }
2875 _ => None,
2876 }
2877 });
2878 if let Some(ct) = const_.cloned() {
2879 const_substs.insert(const_param_def, ct.clean(cx));
2880 }
2881 // FIXME(const_generics:defaults)
2882 indices.consts += 1;
2883 }
2884 }
2885 }
2886 });
2887 return cx.enter_alias(ty_substs, lt_substs, const_substs, || ty.clean(cx));
2888 }
2889 resolve_type(cx, path.clean(cx), self.hir_id)
2890 }
2891 TyKind::Path(hir::QPath::Resolved(Some(ref qself), ref p)) => {
2892 let mut segments: Vec<_> = p.segments.clone().into();
2893 segments.pop();
2894 let trait_path = hir::Path {
2895 span: p.span,
2896 def: Def::Trait(cx.tcx.associated_item(p.def.def_id()).container.id()),
2897 segments: segments.into(),
2898 };
2899 Type::QPath {
2900 name: p.segments.last().expect("segments were empty").ident.name.clean(cx),
2901 self_type: box qself.clean(cx),
2902 trait_: box resolve_type(cx, trait_path.clean(cx), self.hir_id)
2903 }
2904 }
2905 TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
2906 let mut def = Def::Err;
2907 let ty = hir_ty_to_ty(cx.tcx, self);
2908 if let ty::Projection(proj) = ty.sty {
2909 def = Def::Trait(proj.trait_ref(cx.tcx).def_id);
2910 }
2911 let trait_path = hir::Path {
2912 span: self.span,
2913 def,
2914 segments: vec![].into(),
2915 };
2916 Type::QPath {
2917 name: segment.ident.name.clean(cx),
2918 self_type: box qself.clean(cx),
2919 trait_: box resolve_type(cx, trait_path.clean(cx), self.hir_id)
2920 }
2921 }
2922 TyKind::TraitObject(ref bounds, ref lifetime) => {
2923 match bounds[0].clean(cx).trait_ {
2924 ResolvedPath { path, param_names: None, did, is_generic } => {
2925 let mut bounds: Vec<self::GenericBound> = bounds[1..].iter().map(|bound| {
2926 self::GenericBound::TraitBound(bound.clean(cx),
2927 hir::TraitBoundModifier::None)
2928 }).collect();
2929 if !lifetime.is_elided() {
2930 bounds.push(self::GenericBound::Outlives(lifetime.clean(cx)));
2931 }
2932 ResolvedPath { path, param_names: Some(bounds), did, is_generic, }
2933 }
2934 _ => Infer // shouldn't happen
2935 }
2936 }
2937 TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
2938 TyKind::Infer | TyKind::Err => Infer,
2939 TyKind::Typeof(..) => panic!("Unimplemented type {:?}", self.node),
2940 }
2941 }
2942 }
2943
2944 impl<'tcx> Clean<Type> for Ty<'tcx> {
2945 fn clean(&self, cx: &DocContext<'_>) -> Type {
2946 match self.sty {
2947 ty::Never => Never,
2948 ty::Bool => Primitive(PrimitiveType::Bool),
2949 ty::Char => Primitive(PrimitiveType::Char),
2950 ty::Int(int_ty) => Primitive(int_ty.into()),
2951 ty::Uint(uint_ty) => Primitive(uint_ty.into()),
2952 ty::Float(float_ty) => Primitive(float_ty.into()),
2953 ty::Str => Primitive(PrimitiveType::Str),
2954 ty::Slice(ty) => Slice(box ty.clean(cx)),
2955 ty::Array(ty, n) => {
2956 let mut n = *cx.tcx.lift(&n).expect("array lift failed");
2957 if let ConstValue::Unevaluated(def_id, substs) = n.val {
2958 let param_env = cx.tcx.param_env(def_id);
2959 let cid = GlobalId {
2960 instance: ty::Instance::new(def_id, substs),
2961 promoted: None
2962 };
2963 if let Ok(new_n) = cx.tcx.const_eval(param_env.and(cid)) {
2964 n = new_n;
2965 }
2966 };
2967 let n = print_const(cx, n);
2968 Array(box ty.clean(cx), n)
2969 }
2970 ty::RawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
2971 ty::Ref(r, ty, mutbl) => BorrowedRef {
2972 lifetime: r.clean(cx),
2973 mutability: mutbl.clean(cx),
2974 type_: box ty.clean(cx),
2975 },
2976 ty::FnDef(..) |
2977 ty::FnPtr(_) => {
2978 let ty = cx.tcx.lift(self).expect("FnPtr lift failed");
2979 let sig = ty.fn_sig(cx.tcx);
2980 BareFunction(box BareFunctionDecl {
2981 unsafety: sig.unsafety(),
2982 generic_params: Vec::new(),
2983 decl: (cx.tcx.hir().local_def_id(ast::CRATE_NODE_ID), sig).clean(cx),
2984 abi: sig.abi(),
2985 })
2986 }
2987 ty::Adt(def, substs) => {
2988 let did = def.did;
2989 let kind = match def.adt_kind() {
2990 AdtKind::Struct => TypeKind::Struct,
2991 AdtKind::Union => TypeKind::Union,
2992 AdtKind::Enum => TypeKind::Enum,
2993 };
2994 inline::record_extern_fqn(cx, did, kind);
2995 let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
2996 None, false, vec![], substs);
2997 ResolvedPath {
2998 path,
2999 param_names: None,
3000 did,
3001 is_generic: false,
3002 }
3003 }
3004 ty::Foreign(did) => {
3005 inline::record_extern_fqn(cx, did, TypeKind::Foreign);
3006 let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
3007 None, false, vec![], InternalSubsts::empty());
3008 ResolvedPath {
3009 path: path,
3010 param_names: None,
3011 did: did,
3012 is_generic: false,
3013 }
3014 }
3015 ty::Dynamic(ref obj, ref reg) => {
3016 // HACK: pick the first `did` as the `did` of the trait object. Someone
3017 // might want to implement "native" support for marker-trait-only
3018 // trait objects.
3019 let mut dids = obj.principal_def_id().into_iter().chain(obj.auto_traits());
3020 let did = dids.next().unwrap_or_else(|| {
3021 panic!("found trait object `{:?}` with no traits?", self)
3022 });
3023 let substs = match obj.principal() {
3024 Some(principal) => principal.skip_binder().substs,
3025 // marker traits have no substs.
3026 _ => cx.tcx.intern_substs(&[])
3027 };
3028
3029 inline::record_extern_fqn(cx, did, TypeKind::Trait);
3030
3031 let mut param_names = vec![];
3032 reg.clean(cx).map(|b| param_names.push(GenericBound::Outlives(b)));
3033 for did in dids {
3034 let empty = cx.tcx.intern_substs(&[]);
3035 let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
3036 Some(did), false, vec![], empty);
3037 inline::record_extern_fqn(cx, did, TypeKind::Trait);
3038 let bound = GenericBound::TraitBound(PolyTrait {
3039 trait_: ResolvedPath {
3040 path,
3041 param_names: None,
3042 did,
3043 is_generic: false,
3044 },
3045 generic_params: Vec::new(),
3046 }, hir::TraitBoundModifier::None);
3047 param_names.push(bound);
3048 }
3049
3050 let mut bindings = vec![];
3051 for pb in obj.projection_bounds() {
3052 bindings.push(TypeBinding {
3053 name: cx.tcx.associated_item(pb.item_def_id()).ident.name.clean(cx),
3054 ty: pb.skip_binder().ty.clean(cx)
3055 });
3056 }
3057
3058 let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did),
3059 false, bindings, substs);
3060 ResolvedPath {
3061 path,
3062 param_names: Some(param_names),
3063 did,
3064 is_generic: false,
3065 }
3066 }
3067 ty::Tuple(ref t) => Tuple(t.clean(cx)),
3068
3069 ty::Projection(ref data) => data.clean(cx),
3070
3071 ty::Param(ref p) => Generic(p.name.to_string()),
3072
3073 ty::Opaque(def_id, substs) => {
3074 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
3075 // by looking up the projections associated with the def_id.
3076 let predicates_of = cx.tcx.explicit_predicates_of(def_id);
3077 let substs = cx.tcx.lift(&substs).expect("Opaque lift failed");
3078 let bounds = predicates_of.instantiate(cx.tcx, substs);
3079 let mut regions = vec![];
3080 let mut has_sized = false;
3081 let mut bounds = bounds.predicates.iter().filter_map(|predicate| {
3082 let trait_ref = if let Some(tr) = predicate.to_opt_poly_trait_ref() {
3083 tr
3084 } else if let ty::Predicate::TypeOutlives(pred) = *predicate {
3085 // these should turn up at the end
3086 pred.skip_binder().1.clean(cx).map(|r| {
3087 regions.push(GenericBound::Outlives(r))
3088 });
3089 return None;
3090 } else {
3091 return None;
3092 };
3093
3094 if let Some(sized) = cx.tcx.lang_items().sized_trait() {
3095 if trait_ref.def_id() == sized {
3096 has_sized = true;
3097 return None;
3098 }
3099 }
3100
3101 let bounds = bounds.predicates.iter().filter_map(|pred|
3102 if let ty::Predicate::Projection(proj) = *pred {
3103 let proj = proj.skip_binder();
3104 if proj.projection_ty.trait_ref(cx.tcx) == *trait_ref.skip_binder() {
3105 Some(TypeBinding {
3106 name: cx.tcx.associated_item(proj.projection_ty.item_def_id)
3107 .ident.name.clean(cx),
3108 ty: proj.ty.clean(cx),
3109 })
3110 } else {
3111 None
3112 }
3113 } else {
3114 None
3115 }
3116 ).collect();
3117
3118 Some((trait_ref.skip_binder(), bounds).clean(cx))
3119 }).collect::<Vec<_>>();
3120 bounds.extend(regions);
3121 if !has_sized && !bounds.is_empty() {
3122 bounds.insert(0, GenericBound::maybe_sized(cx));
3123 }
3124 ImplTrait(bounds)
3125 }
3126
3127 ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton)
3128
3129 ty::Bound(..) => panic!("Bound"),
3130 ty::Placeholder(..) => panic!("Placeholder"),
3131 ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"),
3132 ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
3133 ty::Infer(..) => panic!("Infer"),
3134 ty::Error => panic!("Error"),
3135 }
3136 }
3137 }
3138
3139 impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
3140 fn clean(&self, cx: &DocContext<'_>) -> Constant {
3141 Constant {
3142 type_: self.ty.clean(cx),
3143 expr: format!("{:?}", self.val), // FIXME(const_generics)
3144 }
3145 }
3146 }
3147
3148 impl Clean<Item> for hir::StructField {
3149 fn clean(&self, cx: &DocContext<'_>) -> Item {
3150 let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);
3151
3152 Item {
3153 name: Some(self.ident.name).clean(cx),
3154 attrs: self.attrs.clean(cx),
3155 source: self.span.clean(cx),
3156 visibility: self.vis.clean(cx),
3157 stability: get_stability(cx, local_did),
3158 deprecation: get_deprecation(cx, local_did),
3159 def_id: local_did,
3160 inner: StructFieldItem(self.ty.clean(cx)),
3161 }
3162 }
3163 }
3164
3165 impl<'tcx> Clean<Item> for ty::FieldDef {
3166 fn clean(&self, cx: &DocContext<'_>) -> Item {
3167 Item {
3168 name: Some(self.ident.name).clean(cx),
3169 attrs: cx.tcx.get_attrs(self.did).clean(cx),
3170 source: cx.tcx.def_span(self.did).clean(cx),
3171 visibility: self.vis.clean(cx),
3172 stability: get_stability(cx, self.did),
3173 deprecation: get_deprecation(cx, self.did),
3174 def_id: self.did,
3175 inner: StructFieldItem(cx.tcx.type_of(self.did).clean(cx)),
3176 }
3177 }
3178 }
3179
3180 #[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug)]
3181 pub enum Visibility {
3182 Public,
3183 Inherited,
3184 Crate,
3185 Restricted(DefId, Path),
3186 }
3187
3188 impl Clean<Option<Visibility>> for hir::Visibility {
3189 fn clean(&self, cx: &DocContext<'_>) -> Option<Visibility> {
3190 Some(match self.node {
3191 hir::VisibilityKind::Public => Visibility::Public,
3192 hir::VisibilityKind::Inherited => Visibility::Inherited,
3193 hir::VisibilityKind::Crate(_) => Visibility::Crate,
3194 hir::VisibilityKind::Restricted { ref path, .. } => {
3195 let path = path.clean(cx);
3196 let did = register_def(cx, path.def);
3197 Visibility::Restricted(did, path)
3198 }
3199 })
3200 }
3201 }
3202
3203 impl Clean<Option<Visibility>> for ty::Visibility {
3204 fn clean(&self, _: &DocContext<'_>) -> Option<Visibility> {
3205 Some(if *self == ty::Visibility::Public { Public } else { Inherited })
3206 }
3207 }
3208
3209 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3210 pub struct Struct {
3211 pub struct_type: doctree::StructType,
3212 pub generics: Generics,
3213 pub fields: Vec<Item>,
3214 pub fields_stripped: bool,
3215 }
3216
3217 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3218 pub struct Union {
3219 pub struct_type: doctree::StructType,
3220 pub generics: Generics,
3221 pub fields: Vec<Item>,
3222 pub fields_stripped: bool,
3223 }
3224
3225 impl Clean<Item> for doctree::Struct {
3226 fn clean(&self, cx: &DocContext<'_>) -> Item {
3227 Item {
3228 name: Some(self.name.clean(cx)),
3229 attrs: self.attrs.clean(cx),
3230 source: self.whence.clean(cx),
3231 def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
3232 visibility: self.vis.clean(cx),
3233 stability: self.stab.clean(cx),
3234 deprecation: self.depr.clean(cx),
3235 inner: StructItem(Struct {
3236 struct_type: self.struct_type,
3237 generics: self.generics.clean(cx),
3238 fields: self.fields.clean(cx),
3239 fields_stripped: false,
3240 }),
3241 }
3242 }
3243 }
3244
3245 impl Clean<Item> for doctree::Union {
3246 fn clean(&self, cx: &DocContext<'_>) -> Item {
3247 Item {
3248 name: Some(self.name.clean(cx)),
3249 attrs: self.attrs.clean(cx),
3250 source: self.whence.clean(cx),
3251 def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
3252 visibility: self.vis.clean(cx),
3253 stability: self.stab.clean(cx),
3254 deprecation: self.depr.clean(cx),
3255 inner: UnionItem(Union {
3256 struct_type: self.struct_type,
3257 generics: self.generics.clean(cx),
3258 fields: self.fields.clean(cx),
3259 fields_stripped: false,
3260 }),
3261 }
3262 }
3263 }
3264
3265 /// This is a more limited form of the standard Struct, different in that
3266 /// it lacks the things most items have (name, id, parameterization). Found
3267 /// only as a variant in an enum.
3268 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3269 pub struct VariantStruct {
3270 pub struct_type: doctree::StructType,
3271 pub fields: Vec<Item>,
3272 pub fields_stripped: bool,
3273 }
3274
3275 impl Clean<VariantStruct> for ::rustc::hir::VariantData {
3276 fn clean(&self, cx: &DocContext<'_>) -> VariantStruct {
3277 VariantStruct {
3278 struct_type: doctree::struct_type_from_def(self),
3279 fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
3280 fields_stripped: false,
3281 }
3282 }
3283 }
3284
3285 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3286 pub struct Enum {
3287 pub variants: IndexVec<VariantIdx, Item>,
3288 pub generics: Generics,
3289 pub variants_stripped: bool,
3290 }
3291
3292 impl Clean<Item> for doctree::Enum {
3293 fn clean(&self, cx: &DocContext<'_>) -> Item {
3294 Item {
3295 name: Some(self.name.clean(cx)),
3296 attrs: self.attrs.clean(cx),
3297 source: self.whence.clean(cx),
3298 def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
3299 visibility: self.vis.clean(cx),
3300 stability: self.stab.clean(cx),
3301 deprecation: self.depr.clean(cx),
3302 inner: EnumItem(Enum {
3303 variants: self.variants.iter().map(|v| v.clean(cx)).collect(),
3304 generics: self.generics.clean(cx),
3305 variants_stripped: false,
3306 }),
3307 }
3308 }
3309 }
3310
3311 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3312 pub struct Variant {
3313 pub kind: VariantKind,
3314 }
3315
3316 impl Clean<Item> for doctree::Variant {
3317 fn clean(&self, cx: &DocContext<'_>) -> Item {
3318 Item {
3319 name: Some(self.name.clean(cx)),
3320 attrs: self.attrs.clean(cx),
3321 source: self.whence.clean(cx),
3322 visibility: None,
3323 stability: self.stab.clean(cx),
3324 deprecation: self.depr.clean(cx),
3325 def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
3326 inner: VariantItem(Variant {
3327 kind: self.def.clean(cx),
3328 }),
3329 }
3330 }
3331 }
3332
3333 impl<'tcx> Clean<Item> for ty::VariantDef {
3334 fn clean(&self, cx: &DocContext<'_>) -> Item {
3335 let kind = match self.ctor_kind {
3336 CtorKind::Const => VariantKind::CLike,
3337 CtorKind::Fn => {
3338 VariantKind::Tuple(
3339 self.fields.iter().map(|f| cx.tcx.type_of(f.did).clean(cx)).collect()
3340 )
3341 }
3342 CtorKind::Fictive => {
3343 VariantKind::Struct(VariantStruct {
3344 struct_type: doctree::Plain,
3345 fields_stripped: false,
3346 fields: self.fields.iter().map(|field| {
3347 Item {
3348 source: cx.tcx.def_span(field.did).clean(cx),
3349 name: Some(field.ident.name.clean(cx)),
3350 attrs: cx.tcx.get_attrs(field.did).clean(cx),
3351 visibility: field.vis.clean(cx),
3352 def_id: field.did,
3353 stability: get_stability(cx, field.did),
3354 deprecation: get_deprecation(cx, field.did),
3355 inner: StructFieldItem(cx.tcx.type_of(field.did).clean(cx))
3356 }
3357 }).collect()
3358 })
3359 }
3360 };
3361 Item {
3362 name: Some(self.ident.clean(cx)),
3363 attrs: inline::load_attrs(cx, self.def_id),
3364 source: cx.tcx.def_span(self.def_id).clean(cx),
3365 visibility: Some(Inherited),
3366 def_id: self.def_id,
3367 inner: VariantItem(Variant { kind }),
3368 stability: get_stability(cx, self.def_id),
3369 deprecation: get_deprecation(cx, self.def_id),
3370 }
3371 }
3372 }
3373
3374 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3375 pub enum VariantKind {
3376 CLike,
3377 Tuple(Vec<Type>),
3378 Struct(VariantStruct),
3379 }
3380
3381 impl Clean<VariantKind> for hir::VariantData {
3382 fn clean(&self, cx: &DocContext<'_>) -> VariantKind {
3383 match self {
3384 hir::VariantData::Struct(..) => VariantKind::Struct(self.clean(cx)),
3385 hir::VariantData::Tuple(..) =>
3386 VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect()),
3387 hir::VariantData::Unit(..) => VariantKind::CLike,
3388 }
3389 }
3390 }
3391
3392 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3393 pub struct Span {
3394 pub filename: FileName,
3395 pub loline: usize,
3396 pub locol: usize,
3397 pub hiline: usize,
3398 pub hicol: usize,
3399 }
3400
3401 impl Span {
3402 pub fn empty() -> Span {
3403 Span {
3404 filename: FileName::Anon(0),
3405 loline: 0, locol: 0,
3406 hiline: 0, hicol: 0,
3407 }
3408 }
3409 }
3410
3411 impl Clean<Span> for syntax_pos::Span {
3412 fn clean(&self, cx: &DocContext<'_>) -> Span {
3413 if self.is_dummy() {
3414 return Span::empty();
3415 }
3416
3417 let cm = cx.sess().source_map();
3418 let filename = cm.span_to_filename(*self);
3419 let lo = cm.lookup_char_pos(self.lo());
3420 let hi = cm.lookup_char_pos(self.hi());
3421 Span {
3422 filename,
3423 loline: lo.line,
3424 locol: lo.col.to_usize(),
3425 hiline: hi.line,
3426 hicol: hi.col.to_usize(),
3427 }
3428 }
3429 }
3430
3431 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3432 pub struct Path {
3433 pub global: bool,
3434 pub def: Def,
3435 pub segments: Vec<PathSegment>,
3436 }
3437
3438 impl Path {
3439 pub fn last_name(&self) -> &str {
3440 self.segments.last().expect("segments were empty").name.as_str()
3441 }
3442 }
3443
3444 impl Clean<Path> for hir::Path {
3445 fn clean(&self, cx: &DocContext<'_>) -> Path {
3446 Path {
3447 global: self.is_global(),
3448 def: self.def,
3449 segments: if self.is_global() { &self.segments[1..] } else { &self.segments }.clean(cx),
3450 }
3451 }
3452 }
3453
3454 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3455 pub enum GenericArg {
3456 Lifetime(Lifetime),
3457 Type(Type),
3458 Const(Constant),
3459 }
3460
3461 impl fmt::Display for GenericArg {
3462 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3463 match self {
3464 GenericArg::Lifetime(lt) => lt.fmt(f),
3465 GenericArg::Type(ty) => ty.fmt(f),
3466 GenericArg::Const(ct) => ct.fmt(f),
3467 }
3468 }
3469 }
3470
3471 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3472 pub enum GenericArgs {
3473 AngleBracketed {
3474 args: Vec<GenericArg>,
3475 bindings: Vec<TypeBinding>,
3476 },
3477 Parenthesized {
3478 inputs: Vec<Type>,
3479 output: Option<Type>,
3480 }
3481 }
3482
3483 impl Clean<GenericArgs> for hir::GenericArgs {
3484 fn clean(&self, cx: &DocContext<'_>) -> GenericArgs {
3485 if self.parenthesized {
3486 let output = self.bindings[0].ty.clean(cx);
3487 GenericArgs::Parenthesized {
3488 inputs: self.inputs().clean(cx),
3489 output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
3490 }
3491 } else {
3492 let elide_lifetimes = self.args.iter().all(|arg| match arg {
3493 hir::GenericArg::Lifetime(lt) => lt.is_elided(),
3494 _ => true,
3495 });
3496 GenericArgs::AngleBracketed {
3497 args: self.args.iter().filter_map(|arg| match arg {
3498 hir::GenericArg::Lifetime(lt) if !elide_lifetimes => {
3499 Some(GenericArg::Lifetime(lt.clean(cx)))
3500 }
3501 hir::GenericArg::Lifetime(_) => None,
3502 hir::GenericArg::Type(ty) => Some(GenericArg::Type(ty.clean(cx))),
3503 hir::GenericArg::Const(ct) => Some(GenericArg::Const(ct.clean(cx))),
3504 }).collect(),
3505 bindings: self.bindings.clean(cx),
3506 }
3507 }
3508 }
3509 }
3510
3511 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3512 pub struct PathSegment {
3513 pub name: String,
3514 pub args: GenericArgs,
3515 }
3516
3517 impl Clean<PathSegment> for hir::PathSegment {
3518 fn clean(&self, cx: &DocContext<'_>) -> PathSegment {
3519 PathSegment {
3520 name: self.ident.name.clean(cx),
3521 args: self.with_generic_args(|generic_args| generic_args.clean(cx))
3522 }
3523 }
3524 }
3525
3526 fn strip_type(ty: Type) -> Type {
3527 match ty {
3528 Type::ResolvedPath { path, param_names, did, is_generic } => {
3529 Type::ResolvedPath { path: strip_path(&path), param_names, did, is_generic }
3530 }
3531 Type::Tuple(inner_tys) => {
3532 Type::Tuple(inner_tys.iter().map(|t| strip_type(t.clone())).collect())
3533 }
3534 Type::Slice(inner_ty) => Type::Slice(Box::new(strip_type(*inner_ty))),
3535 Type::Array(inner_ty, s) => Type::Array(Box::new(strip_type(*inner_ty)), s),
3536 Type::Unique(inner_ty) => Type::Unique(Box::new(strip_type(*inner_ty))),
3537 Type::RawPointer(m, inner_ty) => Type::RawPointer(m, Box::new(strip_type(*inner_ty))),
3538 Type::BorrowedRef { lifetime, mutability, type_ } => {
3539 Type::BorrowedRef { lifetime, mutability, type_: Box::new(strip_type(*type_)) }
3540 }
3541 Type::QPath { name, self_type, trait_ } => {
3542 Type::QPath {
3543 name,
3544 self_type: Box::new(strip_type(*self_type)), trait_: Box::new(strip_type(*trait_))
3545 }
3546 }
3547 _ => ty
3548 }
3549 }
3550
3551 fn strip_path(path: &Path) -> Path {
3552 let segments = path.segments.iter().map(|s| {
3553 PathSegment {
3554 name: s.name.clone(),
3555 args: GenericArgs::AngleBracketed {
3556 args: vec![],
3557 bindings: vec![],
3558 }
3559 }
3560 }).collect();
3561
3562 Path {
3563 global: path.global,
3564 def: path.def.clone(),
3565 segments,
3566 }
3567 }
3568
3569 fn qpath_to_string(p: &hir::QPath) -> String {
3570 let segments = match *p {
3571 hir::QPath::Resolved(_, ref path) => &path.segments,
3572 hir::QPath::TypeRelative(_, ref segment) => return segment.ident.to_string(),
3573 };
3574
3575 let mut s = String::new();
3576 for (i, seg) in segments.iter().enumerate() {
3577 if i > 0 {
3578 s.push_str("::");
3579 }
3580 if seg.ident.name != keywords::PathRoot.name() {
3581 s.push_str(&*seg.ident.as_str());
3582 }
3583 }
3584 s
3585 }
3586
3587 impl Clean<String> for Ident {
3588 #[inline]
3589 fn clean(&self, cx: &DocContext<'_>) -> String {
3590 self.name.clean(cx)
3591 }
3592 }
3593
3594 impl Clean<String> for ast::Name {
3595 #[inline]
3596 fn clean(&self, _: &DocContext<'_>) -> String {
3597 self.to_string()
3598 }
3599 }
3600
3601 impl Clean<String> for InternedString {
3602 #[inline]
3603 fn clean(&self, _: &DocContext<'_>) -> String {
3604 self.to_string()
3605 }
3606 }
3607
3608 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3609 pub struct Typedef {
3610 pub type_: Type,
3611 pub generics: Generics,
3612 }
3613
3614 impl Clean<Item> for doctree::Typedef {
3615 fn clean(&self, cx: &DocContext<'_>) -> Item {
3616 Item {
3617 name: Some(self.name.clean(cx)),
3618 attrs: self.attrs.clean(cx),
3619 source: self.whence.clean(cx),
3620 def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
3621 visibility: self.vis.clean(cx),
3622 stability: self.stab.clean(cx),
3623 deprecation: self.depr.clean(cx),
3624 inner: TypedefItem(Typedef {
3625 type_: self.ty.clean(cx),
3626 generics: self.gen.clean(cx),
3627 }, false),
3628 }
3629 }
3630 }
3631
3632 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3633 pub struct Existential {
3634 pub bounds: Vec<GenericBound>,
3635 pub generics: Generics,
3636 }
3637
3638 impl Clean<Item> for doctree::Existential {
3639 fn clean(&self, cx: &DocContext<'_>) -> Item {
3640 Item {
3641 name: Some(self.name.clean(cx)),
3642 attrs: self.attrs.clean(cx),
3643 source: self.whence.clean(cx),
3644 def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
3645 visibility: self.vis.clean(cx),
3646 stability: self.stab.clean(cx),
3647 deprecation: self.depr.clean(cx),
3648 inner: ExistentialItem(Existential {
3649 bounds: self.exist_ty.bounds.clean(cx),
3650 generics: self.exist_ty.generics.clean(cx),
3651 }, false),
3652 }
3653 }
3654 }
3655
3656 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3657 pub struct BareFunctionDecl {
3658 pub unsafety: hir::Unsafety,
3659 pub generic_params: Vec<GenericParamDef>,
3660 pub decl: FnDecl,
3661 pub abi: Abi,
3662 }
3663
3664 impl Clean<BareFunctionDecl> for hir::BareFnTy {
3665 fn clean(&self, cx: &DocContext<'_>) -> BareFunctionDecl {
3666 let (generic_params, decl) = enter_impl_trait(cx, || {
3667 (self.generic_params.clean(cx), (&*self.decl, &self.arg_names[..]).clean(cx))
3668 });
3669 BareFunctionDecl {
3670 unsafety: self.unsafety,
3671 abi: self.abi,
3672 decl,
3673 generic_params,
3674 }
3675 }
3676 }
3677
3678 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3679 pub struct Static {
3680 pub type_: Type,
3681 pub mutability: Mutability,
3682 /// It's useful to have the value of a static documented, but I have no
3683 /// desire to represent expressions (that'd basically be all of the AST,
3684 /// which is huge!). So, have a string.
3685 pub expr: String,
3686 }
3687
3688 impl Clean<Item> for doctree::Static {
3689 fn clean(&self, cx: &DocContext<'_>) -> Item {
3690 debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
3691 Item {
3692 name: Some(self.name.clean(cx)),
3693 attrs: self.attrs.clean(cx),
3694 source: self.whence.clean(cx),
3695 def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
3696 visibility: self.vis.clean(cx),
3697 stability: self.stab.clean(cx),
3698 deprecation: self.depr.clean(cx),
3699 inner: StaticItem(Static {
3700 type_: self.type_.clean(cx),
3701 mutability: self.mutability.clean(cx),
3702 expr: print_const_expr(cx, self.expr),
3703 }),
3704 }
3705 }
3706 }
3707
3708 #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
3709 pub struct Constant {
3710 pub type_: Type,
3711 pub expr: String,
3712 }
3713
3714 impl Clean<Item> for doctree::Constant {
3715 fn clean(&self, cx: &DocContext<'_>) -> Item {
3716 Item {
3717 name: Some(self.name.clean(cx)),
3718 attrs: self.attrs.clean(cx),
3719 source: self.whence.clean(cx),
3720 def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
3721 visibility: self.vis.clean(cx),
3722 stability: self.stab.clean(cx),
3723 deprecation: self.depr.clean(cx),
3724 inner: ConstantItem(Constant {
3725 type_: self.type_.clean(cx),
3726 expr: print_const_expr(cx, self.expr),
3727 }),
3728 }
3729 }
3730 }
3731
3732 #[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Copy, Hash)]
3733 pub enum Mutability {
3734 Mutable,
3735 Immutable,
3736 }
3737
3738 impl Clean<Mutability> for hir::Mutability {
3739 fn clean(&self, _: &DocContext<'_>) -> Mutability {
3740 match self {
3741 &hir::MutMutable => Mutable,
3742 &hir::MutImmutable => Immutable,
3743 }
3744 }
3745 }
3746
3747 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Copy, Debug, Hash)]
3748 pub enum ImplPolarity {
3749 Positive,
3750 Negative,
3751 }
3752
3753 impl Clean<ImplPolarity> for hir::ImplPolarity {
3754 fn clean(&self, _: &DocContext<'_>) -> ImplPolarity {
3755 match self {
3756 &hir::ImplPolarity::Positive => ImplPolarity::Positive,
3757 &hir::ImplPolarity::Negative => ImplPolarity::Negative,
3758 }
3759 }
3760 }
3761
3762 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3763 pub struct Impl {
3764 pub unsafety: hir::Unsafety,
3765 pub generics: Generics,
3766 pub provided_trait_methods: FxHashSet<String>,
3767 pub trait_: Option<Type>,
3768 pub for_: Type,
3769 pub items: Vec<Item>,
3770 pub polarity: Option<ImplPolarity>,
3771 pub synthetic: bool,
3772 pub blanket_impl: Option<Type>,
3773 }
3774
3775 pub fn get_auto_traits_with_hir_id(
3776 cx: &DocContext<'_>,
3777 id: hir::HirId,
3778 name: String
3779 ) -> Vec<Item> {
3780 let finder = AutoTraitFinder::new(cx);
3781 finder.get_with_hir_id(id, name)
3782 }
3783
3784 pub fn get_auto_traits_with_def_id(
3785 cx: &DocContext<'_>,
3786 id: DefId
3787 ) -> Vec<Item> {
3788 let finder = AutoTraitFinder::new(cx);
3789
3790 finder.get_with_def_id(id)
3791 }
3792
3793 pub fn get_blanket_impls_with_hir_id(
3794 cx: &DocContext<'_>,
3795 id: hir::HirId,
3796 name: String
3797 ) -> Vec<Item> {
3798 let finder = BlanketImplFinder::new(cx);
3799 finder.get_with_hir_id(id, name)
3800 }
3801
3802 pub fn get_blanket_impls_with_def_id(
3803 cx: &DocContext<'_>,
3804 id: DefId
3805 ) -> Vec<Item> {
3806 let finder = BlanketImplFinder::new(cx);
3807
3808 finder.get_with_def_id(id)
3809 }
3810
3811 impl Clean<Vec<Item>> for doctree::Impl {
3812 fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
3813 let mut ret = Vec::new();
3814 let trait_ = self.trait_.clean(cx);
3815 let items = self.items.clean(cx);
3816
3817 // If this impl block is an implementation of the Deref trait, then we
3818 // need to try inlining the target's inherent impl blocks as well.
3819 if trait_.def_id() == cx.tcx.lang_items().deref_trait() {
3820 build_deref_target_impls(cx, &items, &mut ret);
3821 }
3822
3823 let provided = trait_.def_id().map(|did| {
3824 cx.tcx.provided_trait_methods(did)
3825 .into_iter()
3826 .map(|meth| meth.ident.to_string())
3827 .collect()
3828 }).unwrap_or_default();
3829
3830 ret.push(Item {
3831 name: None,
3832 attrs: self.attrs.clean(cx),
3833 source: self.whence.clean(cx),
3834 def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
3835 visibility: self.vis.clean(cx),
3836 stability: self.stab.clean(cx),
3837 deprecation: self.depr.clean(cx),
3838 inner: ImplItem(Impl {
3839 unsafety: self.unsafety,
3840 generics: self.generics.clean(cx),
3841 provided_trait_methods: provided,
3842 trait_,
3843 for_: self.for_.clean(cx),
3844 items,
3845 polarity: Some(self.polarity.clean(cx)),
3846 synthetic: false,
3847 blanket_impl: None,
3848 })
3849 });
3850 ret
3851 }
3852 }
3853
3854 fn build_deref_target_impls(cx: &DocContext<'_>,
3855 items: &[Item],
3856 ret: &mut Vec<Item>) {
3857 use self::PrimitiveType::*;
3858 let tcx = cx.tcx;
3859
3860 for item in items {
3861 let target = match item.inner {
3862 TypedefItem(ref t, true) => &t.type_,
3863 _ => continue,
3864 };
3865 let primitive = match *target {
3866 ResolvedPath { did, .. } if did.is_local() => continue,
3867 ResolvedPath { did, .. } => {
3868 ret.extend(inline::build_impls(cx, did));
3869 continue
3870 }
3871 _ => match target.primitive_type() {
3872 Some(prim) => prim,
3873 None => continue,
3874 }
3875 };
3876 let did = match primitive {
3877 Isize => tcx.lang_items().isize_impl(),
3878 I8 => tcx.lang_items().i8_impl(),
3879 I16 => tcx.lang_items().i16_impl(),
3880 I32 => tcx.lang_items().i32_impl(),
3881 I64 => tcx.lang_items().i64_impl(),
3882 I128 => tcx.lang_items().i128_impl(),
3883 Usize => tcx.lang_items().usize_impl(),
3884 U8 => tcx.lang_items().u8_impl(),
3885 U16 => tcx.lang_items().u16_impl(),
3886 U32 => tcx.lang_items().u32_impl(),
3887 U64 => tcx.lang_items().u64_impl(),
3888 U128 => tcx.lang_items().u128_impl(),
3889 F32 => tcx.lang_items().f32_impl(),
3890 F64 => tcx.lang_items().f64_impl(),
3891 Char => tcx.lang_items().char_impl(),
3892 Bool => None,
3893 Str => tcx.lang_items().str_impl(),
3894 Slice => tcx.lang_items().slice_impl(),
3895 Array => tcx.lang_items().slice_impl(),
3896 Tuple => None,
3897 Unit => None,
3898 RawPointer => tcx.lang_items().const_ptr_impl(),
3899 Reference => None,
3900 Fn => None,
3901 Never => None,
3902 CVarArgs => tcx.lang_items().va_list(),
3903 };
3904 if let Some(did) = did {
3905 if !did.is_local() {
3906 inline::build_impl(cx, did, ret);
3907 }
3908 }
3909 }
3910 }
3911
3912 impl Clean<Vec<Item>> for doctree::ExternCrate {
3913 fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
3914
3915 let please_inline = self.vis.node.is_pub() && self.attrs.iter().any(|a| {
3916 a.check_name("doc") && match a.meta_item_list() {
3917 Some(l) => attr::list_contains_name(&l, "inline"),
3918 None => false,
3919 }
3920 });
3921
3922 if please_inline {
3923 let mut visited = FxHashSet::default();
3924
3925 let def = Def::Mod(DefId {
3926 krate: self.cnum,
3927 index: CRATE_DEF_INDEX,
3928 });
3929
3930 if let Some(items) = inline::try_inline(cx, def, self.name, &mut visited) {
3931 return items;
3932 }
3933 }
3934
3935 vec![Item {
3936 name: None,
3937 attrs: self.attrs.clean(cx),
3938 source: self.whence.clean(cx),
3939 def_id: DefId { krate: self.cnum, index: CRATE_DEF_INDEX },
3940 visibility: self.vis.clean(cx),
3941 stability: None,
3942 deprecation: None,
3943 inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
3944 }]
3945 }
3946 }
3947
3948 impl Clean<Vec<Item>> for doctree::Import {
3949 fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
3950 // We consider inlining the documentation of `pub use` statements, but we
3951 // forcefully don't inline if this is not public or if the
3952 // #[doc(no_inline)] attribute is present.
3953 // Don't inline doc(hidden) imports so they can be stripped at a later stage.
3954 let mut denied = !self.vis.node.is_pub() || self.attrs.iter().any(|a| {
3955 a.check_name("doc") && match a.meta_item_list() {
3956 Some(l) => attr::list_contains_name(&l, "no_inline") ||
3957 attr::list_contains_name(&l, "hidden"),
3958 None => false,
3959 }
3960 });
3961 // Also check whether imports were asked to be inlined, in case we're trying to re-export a
3962 // crate in Rust 2018+
3963 let please_inline = self.attrs.lists("doc").has_word("inline");
3964 let path = self.path.clean(cx);
3965 let inner = if self.glob {
3966 if !denied {
3967 let mut visited = FxHashSet::default();
3968 if let Some(items) = inline::try_inline_glob(cx, path.def, &mut visited) {
3969 return items;
3970 }
3971 }
3972
3973 Import::Glob(resolve_use_source(cx, path))
3974 } else {
3975 let name = self.name;
3976 if !please_inline {
3977 match path.def {
3978 Def::Mod(did) => if !did.is_local() && did.index == CRATE_DEF_INDEX {
3979 // if we're `pub use`ing an extern crate root, don't inline it unless we
3980 // were specifically asked for it
3981 denied = true;
3982 }
3983 _ => {}
3984 }
3985 }
3986 if !denied {
3987 let mut visited = FxHashSet::default();
3988 if let Some(items) = inline::try_inline(cx, path.def, name, &mut visited) {
3989 return items;
3990 }
3991 }
3992 Import::Simple(name.clean(cx), resolve_use_source(cx, path))
3993 };
3994
3995 vec![Item {
3996 name: None,
3997 attrs: self.attrs.clean(cx),
3998 source: self.whence.clean(cx),
3999 def_id: cx.tcx.hir().local_def_id(ast::CRATE_NODE_ID),
4000 visibility: self.vis.clean(cx),
4001 stability: None,
4002 deprecation: None,
4003 inner: ImportItem(inner)
4004 }]
4005 }
4006 }
4007
4008 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
4009 pub enum Import {
4010 // use source as str;
4011 Simple(String, ImportSource),
4012 // use source::*;
4013 Glob(ImportSource)
4014 }
4015
4016 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
4017 pub struct ImportSource {
4018 pub path: Path,
4019 pub did: Option<DefId>,
4020 }
4021
4022 impl Clean<Vec<Item>> for hir::ForeignMod {
4023 fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
4024 let mut items = self.items.clean(cx);
4025 for item in &mut items {
4026 if let ForeignFunctionItem(ref mut f) = item.inner {
4027 f.header.abi = self.abi;
4028 }
4029 }
4030 items
4031 }
4032 }
4033
4034 impl Clean<Item> for hir::ForeignItem {
4035 fn clean(&self, cx: &DocContext<'_>) -> Item {
4036 let inner = match self.node {
4037 hir::ForeignItemKind::Fn(ref decl, ref names, ref generics) => {
4038 let (generics, decl) = enter_impl_trait(cx, || {
4039 (generics.clean(cx), (&**decl, &names[..]).clean(cx))
4040 });
4041 let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
4042 ForeignFunctionItem(Function {
4043 decl,
4044 generics,
4045 header: hir::FnHeader {
4046 unsafety: hir::Unsafety::Unsafe,
4047 abi: Abi::Rust,
4048 constness: hir::Constness::NotConst,
4049 asyncness: hir::IsAsync::NotAsync,
4050 },
4051 all_types,
4052 ret_types,
4053 })
4054 }
4055 hir::ForeignItemKind::Static(ref ty, mutbl) => {
4056 ForeignStaticItem(Static {
4057 type_: ty.clean(cx),
4058 mutability: if mutbl {Mutable} else {Immutable},
4059 expr: String::new(),
4060 })
4061 }
4062 hir::ForeignItemKind::Type => {
4063 ForeignTypeItem
4064 }
4065 };
4066
4067 let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);
4068
4069 Item {
4070 name: Some(self.ident.clean(cx)),
4071 attrs: self.attrs.clean(cx),
4072 source: self.span.clean(cx),
4073 def_id: local_did,
4074 visibility: self.vis.clean(cx),
4075 stability: get_stability(cx, local_did),
4076 deprecation: get_deprecation(cx, local_did),
4077 inner,
4078 }
4079 }
4080 }
4081
4082 // Utilities
4083
4084 pub trait ToSource {
4085 fn to_src(&self, cx: &DocContext<'_>) -> String;
4086 }
4087
4088 impl ToSource for syntax_pos::Span {
4089 fn to_src(&self, cx: &DocContext<'_>) -> String {
4090 debug!("converting span {:?} to snippet", self.clean(cx));
4091 let sn = match cx.sess().source_map().span_to_snippet(*self) {
4092 Ok(x) => x,
4093 Err(_) => String::new()
4094 };
4095 debug!("got snippet {}", sn);
4096 sn
4097 }
4098 }
4099
4100 fn name_from_pat(p: &hir::Pat) -> String {
4101 use rustc::hir::*;
4102 debug!("Trying to get a name from pattern: {:?}", p);
4103
4104 match p.node {
4105 PatKind::Wild => "_".to_string(),
4106 PatKind::Binding(_, _, ident, _) => ident.to_string(),
4107 PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
4108 PatKind::Struct(ref name, ref fields, etc) => {
4109 format!("{} {{ {}{} }}", qpath_to_string(name),
4110 fields.iter().map(|&Spanned { node: ref fp, .. }|
4111 format!("{}: {}", fp.ident, name_from_pat(&*fp.pat)))
4112 .collect::<Vec<String>>().join(", "),
4113 if etc { ", .." } else { "" }
4114 )
4115 }
4116 PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
4117 .collect::<Vec<String>>().join(", ")),
4118 PatKind::Box(ref p) => name_from_pat(&**p),
4119 PatKind::Ref(ref p, _) => name_from_pat(&**p),
4120 PatKind::Lit(..) => {
4121 warn!("tried to get argument name from PatKind::Lit, \
4122 which is silly in function arguments");
4123 "()".to_string()
4124 },
4125 PatKind::Range(..) => panic!("tried to get argument name from PatKind::Range, \
4126 which is not allowed in function arguments"),
4127 PatKind::Slice(ref begin, ref mid, ref end) => {
4128 let begin = begin.iter().map(|p| name_from_pat(&**p));
4129 let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter();
4130 let end = end.iter().map(|p| name_from_pat(&**p));
4131 format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
4132 },
4133 }
4134 }
4135
4136 fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
4137 match n.val {
4138 ConstValue::Unevaluated(def_id, _) => {
4139 if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
4140 print_const_expr(cx, cx.tcx.hir().body_owned_by(hir_id))
4141 } else {
4142 inline::print_inlined_const(cx, def_id)
4143 }
4144 },
4145 _ => {
4146 let mut s = String::new();
4147 ::rustc::mir::fmt_const_val(&mut s, n).expect("fmt_const_val failed");
4148 // array lengths are obviously usize
4149 if s.ends_with("usize") {
4150 let n = s.len() - "usize".len();
4151 s.truncate(n);
4152 }
4153 s
4154 },
4155 }
4156 }
4157
4158 fn print_const_expr(cx: &DocContext<'_>, body: hir::BodyId) -> String {
4159 cx.tcx.hir().hir_to_pretty_string(body.hir_id)
4160 }
4161
4162 /// Given a type Path, resolve it to a Type using the TyCtxt
4163 fn resolve_type(cx: &DocContext<'_>,
4164 path: Path,
4165 id: hir::HirId) -> Type {
4166 if id == hir::DUMMY_HIR_ID {
4167 debug!("resolve_type({:?})", path);
4168 } else {
4169 debug!("resolve_type({:?},{:?})", path, id);
4170 }
4171
4172 let is_generic = match path.def {
4173 Def::PrimTy(p) => match p {
4174 hir::Str => return Primitive(PrimitiveType::Str),
4175 hir::Bool => return Primitive(PrimitiveType::Bool),
4176 hir::Char => return Primitive(PrimitiveType::Char),
4177 hir::Int(int_ty) => return Primitive(int_ty.into()),
4178 hir::Uint(uint_ty) => return Primitive(uint_ty.into()),
4179 hir::Float(float_ty) => return Primitive(float_ty.into()),
4180 },
4181 Def::SelfTy(..) if path.segments.len() == 1 => {
4182 return Generic(keywords::SelfUpper.name().to_string());
4183 }
4184 Def::TyParam(..) if path.segments.len() == 1 => {
4185 return Generic(format!("{:#}", path));
4186 }
4187 Def::SelfTy(..) | Def::TyParam(..) | Def::AssociatedTy(..) => true,
4188 _ => false,
4189 };
4190 let did = register_def(&*cx, path.def);
4191 ResolvedPath { path: path, param_names: None, did: did, is_generic: is_generic }
4192 }
4193
4194 pub fn register_def(cx: &DocContext<'_>, def: Def) -> DefId {
4195 debug!("register_def({:?})", def);
4196
4197 let (did, kind) = match def {
4198 Def::Fn(i) => (i, TypeKind::Function),
4199 Def::TyAlias(i) => (i, TypeKind::Typedef),
4200 Def::Enum(i) => (i, TypeKind::Enum),
4201 Def::Trait(i) => (i, TypeKind::Trait),
4202 Def::Struct(i) => (i, TypeKind::Struct),
4203 Def::Union(i) => (i, TypeKind::Union),
4204 Def::Mod(i) => (i, TypeKind::Module),
4205 Def::ForeignTy(i) => (i, TypeKind::Foreign),
4206 Def::Const(i) => (i, TypeKind::Const),
4207 Def::Static(i, _) => (i, TypeKind::Static),
4208 Def::Variant(i) => (cx.tcx.parent(i).expect("cannot get parent def id"),
4209 TypeKind::Enum),
4210 Def::Macro(i, mac_kind) => match mac_kind {
4211 MacroKind::Bang => (i, TypeKind::Macro),
4212 MacroKind::Attr => (i, TypeKind::Attr),
4213 MacroKind::Derive => (i, TypeKind::Derive),
4214 MacroKind::ProcMacroStub => unreachable!(),
4215 },
4216 Def::TraitAlias(i) => (i, TypeKind::TraitAlias),
4217 Def::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
4218 Def::SelfTy(_, Some(impl_def_id)) => return impl_def_id,
4219 _ => return def.def_id()
4220 };
4221 if did.is_local() { return did }
4222 inline::record_extern_fqn(cx, did, kind);
4223 if let TypeKind::Trait = kind {
4224 inline::record_extern_trait(cx, did);
4225 }
4226 did
4227 }
4228
4229 fn resolve_use_source(cx: &DocContext<'_>, path: Path) -> ImportSource {
4230 ImportSource {
4231 did: if path.def.opt_def_id().is_none() {
4232 None
4233 } else {
4234 Some(register_def(cx, path.def))
4235 },
4236 path,
4237 }
4238 }
4239
4240 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
4241 pub struct Macro {
4242 pub source: String,
4243 pub imported_from: Option<String>,
4244 }
4245
4246 impl Clean<Item> for doctree::Macro {
4247 fn clean(&self, cx: &DocContext<'_>) -> Item {
4248 let name = self.name.clean(cx);
4249 Item {
4250 name: Some(name.clone()),
4251 attrs: self.attrs.clean(cx),
4252 source: self.whence.clean(cx),
4253 visibility: Some(Public),
4254 stability: self.stab.clean(cx),
4255 deprecation: self.depr.clean(cx),
4256 def_id: self.def_id,
4257 inner: MacroItem(Macro {
4258 source: format!("macro_rules! {} {{\n{}}}",
4259 name,
4260 self.matchers.iter().map(|span| {
4261 format!(" {} => {{ ... }};\n", span.to_src(cx))
4262 }).collect::<String>()),
4263 imported_from: self.imported_from.clean(cx),
4264 }),
4265 }
4266 }
4267 }
4268
4269 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
4270 pub struct ProcMacro {
4271 pub kind: MacroKind,
4272 pub helpers: Vec<String>,
4273 }
4274
4275 impl Clean<Item> for doctree::ProcMacro {
4276 fn clean(&self, cx: &DocContext<'_>) -> Item {
4277 Item {
4278 name: Some(self.name.clean(cx)),
4279 attrs: self.attrs.clean(cx),
4280 source: self.whence.clean(cx),
4281 visibility: Some(Public),
4282 stability: self.stab.clean(cx),
4283 deprecation: self.depr.clean(cx),
4284 def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
4285 inner: ProcMacroItem(ProcMacro {
4286 kind: self.kind,
4287 helpers: self.helpers.clean(cx),
4288 }),
4289 }
4290 }
4291 }
4292
4293 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
4294 pub struct Stability {
4295 pub level: stability::StabilityLevel,
4296 pub feature: Option<String>,
4297 pub since: String,
4298 pub deprecation: Option<Deprecation>,
4299 pub unstable_reason: Option<String>,
4300 pub issue: Option<u32>,
4301 }
4302
4303 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
4304 pub struct Deprecation {
4305 pub since: Option<String>,
4306 pub note: Option<String>,
4307 }
4308
4309 impl Clean<Stability> for attr::Stability {
4310 fn clean(&self, _: &DocContext<'_>) -> Stability {
4311 Stability {
4312 level: stability::StabilityLevel::from_attr_level(&self.level),
4313 feature: Some(self.feature.to_string()).filter(|f| !f.is_empty()),
4314 since: match self.level {
4315 attr::Stable {ref since} => since.to_string(),
4316 _ => String::new(),
4317 },
4318 deprecation: self.rustc_depr.as_ref().map(|d| {
4319 Deprecation {
4320 note: Some(d.reason.to_string()).filter(|r| !r.is_empty()),
4321 since: Some(d.since.to_string()).filter(|d| !d.is_empty()),
4322 }
4323 }),
4324 unstable_reason: match self.level {
4325 attr::Unstable { reason: Some(ref reason), .. } => Some(reason.to_string()),
4326 _ => None,
4327 },
4328 issue: match self.level {
4329 attr::Unstable {issue, ..} => Some(issue),
4330 _ => None,
4331 }
4332 }
4333 }
4334 }
4335
4336 impl<'a> Clean<Stability> for &'a attr::Stability {
4337 fn clean(&self, dc: &DocContext<'_>) -> Stability {
4338 (**self).clean(dc)
4339 }
4340 }
4341
4342 impl Clean<Deprecation> for attr::Deprecation {
4343 fn clean(&self, _: &DocContext<'_>) -> Deprecation {
4344 Deprecation {
4345 since: self.since.map(|s| s.to_string()).filter(|s| !s.is_empty()),
4346 note: self.note.map(|n| n.to_string()).filter(|n| !n.is_empty()),
4347 }
4348 }
4349 }
4350
4351 /// An equality constraint on an associated type, e.g., `A = Bar` in `Foo<A = Bar>`
4352 #[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug, Hash)]
4353 pub struct TypeBinding {
4354 pub name: String,
4355 pub ty: Type
4356 }
4357
4358 impl Clean<TypeBinding> for hir::TypeBinding {
4359 fn clean(&self, cx: &DocContext<'_>) -> TypeBinding {
4360 TypeBinding {
4361 name: self.ident.name.clean(cx),
4362 ty: self.ty.clean(cx)
4363 }
4364 }
4365 }
4366
4367 pub fn def_id_to_path(
4368 cx: &DocContext<'_>,
4369 did: DefId,
4370 name: Option<String>
4371 ) -> Vec<String> {
4372 let crate_name = name.unwrap_or_else(|| cx.tcx.crate_name(did.krate).to_string());
4373 let relative = cx.tcx.def_path(did).data.into_iter().filter_map(|elem| {
4374 // extern blocks have an empty name
4375 let s = elem.data.to_string();
4376 if !s.is_empty() {
4377 Some(s)
4378 } else {
4379 None
4380 }
4381 });
4382 once(crate_name).chain(relative).collect()
4383 }
4384
4385 pub fn enter_impl_trait<F, R>(cx: &DocContext<'_>, f: F) -> R
4386 where
4387 F: FnOnce() -> R,
4388 {
4389 let old_bounds = mem::replace(&mut *cx.impl_trait_bounds.borrow_mut(), Default::default());
4390 let r = f();
4391 assert!(cx.impl_trait_bounds.borrow().is_empty());
4392 *cx.impl_trait_bounds.borrow_mut() = old_bounds;
4393 r
4394 }
4395
4396 // Start of code copied from rust-clippy
4397
4398 pub fn path_to_def_local(tcx: &TyCtxt<'_, '_, '_>, path: &[&str]) -> Option<DefId> {
4399 let krate = tcx.hir().krate();
4400 let mut items = krate.module.item_ids.clone();
4401 let mut path_it = path.iter().peekable();
4402
4403 loop {
4404 let segment = path_it.next()?;
4405
4406 for item_id in mem::replace(&mut items, HirVec::new()).iter() {
4407 let item = tcx.hir().expect_item_by_hir_id(item_id.id);
4408 if item.ident.name == *segment {
4409 if path_it.peek().is_none() {
4410 return Some(tcx.hir().local_def_id_from_hir_id(item_id.id))
4411 }
4412
4413 items = match &item.node {
4414 &hir::ItemKind::Mod(ref m) => m.item_ids.clone(),
4415 _ => panic!("Unexpected item {:?} in path {:?} path")
4416 };
4417 break;
4418 }
4419 }
4420 }
4421 }
4422
4423 pub fn path_to_def(tcx: &TyCtxt<'_, '_, '_>, path: &[&str]) -> Option<DefId> {
4424 let crates = tcx.crates();
4425
4426 let krate = crates
4427 .iter()
4428 .find(|&&krate| tcx.crate_name(krate) == path[0]);
4429
4430 if let Some(krate) = krate {
4431 let krate = DefId {
4432 krate: *krate,
4433 index: CRATE_DEF_INDEX,
4434 };
4435 let mut items = tcx.item_children(krate);
4436 let mut path_it = path.iter().skip(1).peekable();
4437
4438 loop {
4439 let segment = path_it.next()?;
4440
4441 for item in mem::replace(&mut items, Lrc::new(vec![])).iter() {
4442 if item.ident.name == *segment {
4443 if path_it.peek().is_none() {
4444 return match item.def {
4445 def::Def::Trait(did) => Some(did),
4446 _ => None,
4447 }
4448 }
4449
4450 items = tcx.item_children(item.def.def_id());
4451 break;
4452 }
4453 }
4454 }
4455 } else {
4456 None
4457 }
4458 }
4459
4460 pub fn get_path_for_type(
4461 tcx: TyCtxt<'_, '_, '_>,
4462 def_id: DefId,
4463 def_ctor: impl Fn(DefId) -> Def,
4464 ) -> hir::Path {
4465 use rustc::ty::print::Printer;
4466
4467 struct AbsolutePathPrinter<'a, 'tcx> {
4468 tcx: TyCtxt<'a, 'tcx, 'tcx>,
4469 }
4470
4471 impl Printer<'tcx, 'tcx> for AbsolutePathPrinter<'_, 'tcx> {
4472 type Error = !;
4473
4474 type Path = Vec<String>;
4475 type Region = ();
4476 type Type = ();
4477 type DynExistential = ();
4478
4479 fn tcx(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
4480 self.tcx
4481 }
4482
4483 fn print_region(
4484 self,
4485 _region: ty::Region<'_>,
4486 ) -> Result<Self::Region, Self::Error> {
4487 Ok(())
4488 }
4489
4490 fn print_type(
4491 self,
4492 _ty: Ty<'tcx>,
4493 ) -> Result<Self::Type, Self::Error> {
4494 Ok(())
4495 }
4496
4497 fn print_dyn_existential(
4498 self,
4499 _predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
4500 ) -> Result<Self::DynExistential, Self::Error> {
4501 Ok(())
4502 }
4503
4504 fn path_crate(
4505 self,
4506 cnum: CrateNum,
4507 ) -> Result<Self::Path, Self::Error> {
4508 Ok(vec![self.tcx.original_crate_name(cnum).to_string()])
4509 }
4510 fn path_qualified(
4511 self,
4512 self_ty: Ty<'tcx>,
4513 trait_ref: Option<ty::TraitRef<'tcx>>,
4514 ) -> Result<Self::Path, Self::Error> {
4515 // This shouldn't ever be needed, but just in case:
4516 Ok(vec![match trait_ref {
4517 Some(trait_ref) => format!("{:?}", trait_ref),
4518 None => format!("<{}>", self_ty),
4519 }])
4520 }
4521
4522 fn path_append_impl(
4523 self,
4524 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
4525 _disambiguated_data: &DisambiguatedDefPathData,
4526 self_ty: Ty<'tcx>,
4527 trait_ref: Option<ty::TraitRef<'tcx>>,
4528 ) -> Result<Self::Path, Self::Error> {
4529 let mut path = print_prefix(self)?;
4530
4531 // This shouldn't ever be needed, but just in case:
4532 path.push(match trait_ref {
4533 Some(trait_ref) => {
4534 format!("<impl {} for {}>", trait_ref, self_ty)
4535 }
4536 None => format!("<impl {}>", self_ty),
4537 });
4538
4539 Ok(path)
4540 }
4541 fn path_append(
4542 self,
4543 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
4544 disambiguated_data: &DisambiguatedDefPathData,
4545 ) -> Result<Self::Path, Self::Error> {
4546 let mut path = print_prefix(self)?;
4547 path.push(disambiguated_data.data.as_interned_str().to_string());
4548 Ok(path)
4549 }
4550 fn path_generic_args(
4551 self,
4552 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
4553 _args: &[Kind<'tcx>],
4554 ) -> Result<Self::Path, Self::Error> {
4555 print_prefix(self)
4556 }
4557 }
4558
4559 let names = AbsolutePathPrinter { tcx: tcx.global_tcx() }
4560 .print_def_path(def_id, &[])
4561 .unwrap();
4562
4563 hir::Path {
4564 span: DUMMY_SP,
4565 def: def_ctor(def_id),
4566 segments: hir::HirVec::from_vec(names.iter().map(|s| hir::PathSegment {
4567 ident: ast::Ident::from_str(&s),
4568 hir_id: None,
4569 def: None,
4570 args: None,
4571 infer_types: false,
4572 }).collect())
4573 }
4574 }
4575
4576 // End of code copied from rust-clippy
4577
4578
4579 #[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
4580 enum RegionTarget<'tcx> {
4581 Region(Region<'tcx>),
4582 RegionVid(RegionVid)
4583 }
4584
4585 #[derive(Default, Debug, Clone)]
4586 struct RegionDeps<'tcx> {
4587 larger: FxHashSet<RegionTarget<'tcx>>,
4588 smaller: FxHashSet<RegionTarget<'tcx>>
4589 }
4590
4591 #[derive(Eq, PartialEq, Hash, Debug)]
4592 enum SimpleBound {
4593 TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier),
4594 Outlives(Lifetime),
4595 }
4596
4597 enum AutoTraitResult {
4598 ExplicitImpl,
4599 PositiveImpl(Generics),
4600 NegativeImpl,
4601 }
4602
4603 impl AutoTraitResult {
4604 fn is_auto(&self) -> bool {
4605 match *self {
4606 AutoTraitResult::PositiveImpl(_) | AutoTraitResult::NegativeImpl => true,
4607 _ => false,
4608 }
4609 }
4610 }
4611
4612 impl From<GenericBound> for SimpleBound {
4613 fn from(bound: GenericBound) -> Self {
4614 match bound.clone() {
4615 GenericBound::Outlives(l) => SimpleBound::Outlives(l),
4616 GenericBound::TraitBound(t, mod_) => match t.trait_ {
4617 Type::ResolvedPath { path, param_names, .. } => {
4618 SimpleBound::TraitBound(path.segments,
4619 param_names
4620 .map_or_else(|| Vec::new(), |v| v.iter()
4621 .map(|p| SimpleBound::from(p.clone()))
4622 .collect()),
4623 t.generic_params,
4624 mod_)
4625 }
4626 _ => panic!("Unexpected bound {:?}", bound),
4627 }
4628 }
4629 }
4630 }