1 use std::cell::RefCell;
2 use std::default::Default;
4 use std::hash::{Hash, Hasher};
5 use std::iter::FromIterator;
6 use std::num::NonZeroU32;
11 use rustc::middle::lang_items;
12 use rustc::middle::stability;
13 use rustc::ty::layout::VariantIdx;
14 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
16 use rustc_hir::def::Res;
17 use rustc_hir::def_id::{CrateNum, DefId};
18 use rustc_hir::Mutability;
19 use rustc_index::vec::IndexVec;
20 use rustc_span::hygiene::MacroKind;
21 use rustc_span::source_map::DUMMY_SP;
22 use rustc_span::symbol::{sym, Symbol};
23 use rustc_span::{self, FileName};
24 use rustc_target::spec::abi::Abi;
25 use syntax::ast::{self, AttrStyle, Ident};
27 use syntax::util::comments::strip_doc_comment_decoration;
29 use crate::clean::cfg::Cfg;
30 use crate::clean::external_path;
31 use crate::clean::inline;
32 use crate::clean::types::Type::{QPath, ResolvedPath};
33 use crate::core::DocContext;
35 use crate::html::item_type::ItemType;
36 use crate::html::render::{cache, ExternalLocation};
39 use self::ItemEnum::*;
43 thread_local!(pub static MAX_DEF_ID: RefCell<FxHashMap<CrateNum, DefId>> = Default::default());
45 #[derive(Clone, Debug)]
48 pub version: Option<String>,
50 pub module: Option<Item>,
51 pub externs: Vec<(CrateNum, ExternalCrate)>,
52 pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
53 // These are later on moved into `CACHEKEY`, leaving the map empty.
54 // Only here so that they can be filtered through the rustdoc passes.
55 pub external_traits: Rc<RefCell<FxHashMap<DefId, Trait>>>,
56 pub masked_crates: FxHashSet<CrateNum>,
60 #[derive(Clone, Debug)]
61 pub struct ExternalCrate {
64 pub attrs: Attributes,
65 pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
66 pub keywords: Vec<(DefId, String, Attributes)>,
69 /// Anything with a source location and set of attributes and, optionally, a
70 /// name. That is, anything that can be documented. This doesn't correspond
71 /// directly to the AST's concept of an item; it's a strict superset.
76 /// Not everything has a name. E.g., impls
77 pub name: Option<String>,
78 pub attrs: Attributes,
80 pub visibility: Visibility,
82 pub stability: Option<Stability>,
83 pub deprecation: Option<Deprecation>,
86 impl fmt::Debug for Item {
87 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
88 let fake = MAX_DEF_ID.with(|m| {
89 m.borrow().get(&self.def_id.krate).map(|id| self.def_id >= *id).unwrap_or(false)
91 let def_id: &dyn fmt::Debug = if fake { &"**FAKE**" } else { &self.def_id };
93 fmt.debug_struct("Item")
94 .field("source", &self.source)
95 .field("name", &self.name)
96 .field("attrs", &self.attrs)
97 .field("inner", &self.inner)
98 .field("visibility", &self.visibility)
99 .field("def_id", def_id)
100 .field("stability", &self.stability)
101 .field("deprecation", &self.deprecation)
107 /// Finds the `doc` attribute as a NameValue and returns the corresponding
109 pub fn doc_value(&self) -> Option<&str> {
110 self.attrs.doc_value()
113 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
115 pub fn collapsed_doc_value(&self) -> Option<String> {
116 self.attrs.collapsed_doc_value()
119 pub fn links(&self) -> Vec<(String, String)> {
120 self.attrs.links(&self.def_id.krate)
123 pub fn is_crate(&self) -> bool {
125 StrippedItem(box ModuleItem(Module { is_crate: true, .. }))
126 | ModuleItem(Module { is_crate: true, .. }) => true,
130 pub fn is_mod(&self) -> bool {
131 self.type_() == ItemType::Module
133 pub fn is_trait(&self) -> bool {
134 self.type_() == ItemType::Trait
136 pub fn is_struct(&self) -> bool {
137 self.type_() == ItemType::Struct
139 pub fn is_enum(&self) -> bool {
140 self.type_() == ItemType::Enum
142 pub fn is_variant(&self) -> bool {
143 self.type_() == ItemType::Variant
145 pub fn is_associated_type(&self) -> bool {
146 self.type_() == ItemType::AssocType
148 pub fn is_associated_const(&self) -> bool {
149 self.type_() == ItemType::AssocConst
151 pub fn is_method(&self) -> bool {
152 self.type_() == ItemType::Method
154 pub fn is_ty_method(&self) -> bool {
155 self.type_() == ItemType::TyMethod
157 pub fn is_typedef(&self) -> bool {
158 self.type_() == ItemType::Typedef
160 pub fn is_primitive(&self) -> bool {
161 self.type_() == ItemType::Primitive
163 pub fn is_union(&self) -> bool {
164 self.type_() == ItemType::Union
166 pub fn is_import(&self) -> bool {
167 self.type_() == ItemType::Import
169 pub fn is_extern_crate(&self) -> bool {
170 self.type_() == ItemType::ExternCrate
172 pub fn is_keyword(&self) -> bool {
173 self.type_() == ItemType::Keyword
175 pub fn is_stripped(&self) -> bool {
177 StrippedItem(..) => true,
181 pub fn has_stripped_fields(&self) -> Option<bool> {
183 StructItem(ref _struct) => Some(_struct.fields_stripped),
184 UnionItem(ref union) => Some(union.fields_stripped),
185 VariantItem(Variant { kind: VariantKind::Struct(ref vstruct) }) => {
186 Some(vstruct.fields_stripped)
192 pub fn stability_class(&self) -> Option<String> {
193 self.stability.as_ref().and_then(|ref s| {
194 let mut classes = Vec::with_capacity(2);
196 if s.level == stability::Unstable {
197 classes.push("unstable");
200 if s.deprecation.is_some() {
201 classes.push("deprecated");
204 if classes.len() != 0 { Some(classes.join(" ")) } else { None }
208 pub fn stable_since(&self) -> Option<&str> {
209 self.stability.as_ref().map(|s| &s.since[..])
212 pub fn is_non_exhaustive(&self) -> bool {
213 self.attrs.other_attrs.iter().any(|a| a.check_name(sym::non_exhaustive))
216 /// Returns a documentation-level item type from the item.
217 pub fn type_(&self) -> ItemType {
221 /// Returns the info in the item's `#[deprecated]` or `#[rustc_deprecated]` attributes.
223 /// If the item is not deprecated, returns `None`.
224 pub fn deprecation(&self) -> Option<&Deprecation> {
227 .or_else(|| self.stability.as_ref().and_then(|s| s.deprecation.as_ref()))
229 pub fn is_default(&self) -> bool {
231 ItemEnum::MethodItem(ref meth) => {
232 if let Some(defaultness) = meth.defaultness {
233 defaultness.has_value() && !defaultness.is_final()
243 #[derive(Clone, Debug)]
245 ExternCrateItem(String, Option<String>),
250 FunctionItem(Function),
252 TypedefItem(Typedef, bool /* is associated type */),
253 OpaqueTyItem(OpaqueTy, bool /* is associated type */),
255 ConstantItem(Constant),
257 TraitAliasItem(TraitAlias),
259 /// A method signature only. Used for required methods in traits (ie,
260 /// non-default-methods).
261 TyMethodItem(TyMethod),
262 /// A method with a body.
264 StructFieldItem(Type),
265 VariantItem(Variant),
266 /// `fn`s from an extern block
267 ForeignFunctionItem(Function),
268 /// `static`s from an extern block
269 ForeignStaticItem(Static),
270 /// `type`s from an extern block
273 ProcMacroItem(ProcMacro),
274 PrimitiveItem(PrimitiveType),
275 AssocConstItem(Type, Option<String>),
276 AssocTypeItem(Vec<GenericBound>, Option<Type>),
277 /// An item that has been stripped by a rustdoc pass
278 StrippedItem(Box<ItemEnum>),
283 pub fn is_associated(&self) -> bool {
285 ItemEnum::TypedefItem(_, _) | ItemEnum::AssocTypeItem(_, _) => true,
291 #[derive(Clone, Debug)]
293 pub items: Vec<Item>,
297 pub struct ListAttributesIter<'a> {
298 attrs: slice::Iter<'a, ast::Attribute>,
299 current_list: vec::IntoIter<ast::NestedMetaItem>,
303 impl<'a> Iterator for ListAttributesIter<'a> {
304 type Item = ast::NestedMetaItem;
306 fn next(&mut self) -> Option<Self::Item> {
307 if let Some(nested) = self.current_list.next() {
311 for attr in &mut self.attrs {
312 if let Some(list) = attr.meta_item_list() {
313 if attr.check_name(self.name) {
314 self.current_list = list.into_iter();
315 if let Some(nested) = self.current_list.next() {
325 fn size_hint(&self) -> (usize, Option<usize>) {
326 let lower = self.current_list.len();
331 pub trait AttributesExt {
332 /// Finds an attribute as List and returns the list of attributes nested inside.
333 fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
336 impl AttributesExt for [ast::Attribute] {
337 fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
338 ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), name }
342 pub trait NestedAttributesExt {
343 /// Returns `true` if the attribute list contains a specific `Word`
344 fn has_word(self, word: Symbol) -> bool;
347 impl<I: IntoIterator<Item = ast::NestedMetaItem>> NestedAttributesExt for I {
348 fn has_word(self, word: Symbol) -> bool {
349 self.into_iter().any(|attr| attr.is_word() && attr.check_name(word))
353 /// A portion of documentation, extracted from a `#[doc]` attribute.
355 /// Each variant contains the line number within the complete doc-comment where the fragment
356 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
358 /// Included files are kept separate from inline doc comments so that proper line-number
359 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
360 /// kept separate because of issue #42760.
361 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
362 pub enum DocFragment {
363 /// A doc fragment created from a `///` or `//!` doc comment.
364 SugaredDoc(usize, rustc_span::Span, String),
365 /// A doc fragment created from a "raw" `#[doc=""]` attribute.
366 RawDoc(usize, rustc_span::Span, String),
367 /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
368 /// given filename and the file contents.
369 Include(usize, rustc_span::Span, String, String),
373 pub fn as_str(&self) -> &str {
375 DocFragment::SugaredDoc(_, _, ref s) => &s[..],
376 DocFragment::RawDoc(_, _, ref s) => &s[..],
377 DocFragment::Include(_, _, _, ref s) => &s[..],
381 pub fn span(&self) -> rustc_span::Span {
383 DocFragment::SugaredDoc(_, span, _)
384 | DocFragment::RawDoc(_, span, _)
385 | DocFragment::Include(_, span, _, _) => span,
390 impl<'a> FromIterator<&'a DocFragment> for String {
391 fn from_iter<T>(iter: T) -> Self
393 T: IntoIterator<Item = &'a DocFragment>,
395 iter.into_iter().fold(String::new(), |mut acc, frag| {
400 DocFragment::SugaredDoc(_, _, ref docs)
401 | DocFragment::RawDoc(_, _, ref docs)
402 | DocFragment::Include(_, _, _, ref docs) => acc.push_str(docs),
410 #[derive(Clone, Debug, Default)]
411 pub struct Attributes {
412 pub doc_strings: Vec<DocFragment>,
413 pub other_attrs: Vec<ast::Attribute>,
414 pub cfg: Option<Arc<Cfg>>,
415 pub span: Option<rustc_span::Span>,
416 /// map from Rust paths to resolved defs and potential URL fragments
417 pub links: Vec<(String, Option<DefId>, Option<String>)>,
418 pub inner_docs: bool,
422 /// Extracts the content from an attribute `#[doc(cfg(content))]`.
423 pub fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
424 use syntax::ast::NestedMetaItem::MetaItem;
426 if let ast::MetaItemKind::List(ref nmis) = mi.kind {
428 if let MetaItem(ref cfg_mi) = nmis[0] {
429 if cfg_mi.check_name(sym::cfg) {
430 if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.kind {
431 if cfg_nmis.len() == 1 {
432 if let MetaItem(ref content_mi) = cfg_nmis[0] {
433 return Some(content_mi);
445 /// Reads a `MetaItem` from within an attribute, looks for whether it is a
446 /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
448 pub fn extract_include(mi: &ast::MetaItem) -> Option<(String, String)> {
449 mi.meta_item_list().and_then(|list| {
451 if meta.check_name(sym::include) {
452 // the actual compiled `#[doc(include="filename")]` gets expanded to
453 // `#[doc(include(file="filename", contents="file contents")]` so we need to
454 // look for that instead
455 return meta.meta_item_list().and_then(|list| {
456 let mut filename: Option<String> = None;
457 let mut contents: Option<String> = None;
460 if it.check_name(sym::file) {
461 if let Some(name) = it.value_str() {
462 filename = Some(name.to_string());
464 } else if it.check_name(sym::contents) {
465 if let Some(docs) = it.value_str() {
466 contents = Some(docs.to_string());
471 if let (Some(filename), Some(contents)) = (filename, contents) {
472 Some((filename, contents))
484 pub fn has_doc_flag(&self, flag: Symbol) -> bool {
485 for attr in &self.other_attrs {
486 if !attr.check_name(sym::doc) {
490 if let Some(items) = attr.meta_item_list() {
491 if items.iter().filter_map(|i| i.meta_item()).any(|it| it.check_name(flag)) {
500 pub fn from_ast(diagnostic: &::rustc_errors::Handler, attrs: &[ast::Attribute]) -> Attributes {
501 let mut doc_strings = vec![];
503 let mut cfg = Cfg::True;
504 let mut doc_line = 0;
506 let other_attrs = attrs
509 if let Some(value) = attr.doc_str() {
510 let (value, mk_fragment): (_, fn(_, _, _) -> _) = if attr.is_doc_comment() {
511 (strip_doc_comment_decoration(&value.as_str()), DocFragment::SugaredDoc)
513 (value.to_string(), DocFragment::RawDoc)
517 doc_line += value.lines().count();
518 doc_strings.push(mk_fragment(line, attr.span, value));
521 sp = Some(attr.span);
525 if attr.check_name(sym::doc) {
526 if let Some(mi) = attr.meta() {
527 if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
528 // Extracted #[doc(cfg(...))]
529 match Cfg::parse(cfg_mi) {
530 Ok(new_cfg) => cfg &= new_cfg,
531 Err(e) => diagnostic.span_err(e.span, e.msg),
533 } else if let Some((filename, contents)) =
534 Attributes::extract_include(&mi)
537 doc_line += contents.lines().count();
538 doc_strings.push(DocFragment::Include(
539 line, attr.span, filename, contents,
549 // treat #[target_feature(enable = "feat")] attributes as if they were
550 // #[doc(cfg(target_feature = "feat"))] attributes as well
551 for attr in attrs.lists(sym::target_feature) {
552 if attr.check_name(sym::enable) {
553 if let Some(feat) = attr.value_str() {
554 let meta = attr::mk_name_value_item_str(
555 Ident::with_dummy_span(sym::target_feature),
559 if let Ok(feat_cfg) = Cfg::parse(&meta) {
566 let inner_docs = attrs
568 .find(|a| a.doc_str().is_some())
569 .map_or(true, |a| a.style == AttrStyle::Inner);
574 cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) },
581 /// Finds the `doc` attribute as a NameValue and returns the corresponding
583 pub fn doc_value(&self) -> Option<&str> {
584 self.doc_strings.first().map(|s| s.as_str())
587 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
589 pub fn collapsed_doc_value(&self) -> Option<String> {
590 if !self.doc_strings.is_empty() { Some(self.doc_strings.iter().collect()) } else { None }
593 /// Gets links as a vector
595 /// Cache must be populated before call
596 pub fn links(&self, krate: &CrateNum) -> Vec<(String, String)> {
597 use crate::html::format::href;
601 .filter_map(|&(ref s, did, ref fragment)| {
604 if let Some((mut href, ..)) = href(did) {
605 if let Some(ref fragment) = *fragment {
607 href.push_str(fragment);
609 Some((s.clone(), href))
615 if let Some(ref fragment) = *fragment {
617 let url = match cache.extern_locations.get(krate) {
618 Some(&(_, ref src, ExternalLocation::Local)) => {
619 src.to_str().expect("invalid file path")
621 Some(&(_, _, ExternalLocation::Remote(ref s))) => s,
622 Some(&(_, _, ExternalLocation::Unknown)) | None => {
623 "https://doc.rust-lang.org/nightly"
626 // This is a primitive so the url is done "by hand".
627 let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
631 "{}{}std/primitive.{}.html{}",
633 if !url.ends_with('/') { "/" } else { "" },
639 panic!("This isn't a primitive?!");
648 impl PartialEq for Attributes {
649 fn eq(&self, rhs: &Self) -> bool {
650 self.doc_strings == rhs.doc_strings
651 && self.cfg == rhs.cfg
652 && self.span == rhs.span
653 && self.links == rhs.links
658 .eq(rhs.other_attrs.iter().map(|attr| attr.id))
662 impl Eq for Attributes {}
664 impl Hash for Attributes {
665 fn hash<H: Hasher>(&self, hasher: &mut H) {
666 self.doc_strings.hash(hasher);
667 self.cfg.hash(hasher);
668 self.span.hash(hasher);
669 self.links.hash(hasher);
670 for attr in &self.other_attrs {
671 attr.id.hash(hasher);
676 impl AttributesExt for Attributes {
677 fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
678 self.other_attrs.lists(name)
682 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
683 pub enum GenericBound {
684 TraitBound(PolyTrait, hir::TraitBoundModifier),
689 pub fn maybe_sized(cx: &DocContext<'_>) -> GenericBound {
690 let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None);
691 let empty = cx.tcx.intern_substs(&[]);
692 let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
693 inline::record_extern_fqn(cx, did, TypeKind::Trait);
694 GenericBound::TraitBound(
696 trait_: ResolvedPath { path, param_names: None, did, is_generic: false },
697 generic_params: Vec::new(),
699 hir::TraitBoundModifier::Maybe,
703 pub fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
704 use rustc_hir::TraitBoundModifier as TBM;
705 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
706 if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
713 pub fn get_poly_trait(&self) -> Option<PolyTrait> {
714 if let GenericBound::TraitBound(ref p, _) = *self {
715 return Some(p.clone());
720 pub fn get_trait_type(&self) -> Option<Type> {
721 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
729 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
730 pub struct Lifetime(pub String);
733 pub fn get_ref<'a>(&'a self) -> &'a str {
734 let Lifetime(ref s) = *self;
739 pub fn statik() -> Lifetime {
740 Lifetime("'static".to_string())
744 #[derive(Clone, Debug)]
745 pub enum WherePredicate {
746 BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
747 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
748 EqPredicate { lhs: Type, rhs: Type },
751 impl WherePredicate {
752 pub fn get_bounds(&self) -> Option<&[GenericBound]> {
754 WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
755 WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
761 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
762 pub enum GenericParamDefKind {
766 bounds: Vec<GenericBound>,
767 default: Option<Type>,
768 synthetic: Option<hir::SyntheticTyParamKind>,
776 impl GenericParamDefKind {
777 pub fn is_type(&self) -> bool {
779 GenericParamDefKind::Type { .. } => true,
784 // FIXME(eddyb) this either returns the default of a type parameter, or the
785 // type of a `const` parameter. It seems that the intention is to *visit*
786 // any embedded types, but `get_type` seems to be the wrong name for that.
787 pub fn get_type(&self) -> Option<Type> {
789 GenericParamDefKind::Type { default, .. } => default.clone(),
790 GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
791 GenericParamDefKind::Lifetime => None,
796 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
797 pub struct GenericParamDef {
799 pub kind: GenericParamDefKind,
802 impl GenericParamDef {
803 pub fn is_synthetic_type_param(&self) -> bool {
805 GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => false,
806 GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
810 pub fn is_type(&self) -> bool {
814 pub fn get_type(&self) -> Option<Type> {
818 pub fn get_bounds(&self) -> Option<&[GenericBound]> {
820 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
826 // maybe use a Generic enum and use Vec<Generic>?
827 #[derive(Clone, Debug, Default)]
828 pub struct Generics {
829 pub params: Vec<GenericParamDef>,
830 pub where_predicates: Vec<WherePredicate>,
833 #[derive(Clone, Debug)]
835 pub generics: Generics,
837 pub header: hir::FnHeader,
838 pub defaultness: Option<hir::Defaultness>,
839 pub all_types: Vec<Type>,
840 pub ret_types: Vec<Type>,
843 #[derive(Clone, Debug)]
844 pub struct TyMethod {
845 pub header: hir::FnHeader,
847 pub generics: Generics,
848 pub all_types: Vec<Type>,
849 pub ret_types: Vec<Type>,
852 #[derive(Clone, Debug)]
853 pub struct Function {
855 pub generics: Generics,
856 pub header: hir::FnHeader,
857 pub all_types: Vec<Type>,
858 pub ret_types: Vec<Type>,
861 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
863 pub inputs: Arguments,
865 pub c_variadic: bool,
866 pub attrs: Attributes,
870 pub fn self_type(&self) -> Option<SelfTy> {
871 self.inputs.values.get(0).and_then(|v| v.to_self())
874 /// Returns the sugared return type for an async function.
876 /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
877 /// will return `i32`.
881 /// This function will panic if the return type does not match the expected sugaring for async
883 pub fn sugared_async_return_type(&self) -> FnRetTy {
885 FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
886 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
887 let bindings = trait_.bindings().unwrap();
888 FnRetTy::Return(bindings[0].ty().clone())
890 _ => panic!("unexpected desugaring of async function"),
892 _ => panic!("unexpected desugaring of async function"),
897 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
898 pub struct Arguments {
899 pub values: Vec<Argument>,
902 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
903 pub struct Argument {
908 #[derive(Clone, PartialEq, Debug)]
911 SelfBorrowed(Option<Lifetime>, Mutability),
916 pub fn to_self(&self) -> Option<SelfTy> {
917 if self.name != "self" {
920 if self.type_.is_self_type() {
921 return Some(SelfValue);
924 BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
925 Some(SelfBorrowed(lifetime.clone(), mutability))
927 _ => Some(SelfExplicit(self.type_.clone())),
932 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
938 impl GetDefId for FnRetTy {
939 fn def_id(&self) -> Option<DefId> {
941 Return(ref ty) => ty.def_id(),
942 DefaultReturn => None,
947 #[derive(Clone, Debug)]
950 pub unsafety: hir::Unsafety,
951 pub items: Vec<Item>,
952 pub generics: Generics,
953 pub bounds: Vec<GenericBound>,
954 pub is_spotlight: bool,
958 #[derive(Clone, Debug)]
959 pub struct TraitAlias {
960 pub generics: Generics,
961 pub bounds: Vec<GenericBound>,
964 /// A trait reference, which may have higher ranked lifetimes.
965 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
966 pub struct PolyTrait {
968 pub generic_params: Vec<GenericParamDef>,
971 /// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
972 /// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
973 /// importantly, it does not preserve mutability or boxes.
974 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
976 /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
979 param_names: Option<Vec<GenericBound>>,
981 /// `true` if is a `T::Name` path for associated types.
984 /// For parameterized types, so the consumer of the JSON don't go
985 /// looking for types which don't exist anywhere.
987 /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
988 /// arrays, slices, and tuples.
989 Primitive(PrimitiveType),
990 /// `extern "ABI" fn`
991 BareFunction(Box<BareFunctionDecl>),
994 Array(Box<Type>, String),
996 RawPointer(Mutability, Box<Type>),
998 lifetime: Option<Lifetime>,
999 mutability: Mutability,
1003 // `<Type as Trait>::Name`
1006 self_type: Box<Type>,
1013 // `impl TraitA + TraitB + ...`
1014 ImplTrait(Vec<GenericBound>),
1017 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1018 pub enum PrimitiveType {
1046 #[derive(Clone, Copy, Debug)]
1064 pub trait GetDefId {
1065 fn def_id(&self) -> Option<DefId>;
1068 impl<T: GetDefId> GetDefId for Option<T> {
1069 fn def_id(&self) -> Option<DefId> {
1070 self.as_ref().and_then(|d| d.def_id())
1075 pub fn primitive_type(&self) -> Option<PrimitiveType> {
1077 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1078 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1079 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1082 Some(PrimitiveType::Unit)
1084 Some(PrimitiveType::Tuple)
1087 RawPointer(..) => Some(PrimitiveType::RawPointer),
1088 BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
1089 BareFunction(..) => Some(PrimitiveType::Fn),
1090 Never => Some(PrimitiveType::Never),
1095 pub fn is_generic(&self) -> bool {
1097 ResolvedPath { is_generic, .. } => is_generic,
1102 pub fn is_self_type(&self) -> bool {
1104 Generic(ref name) => name == "Self",
1109 pub fn generics(&self) -> Option<Vec<Type>> {
1111 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1112 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
1115 .filter_map(|arg| match arg {
1116 GenericArg::Type(ty) => Some(ty.clone()),
1129 pub fn bindings(&self) -> Option<&[TypeBinding]> {
1131 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1132 if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
1142 pub fn is_full_generic(&self) -> bool {
1144 Type::Generic(_) => true,
1149 pub fn projection(&self) -> Option<(&Type, DefId, &str)> {
1150 let (self_, trait_, name) = match self {
1151 QPath { ref self_type, ref trait_, ref name } => (self_type, trait_, name),
1154 let trait_did = match **trait_ {
1155 ResolvedPath { did, .. } => did,
1158 Some((&self_, trait_did, name))
1162 impl GetDefId for Type {
1163 fn def_id(&self) -> Option<DefId> {
1165 ResolvedPath { did, .. } => Some(did),
1166 Primitive(p) => crate::html::render::cache().primitive_locations.get(&p).cloned(),
1167 BorrowedRef { type_: box Generic(..), .. } => {
1168 Primitive(PrimitiveType::Reference).def_id()
1170 BorrowedRef { ref type_, .. } => type_.def_id(),
1173 Primitive(PrimitiveType::Unit).def_id()
1175 Primitive(PrimitiveType::Tuple).def_id()
1178 BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
1179 Never => Primitive(PrimitiveType::Never).def_id(),
1180 Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
1181 Array(..) => Primitive(PrimitiveType::Array).def_id(),
1182 RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(),
1183 QPath { ref self_type, .. } => self_type.def_id(),
1189 impl PrimitiveType {
1190 pub fn from_str(s: &str) -> Option<PrimitiveType> {
1192 "isize" => Some(PrimitiveType::Isize),
1193 "i8" => Some(PrimitiveType::I8),
1194 "i16" => Some(PrimitiveType::I16),
1195 "i32" => Some(PrimitiveType::I32),
1196 "i64" => Some(PrimitiveType::I64),
1197 "i128" => Some(PrimitiveType::I128),
1198 "usize" => Some(PrimitiveType::Usize),
1199 "u8" => Some(PrimitiveType::U8),
1200 "u16" => Some(PrimitiveType::U16),
1201 "u32" => Some(PrimitiveType::U32),
1202 "u64" => Some(PrimitiveType::U64),
1203 "u128" => Some(PrimitiveType::U128),
1204 "bool" => Some(PrimitiveType::Bool),
1205 "char" => Some(PrimitiveType::Char),
1206 "str" => Some(PrimitiveType::Str),
1207 "f32" => Some(PrimitiveType::F32),
1208 "f64" => Some(PrimitiveType::F64),
1209 "array" => Some(PrimitiveType::Array),
1210 "slice" => Some(PrimitiveType::Slice),
1211 "tuple" => Some(PrimitiveType::Tuple),
1212 "unit" => Some(PrimitiveType::Unit),
1213 "pointer" => Some(PrimitiveType::RawPointer),
1214 "reference" => Some(PrimitiveType::Reference),
1215 "fn" => Some(PrimitiveType::Fn),
1216 "never" => Some(PrimitiveType::Never),
1221 pub fn as_str(&self) -> &'static str {
1222 use self::PrimitiveType::*;
1245 RawPointer => "pointer",
1246 Reference => "reference",
1252 pub fn to_url_str(&self) -> &'static str {
1257 impl From<ast::IntTy> for PrimitiveType {
1258 fn from(int_ty: ast::IntTy) -> PrimitiveType {
1260 ast::IntTy::Isize => PrimitiveType::Isize,
1261 ast::IntTy::I8 => PrimitiveType::I8,
1262 ast::IntTy::I16 => PrimitiveType::I16,
1263 ast::IntTy::I32 => PrimitiveType::I32,
1264 ast::IntTy::I64 => PrimitiveType::I64,
1265 ast::IntTy::I128 => PrimitiveType::I128,
1270 impl From<ast::UintTy> for PrimitiveType {
1271 fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1273 ast::UintTy::Usize => PrimitiveType::Usize,
1274 ast::UintTy::U8 => PrimitiveType::U8,
1275 ast::UintTy::U16 => PrimitiveType::U16,
1276 ast::UintTy::U32 => PrimitiveType::U32,
1277 ast::UintTy::U64 => PrimitiveType::U64,
1278 ast::UintTy::U128 => PrimitiveType::U128,
1283 impl From<ast::FloatTy> for PrimitiveType {
1284 fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1286 ast::FloatTy::F32 => PrimitiveType::F32,
1287 ast::FloatTy::F64 => PrimitiveType::F64,
1292 impl From<hir::PrimTy> for PrimitiveType {
1293 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1295 hir::PrimTy::Int(int_ty) => int_ty.into(),
1296 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1297 hir::PrimTy::Float(float_ty) => float_ty.into(),
1298 hir::PrimTy::Str => PrimitiveType::Str,
1299 hir::PrimTy::Bool => PrimitiveType::Bool,
1300 hir::PrimTy::Char => PrimitiveType::Char,
1305 #[derive(Clone, PartialEq, Eq, Debug)]
1306 pub enum Visibility {
1310 Restricted(DefId, Path),
1313 #[derive(Clone, Debug)]
1315 pub struct_type: doctree::StructType,
1316 pub generics: Generics,
1317 pub fields: Vec<Item>,
1318 pub fields_stripped: bool,
1321 #[derive(Clone, Debug)]
1323 pub struct_type: doctree::StructType,
1324 pub generics: Generics,
1325 pub fields: Vec<Item>,
1326 pub fields_stripped: bool,
1329 /// This is a more limited form of the standard Struct, different in that
1330 /// it lacks the things most items have (name, id, parameterization). Found
1331 /// only as a variant in an enum.
1332 #[derive(Clone, Debug)]
1333 pub struct VariantStruct {
1334 pub struct_type: doctree::StructType,
1335 pub fields: Vec<Item>,
1336 pub fields_stripped: bool,
1339 #[derive(Clone, Debug)]
1341 pub variants: IndexVec<VariantIdx, Item>,
1342 pub generics: Generics,
1343 pub variants_stripped: bool,
1346 #[derive(Clone, Debug)]
1347 pub struct Variant {
1348 pub kind: VariantKind,
1351 #[derive(Clone, Debug)]
1352 pub enum VariantKind {
1355 Struct(VariantStruct),
1358 #[derive(Clone, Debug)]
1360 pub filename: FileName,
1365 pub original: rustc_span::Span,
1369 pub fn empty() -> Span {
1371 filename: FileName::Anon(0),
1376 original: rustc_span::DUMMY_SP,
1380 pub fn span(&self) -> rustc_span::Span {
1385 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1389 pub segments: Vec<PathSegment>,
1393 pub fn last_name(&self) -> &str {
1394 self.segments.last().expect("segments were empty").name.as_str()
1398 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1399 pub enum GenericArg {
1405 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1406 pub enum GenericArgs {
1407 AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
1408 Parenthesized { inputs: Vec<Type>, output: Option<Type> },
1411 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1412 pub struct PathSegment {
1414 pub args: GenericArgs,
1417 #[derive(Clone, Debug)]
1418 pub struct Typedef {
1420 pub generics: Generics,
1421 // Type of target item.
1422 pub item_type: Option<Type>,
1425 impl GetDefId for Typedef {
1426 fn def_id(&self) -> Option<DefId> {
1431 #[derive(Clone, Debug)]
1432 pub struct OpaqueTy {
1433 pub bounds: Vec<GenericBound>,
1434 pub generics: Generics,
1437 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1438 pub struct BareFunctionDecl {
1439 pub unsafety: hir::Unsafety,
1440 pub generic_params: Vec<GenericParamDef>,
1445 #[derive(Clone, Debug)]
1448 pub mutability: Mutability,
1449 /// It's useful to have the value of a static documented, but I have no
1450 /// desire to represent expressions (that'd basically be all of the AST,
1451 /// which is huge!). So, have a string.
1455 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
1456 pub struct Constant {
1459 pub value: Option<String>,
1460 pub is_literal: bool,
1463 #[derive(Clone, PartialEq, Debug)]
1464 pub enum ImplPolarity {
1469 #[derive(Clone, Debug)]
1471 pub unsafety: hir::Unsafety,
1472 pub generics: Generics,
1473 pub provided_trait_methods: FxHashSet<String>,
1474 pub trait_: Option<Type>,
1476 pub items: Vec<Item>,
1477 pub polarity: Option<ImplPolarity>,
1478 pub synthetic: bool,
1479 pub blanket_impl: Option<Type>,
1482 #[derive(Clone, Debug)]
1484 // use source as str;
1485 Simple(String, ImportSource),
1490 #[derive(Clone, Debug)]
1491 pub struct ImportSource {
1493 pub did: Option<DefId>,
1496 #[derive(Clone, Debug)]
1499 pub imported_from: Option<String>,
1502 #[derive(Clone, Debug)]
1503 pub struct ProcMacro {
1504 pub kind: MacroKind,
1505 pub helpers: Vec<String>,
1508 #[derive(Clone, Debug)]
1509 pub struct Stability {
1510 pub level: stability::StabilityLevel,
1511 pub feature: Option<String>,
1513 pub deprecation: Option<Deprecation>,
1514 pub unstable_reason: Option<String>,
1515 pub issue: Option<NonZeroU32>,
1518 #[derive(Clone, Debug)]
1519 pub struct Deprecation {
1520 pub since: Option<String>,
1521 pub note: Option<String>,
1524 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
1525 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
1526 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1527 pub struct TypeBinding {
1529 pub kind: TypeBindingKind,
1532 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1533 pub enum TypeBindingKind {
1534 Equality { ty: Type },
1535 Constraint { bounds: Vec<GenericBound> },
1539 pub fn ty(&self) -> &Type {
1541 TypeBindingKind::Equality { ref ty } => ty,
1542 _ => panic!("expected equality type binding for parenthesized generic args"),