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};
38 use self::FunctionRetTy::*;
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 .filter(|a| a.doc_str().is_some())
570 .map_or(true, |a| a.style == AttrStyle::Inner);
575 cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) },
582 /// Finds the `doc` attribute as a NameValue and returns the corresponding
584 pub fn doc_value(&self) -> Option<&str> {
585 self.doc_strings.first().map(|s| s.as_str())
588 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
590 pub fn collapsed_doc_value(&self) -> Option<String> {
591 if !self.doc_strings.is_empty() { Some(self.doc_strings.iter().collect()) } else { None }
594 /// Gets links as a vector
596 /// Cache must be populated before call
597 pub fn links(&self, krate: &CrateNum) -> Vec<(String, String)> {
598 use crate::html::format::href;
602 .filter_map(|&(ref s, did, ref fragment)| {
605 if let Some((mut href, ..)) = href(did) {
606 if let Some(ref fragment) = *fragment {
608 href.push_str(fragment);
610 Some((s.clone(), href))
616 if let Some(ref fragment) = *fragment {
618 let url = match cache.extern_locations.get(krate) {
619 Some(&(_, ref src, ExternalLocation::Local)) => {
620 src.to_str().expect("invalid file path")
622 Some(&(_, _, ExternalLocation::Remote(ref s))) => s,
623 Some(&(_, _, ExternalLocation::Unknown)) | None => {
624 "https://doc.rust-lang.org/nightly"
627 // This is a primitive so the url is done "by hand".
628 let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
632 "{}{}std/primitive.{}.html{}",
634 if !url.ends_with('/') { "/" } else { "" },
640 panic!("This isn't a primitive?!");
649 impl PartialEq for Attributes {
650 fn eq(&self, rhs: &Self) -> bool {
651 self.doc_strings == rhs.doc_strings
652 && self.cfg == rhs.cfg
653 && self.span == rhs.span
654 && self.links == rhs.links
659 .eq(rhs.other_attrs.iter().map(|attr| attr.id))
663 impl Eq for Attributes {}
665 impl Hash for Attributes {
666 fn hash<H: Hasher>(&self, hasher: &mut H) {
667 self.doc_strings.hash(hasher);
668 self.cfg.hash(hasher);
669 self.span.hash(hasher);
670 self.links.hash(hasher);
671 for attr in &self.other_attrs {
672 attr.id.hash(hasher);
677 impl AttributesExt for Attributes {
678 fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
679 self.other_attrs.lists(name)
683 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
684 pub enum GenericBound {
685 TraitBound(PolyTrait, hir::TraitBoundModifier),
690 pub fn maybe_sized(cx: &DocContext<'_>) -> GenericBound {
691 let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None);
692 let empty = cx.tcx.intern_substs(&[]);
693 let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
694 inline::record_extern_fqn(cx, did, TypeKind::Trait);
695 GenericBound::TraitBound(
697 trait_: ResolvedPath { path, param_names: None, did, is_generic: false },
698 generic_params: Vec::new(),
700 hir::TraitBoundModifier::Maybe,
704 pub fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
705 use rustc_hir::TraitBoundModifier as TBM;
706 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
707 if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
714 pub fn get_poly_trait(&self) -> Option<PolyTrait> {
715 if let GenericBound::TraitBound(ref p, _) = *self {
716 return Some(p.clone());
721 pub fn get_trait_type(&self) -> Option<Type> {
722 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
730 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
731 pub struct Lifetime(pub String);
734 pub fn get_ref<'a>(&'a self) -> &'a str {
735 let Lifetime(ref s) = *self;
740 pub fn statik() -> Lifetime {
741 Lifetime("'static".to_string())
745 #[derive(Clone, Debug)]
746 pub enum WherePredicate {
747 BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
748 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
749 EqPredicate { lhs: Type, rhs: Type },
752 impl WherePredicate {
753 pub fn get_bounds(&self) -> Option<&[GenericBound]> {
755 WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
756 WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
762 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
763 pub enum GenericParamDefKind {
767 bounds: Vec<GenericBound>,
768 default: Option<Type>,
769 synthetic: Option<hir::SyntheticTyParamKind>,
777 impl GenericParamDefKind {
778 pub fn is_type(&self) -> bool {
780 GenericParamDefKind::Type { .. } => true,
785 // FIXME(eddyb) this either returns the default of a type parameter, or the
786 // type of a `const` parameter. It seems that the intention is to *visit*
787 // any embedded types, but `get_type` seems to be the wrong name for that.
788 pub fn get_type(&self) -> Option<Type> {
790 GenericParamDefKind::Type { default, .. } => default.clone(),
791 GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
792 GenericParamDefKind::Lifetime => None,
797 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
798 pub struct GenericParamDef {
800 pub kind: GenericParamDefKind,
803 impl GenericParamDef {
804 pub fn is_synthetic_type_param(&self) -> bool {
806 GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => false,
807 GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
811 pub fn is_type(&self) -> bool {
815 pub fn get_type(&self) -> Option<Type> {
819 pub fn get_bounds(&self) -> Option<&[GenericBound]> {
821 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
827 // maybe use a Generic enum and use Vec<Generic>?
828 #[derive(Clone, Debug, Default)]
829 pub struct Generics {
830 pub params: Vec<GenericParamDef>,
831 pub where_predicates: Vec<WherePredicate>,
834 #[derive(Clone, Debug)]
836 pub generics: Generics,
838 pub header: hir::FnHeader,
839 pub defaultness: Option<hir::Defaultness>,
840 pub all_types: Vec<Type>,
841 pub ret_types: Vec<Type>,
844 #[derive(Clone, Debug)]
845 pub struct TyMethod {
846 pub header: hir::FnHeader,
848 pub generics: Generics,
849 pub all_types: Vec<Type>,
850 pub ret_types: Vec<Type>,
853 #[derive(Clone, Debug)]
854 pub struct Function {
856 pub generics: Generics,
857 pub header: hir::FnHeader,
858 pub all_types: Vec<Type>,
859 pub ret_types: Vec<Type>,
862 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
864 pub inputs: Arguments,
865 pub output: FunctionRetTy,
866 pub c_variadic: bool,
867 pub attrs: Attributes,
871 pub fn self_type(&self) -> Option<SelfTy> {
872 self.inputs.values.get(0).and_then(|v| v.to_self())
875 /// Returns the sugared return type for an async function.
877 /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
878 /// will return `i32`.
882 /// This function will panic if the return type does not match the expected sugaring for async
884 pub fn sugared_async_return_type(&self) -> FunctionRetTy {
886 FunctionRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
887 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
888 let bindings = trait_.bindings().unwrap();
889 FunctionRetTy::Return(bindings[0].ty().clone())
891 _ => panic!("unexpected desugaring of async function"),
893 _ => panic!("unexpected desugaring of async function"),
898 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
899 pub struct Arguments {
900 pub values: Vec<Argument>,
903 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
904 pub struct Argument {
909 #[derive(Clone, PartialEq, Debug)]
912 SelfBorrowed(Option<Lifetime>, Mutability),
917 pub fn to_self(&self) -> Option<SelfTy> {
918 if self.name != "self" {
921 if self.type_.is_self_type() {
922 return Some(SelfValue);
925 BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
926 Some(SelfBorrowed(lifetime.clone(), mutability))
928 _ => Some(SelfExplicit(self.type_.clone())),
933 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
934 pub enum FunctionRetTy {
939 impl GetDefId for FunctionRetTy {
940 fn def_id(&self) -> Option<DefId> {
942 Return(ref ty) => ty.def_id(),
943 DefaultReturn => None,
948 #[derive(Clone, Debug)]
951 pub unsafety: hir::Unsafety,
952 pub items: Vec<Item>,
953 pub generics: Generics,
954 pub bounds: Vec<GenericBound>,
955 pub is_spotlight: bool,
959 #[derive(Clone, Debug)]
960 pub struct TraitAlias {
961 pub generics: Generics,
962 pub bounds: Vec<GenericBound>,
965 /// A trait reference, which may have higher ranked lifetimes.
966 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
967 pub struct PolyTrait {
969 pub generic_params: Vec<GenericParamDef>,
972 /// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
973 /// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
974 /// importantly, it does not preserve mutability or boxes.
975 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
977 /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
980 param_names: Option<Vec<GenericBound>>,
982 /// `true` if is a `T::Name` path for associated types.
985 /// For parameterized types, so the consumer of the JSON don't go
986 /// looking for types which don't exist anywhere.
988 /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
989 /// arrays, slices, and tuples.
990 Primitive(PrimitiveType),
991 /// `extern "ABI" fn`
992 BareFunction(Box<BareFunctionDecl>),
995 Array(Box<Type>, String),
997 RawPointer(Mutability, Box<Type>),
999 lifetime: Option<Lifetime>,
1000 mutability: Mutability,
1004 // `<Type as Trait>::Name`
1007 self_type: Box<Type>,
1014 // `impl TraitA + TraitB + ...`
1015 ImplTrait(Vec<GenericBound>),
1018 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1019 pub enum PrimitiveType {
1047 #[derive(Clone, Copy, Debug)]
1065 pub trait GetDefId {
1066 fn def_id(&self) -> Option<DefId>;
1069 impl<T: GetDefId> GetDefId for Option<T> {
1070 fn def_id(&self) -> Option<DefId> {
1071 self.as_ref().and_then(|d| d.def_id())
1076 pub fn primitive_type(&self) -> Option<PrimitiveType> {
1078 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1079 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1080 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1083 Some(PrimitiveType::Unit)
1085 Some(PrimitiveType::Tuple)
1088 RawPointer(..) => Some(PrimitiveType::RawPointer),
1089 BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
1090 BareFunction(..) => Some(PrimitiveType::Fn),
1091 Never => Some(PrimitiveType::Never),
1096 pub fn is_generic(&self) -> bool {
1098 ResolvedPath { is_generic, .. } => is_generic,
1103 pub fn is_self_type(&self) -> bool {
1105 Generic(ref name) => name == "Self",
1110 pub fn generics(&self) -> Option<Vec<Type>> {
1112 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1113 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
1116 .filter_map(|arg| match arg {
1117 GenericArg::Type(ty) => Some(ty.clone()),
1130 pub fn bindings(&self) -> Option<&[TypeBinding]> {
1132 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1133 if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
1143 pub fn is_full_generic(&self) -> bool {
1145 Type::Generic(_) => true,
1150 pub fn projection(&self) -> Option<(&Type, DefId, &str)> {
1151 let (self_, trait_, name) = match self {
1152 QPath { ref self_type, ref trait_, ref name } => (self_type, trait_, name),
1155 let trait_did = match **trait_ {
1156 ResolvedPath { did, .. } => did,
1159 Some((&self_, trait_did, name))
1163 impl GetDefId for Type {
1164 fn def_id(&self) -> Option<DefId> {
1166 ResolvedPath { did, .. } => Some(did),
1167 Primitive(p) => crate::html::render::cache().primitive_locations.get(&p).cloned(),
1168 BorrowedRef { type_: box Generic(..), .. } => {
1169 Primitive(PrimitiveType::Reference).def_id()
1171 BorrowedRef { ref type_, .. } => type_.def_id(),
1174 Primitive(PrimitiveType::Unit).def_id()
1176 Primitive(PrimitiveType::Tuple).def_id()
1179 BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
1180 Never => Primitive(PrimitiveType::Never).def_id(),
1181 Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
1182 Array(..) => Primitive(PrimitiveType::Array).def_id(),
1183 RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(),
1184 QPath { ref self_type, .. } => self_type.def_id(),
1190 impl PrimitiveType {
1191 pub fn from_str(s: &str) -> Option<PrimitiveType> {
1193 "isize" => Some(PrimitiveType::Isize),
1194 "i8" => Some(PrimitiveType::I8),
1195 "i16" => Some(PrimitiveType::I16),
1196 "i32" => Some(PrimitiveType::I32),
1197 "i64" => Some(PrimitiveType::I64),
1198 "i128" => Some(PrimitiveType::I128),
1199 "usize" => Some(PrimitiveType::Usize),
1200 "u8" => Some(PrimitiveType::U8),
1201 "u16" => Some(PrimitiveType::U16),
1202 "u32" => Some(PrimitiveType::U32),
1203 "u64" => Some(PrimitiveType::U64),
1204 "u128" => Some(PrimitiveType::U128),
1205 "bool" => Some(PrimitiveType::Bool),
1206 "char" => Some(PrimitiveType::Char),
1207 "str" => Some(PrimitiveType::Str),
1208 "f32" => Some(PrimitiveType::F32),
1209 "f64" => Some(PrimitiveType::F64),
1210 "array" => Some(PrimitiveType::Array),
1211 "slice" => Some(PrimitiveType::Slice),
1212 "tuple" => Some(PrimitiveType::Tuple),
1213 "unit" => Some(PrimitiveType::Unit),
1214 "pointer" => Some(PrimitiveType::RawPointer),
1215 "reference" => Some(PrimitiveType::Reference),
1216 "fn" => Some(PrimitiveType::Fn),
1217 "never" => Some(PrimitiveType::Never),
1222 pub fn as_str(&self) -> &'static str {
1223 use self::PrimitiveType::*;
1246 RawPointer => "pointer",
1247 Reference => "reference",
1253 pub fn to_url_str(&self) -> &'static str {
1258 impl From<ast::IntTy> for PrimitiveType {
1259 fn from(int_ty: ast::IntTy) -> PrimitiveType {
1261 ast::IntTy::Isize => PrimitiveType::Isize,
1262 ast::IntTy::I8 => PrimitiveType::I8,
1263 ast::IntTy::I16 => PrimitiveType::I16,
1264 ast::IntTy::I32 => PrimitiveType::I32,
1265 ast::IntTy::I64 => PrimitiveType::I64,
1266 ast::IntTy::I128 => PrimitiveType::I128,
1271 impl From<ast::UintTy> for PrimitiveType {
1272 fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1274 ast::UintTy::Usize => PrimitiveType::Usize,
1275 ast::UintTy::U8 => PrimitiveType::U8,
1276 ast::UintTy::U16 => PrimitiveType::U16,
1277 ast::UintTy::U32 => PrimitiveType::U32,
1278 ast::UintTy::U64 => PrimitiveType::U64,
1279 ast::UintTy::U128 => PrimitiveType::U128,
1284 impl From<ast::FloatTy> for PrimitiveType {
1285 fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1287 ast::FloatTy::F32 => PrimitiveType::F32,
1288 ast::FloatTy::F64 => PrimitiveType::F64,
1293 #[derive(Clone, PartialEq, Eq, Debug)]
1294 pub enum Visibility {
1298 Restricted(DefId, Path),
1301 #[derive(Clone, Debug)]
1303 pub struct_type: doctree::StructType,
1304 pub generics: Generics,
1305 pub fields: Vec<Item>,
1306 pub fields_stripped: bool,
1309 #[derive(Clone, Debug)]
1311 pub struct_type: doctree::StructType,
1312 pub generics: Generics,
1313 pub fields: Vec<Item>,
1314 pub fields_stripped: bool,
1317 /// This is a more limited form of the standard Struct, different in that
1318 /// it lacks the things most items have (name, id, parameterization). Found
1319 /// only as a variant in an enum.
1320 #[derive(Clone, Debug)]
1321 pub struct VariantStruct {
1322 pub struct_type: doctree::StructType,
1323 pub fields: Vec<Item>,
1324 pub fields_stripped: bool,
1327 #[derive(Clone, Debug)]
1329 pub variants: IndexVec<VariantIdx, Item>,
1330 pub generics: Generics,
1331 pub variants_stripped: bool,
1334 #[derive(Clone, Debug)]
1335 pub struct Variant {
1336 pub kind: VariantKind,
1339 #[derive(Clone, Debug)]
1340 pub enum VariantKind {
1343 Struct(VariantStruct),
1346 #[derive(Clone, Debug)]
1348 pub filename: FileName,
1353 pub original: rustc_span::Span,
1357 pub fn empty() -> Span {
1359 filename: FileName::Anon(0),
1364 original: rustc_span::DUMMY_SP,
1368 pub fn span(&self) -> rustc_span::Span {
1373 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1377 pub segments: Vec<PathSegment>,
1381 pub fn last_name(&self) -> &str {
1382 self.segments.last().expect("segments were empty").name.as_str()
1386 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1387 pub enum GenericArg {
1393 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1394 pub enum GenericArgs {
1395 AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
1396 Parenthesized { inputs: Vec<Type>, output: Option<Type> },
1399 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1400 pub struct PathSegment {
1402 pub args: GenericArgs,
1405 #[derive(Clone, Debug)]
1406 pub struct Typedef {
1408 pub generics: Generics,
1411 #[derive(Clone, Debug)]
1412 pub struct OpaqueTy {
1413 pub bounds: Vec<GenericBound>,
1414 pub generics: Generics,
1417 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1418 pub struct BareFunctionDecl {
1419 pub unsafety: hir::Unsafety,
1420 pub generic_params: Vec<GenericParamDef>,
1425 #[derive(Clone, Debug)]
1428 pub mutability: Mutability,
1429 /// It's useful to have the value of a static documented, but I have no
1430 /// desire to represent expressions (that'd basically be all of the AST,
1431 /// which is huge!). So, have a string.
1435 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
1436 pub struct Constant {
1439 pub value: Option<String>,
1440 pub is_literal: bool,
1443 #[derive(Clone, PartialEq, Debug)]
1444 pub enum ImplPolarity {
1449 #[derive(Clone, Debug)]
1451 pub unsafety: hir::Unsafety,
1452 pub generics: Generics,
1453 pub provided_trait_methods: FxHashSet<String>,
1454 pub trait_: Option<Type>,
1456 pub items: Vec<Item>,
1457 pub polarity: Option<ImplPolarity>,
1458 pub synthetic: bool,
1459 pub blanket_impl: Option<Type>,
1462 #[derive(Clone, Debug)]
1464 // use source as str;
1465 Simple(String, ImportSource),
1470 #[derive(Clone, Debug)]
1471 pub struct ImportSource {
1473 pub did: Option<DefId>,
1476 #[derive(Clone, Debug)]
1479 pub imported_from: Option<String>,
1482 #[derive(Clone, Debug)]
1483 pub struct ProcMacro {
1484 pub kind: MacroKind,
1485 pub helpers: Vec<String>,
1488 #[derive(Clone, Debug)]
1489 pub struct Stability {
1490 pub level: stability::StabilityLevel,
1491 pub feature: Option<String>,
1493 pub deprecation: Option<Deprecation>,
1494 pub unstable_reason: Option<String>,
1495 pub issue: Option<NonZeroU32>,
1498 #[derive(Clone, Debug)]
1499 pub struct Deprecation {
1500 pub since: Option<String>,
1501 pub note: Option<String>,
1504 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
1505 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
1506 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1507 pub struct TypeBinding {
1509 pub kind: TypeBindingKind,
1512 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1513 pub enum TypeBindingKind {
1514 Equality { ty: Type },
1515 Constraint { bounds: Vec<GenericBound> },
1519 pub fn ty(&self) -> &Type {
1521 TypeBindingKind::Equality { ref ty } => ty,
1522 _ => panic!("expected equality type binding for parenthesized generic args"),