1 use std::cell::RefCell;
2 use std::default::Default;
4 use std::hash::{Hash, Hasher};
5 use std::iter::FromIterator;
6 use std::lazy::SyncOnceCell as OnceCell;
7 use std::num::NonZeroU32;
10 use std::{slice, vec};
13 use rustc_ast::util::comments::beautify_doc_string;
14 use rustc_ast::{self as ast, AttrStyle};
15 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
17 use rustc_hir::def::Res;
18 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
19 use rustc_hir::lang_items::LangItem;
20 use rustc_hir::Mutability;
21 use rustc_index::vec::IndexVec;
22 use rustc_middle::middle::stability;
23 use rustc_middle::ty::{AssocKind, TyCtxt};
24 use rustc_span::hygiene::MacroKind;
25 use rustc_span::source_map::DUMMY_SP;
26 use rustc_span::symbol::{kw, sym, Ident, Symbol};
27 use rustc_span::{self, FileName};
28 use rustc_target::abi::VariantIdx;
29 use rustc_target::spec::abi::Abi;
30 use smallvec::{smallvec, SmallVec};
32 use crate::clean::cfg::Cfg;
33 use crate::clean::external_path;
34 use crate::clean::inline;
35 use crate::clean::types::Type::{QPath, ResolvedPath};
36 use crate::core::DocContext;
38 use crate::formats::cache::cache;
39 use crate::formats::item_type::ItemType;
40 use crate::html::render::cache::ExternalLocation;
43 use self::ItemEnum::*;
47 thread_local!(pub static MAX_DEF_ID: RefCell<FxHashMap<CrateNum, DefId>> = Default::default());
49 #[derive(Clone, Debug)]
52 pub version: Option<String>,
54 pub module: Option<Item>,
55 pub externs: Vec<(CrateNum, ExternalCrate)>,
56 pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
57 // These are later on moved into `CACHEKEY`, leaving the map empty.
58 // Only here so that they can be filtered through the rustdoc passes.
59 pub external_traits: Rc<RefCell<FxHashMap<DefId, Trait>>>,
60 pub masked_crates: FxHashSet<CrateNum>,
64 #[derive(Clone, Debug)]
65 pub struct ExternalCrate {
68 pub attrs: Attributes,
69 pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
70 pub keywords: Vec<(DefId, String, Attributes)>,
73 /// Anything with a source location and set of attributes and, optionally, a
74 /// name. That is, anything that can be documented. This doesn't correspond
75 /// directly to the AST's concept of an item; it's a strict superset.
80 /// Not everything has a name. E.g., impls
81 pub name: Option<String>,
82 pub attrs: Attributes,
84 pub visibility: Visibility,
86 pub stability: Option<Stability>,
87 pub deprecation: Option<Deprecation>,
90 impl fmt::Debug for Item {
91 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
92 let fake = self.is_fake();
93 let def_id: &dyn fmt::Debug = if fake { &"**FAKE**" } else { &self.def_id };
95 fmt.debug_struct("Item")
96 .field("source", &self.source)
97 .field("name", &self.name)
98 .field("attrs", &self.attrs)
99 .field("inner", &self.inner)
100 .field("visibility", &self.visibility)
101 .field("def_id", def_id)
102 .field("stability", &self.stability)
103 .field("deprecation", &self.deprecation)
109 /// Finds the `doc` attribute as a NameValue and returns the corresponding
111 pub fn doc_value(&self) -> Option<&str> {
112 self.attrs.doc_value()
115 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
117 pub fn collapsed_doc_value(&self) -> Option<String> {
118 self.attrs.collapsed_doc_value()
121 pub fn links(&self) -> Vec<(String, String)> {
122 self.attrs.links(&self.def_id.krate)
125 pub fn is_crate(&self) -> bool {
127 StrippedItem(box ModuleItem(Module { is_crate: true, .. }))
128 | ModuleItem(Module { is_crate: true, .. }) => true,
132 pub fn is_mod(&self) -> bool {
133 self.type_() == ItemType::Module
135 pub fn is_trait(&self) -> bool {
136 self.type_() == ItemType::Trait
138 pub fn is_struct(&self) -> bool {
139 self.type_() == ItemType::Struct
141 pub fn is_enum(&self) -> bool {
142 self.type_() == ItemType::Enum
144 pub fn is_variant(&self) -> bool {
145 self.type_() == ItemType::Variant
147 pub fn is_associated_type(&self) -> bool {
148 self.type_() == ItemType::AssocType
150 pub fn is_associated_const(&self) -> bool {
151 self.type_() == ItemType::AssocConst
153 pub fn is_method(&self) -> bool {
154 self.type_() == ItemType::Method
156 pub fn is_ty_method(&self) -> bool {
157 self.type_() == ItemType::TyMethod
159 pub fn is_typedef(&self) -> bool {
160 self.type_() == ItemType::Typedef
162 pub fn is_primitive(&self) -> bool {
163 self.type_() == ItemType::Primitive
165 pub fn is_union(&self) -> bool {
166 self.type_() == ItemType::Union
168 pub fn is_import(&self) -> bool {
169 self.type_() == ItemType::Import
171 pub fn is_extern_crate(&self) -> bool {
172 self.type_() == ItemType::ExternCrate
174 pub fn is_keyword(&self) -> bool {
175 self.type_() == ItemType::Keyword
177 pub fn is_stripped(&self) -> bool {
179 StrippedItem(..) => true,
183 pub fn has_stripped_fields(&self) -> Option<bool> {
185 StructItem(ref _struct) => Some(_struct.fields_stripped),
186 UnionItem(ref union) => Some(union.fields_stripped),
187 VariantItem(Variant { kind: VariantKind::Struct(ref vstruct) }) => {
188 Some(vstruct.fields_stripped)
194 pub fn stability_class(&self) -> Option<String> {
195 self.stability.as_ref().and_then(|ref s| {
196 let mut classes = Vec::with_capacity(2);
198 if s.level == stability::Unstable {
199 classes.push("unstable");
202 // FIXME: what about non-staged API items that are deprecated?
203 if self.deprecation.is_some() {
204 classes.push("deprecated");
207 if !classes.is_empty() { Some(classes.join(" ")) } else { None }
211 pub fn stable_since(&self) -> Option<&str> {
212 self.stability.as_ref().map(|s| &s.since[..])
215 pub fn is_non_exhaustive(&self) -> bool {
216 self.attrs.other_attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
219 /// Returns a documentation-level item type from the item.
220 pub fn type_(&self) -> ItemType {
224 pub fn is_default(&self) -> bool {
226 ItemEnum::MethodItem(ref meth) => {
227 if let Some(defaultness) = meth.defaultness {
228 defaultness.has_value() && !defaultness.is_final()
237 /// See comments on next_def_id
238 pub fn is_fake(&self) -> bool {
239 MAX_DEF_ID.with(|m| {
240 m.borrow().get(&self.def_id.krate).map(|id| self.def_id >= *id).unwrap_or(false)
245 #[derive(Clone, Debug)]
247 ExternCrateItem(String, Option<String>),
252 FunctionItem(Function),
254 TypedefItem(Typedef, bool /* is associated type */),
255 OpaqueTyItem(OpaqueTy, bool /* is associated type */),
257 ConstantItem(Constant),
259 TraitAliasItem(TraitAlias),
261 /// A method signature only. Used for required methods in traits (ie,
262 /// non-default-methods).
263 TyMethodItem(TyMethod),
264 /// A method with a body.
266 StructFieldItem(Type),
267 VariantItem(Variant),
268 /// `fn`s from an extern block
269 ForeignFunctionItem(Function),
270 /// `static`s from an extern block
271 ForeignStaticItem(Static),
272 /// `type`s from an extern block
275 ProcMacroItem(ProcMacro),
276 PrimitiveItem(PrimitiveType),
277 AssocConstItem(Type, Option<String>),
278 AssocTypeItem(Vec<GenericBound>, Option<Type>),
279 /// An item that has been stripped by a rustdoc pass
280 StrippedItem(Box<ItemEnum>),
285 pub fn is_type_alias(&self) -> bool {
287 ItemEnum::TypedefItem(_, _) | ItemEnum::AssocTypeItem(_, _) => true,
292 pub fn as_assoc_kind(&self) -> Option<AssocKind> {
294 ItemEnum::AssocConstItem(..) => Some(AssocKind::Const),
295 ItemEnum::AssocTypeItem(..) => Some(AssocKind::Type),
296 ItemEnum::TyMethodItem(..) | ItemEnum::MethodItem(..) => Some(AssocKind::Fn),
302 #[derive(Clone, Debug)]
304 pub items: Vec<Item>,
308 pub struct ListAttributesIter<'a> {
309 attrs: slice::Iter<'a, ast::Attribute>,
310 current_list: vec::IntoIter<ast::NestedMetaItem>,
314 impl<'a> Iterator for ListAttributesIter<'a> {
315 type Item = ast::NestedMetaItem;
317 fn next(&mut self) -> Option<Self::Item> {
318 if let Some(nested) = self.current_list.next() {
322 for attr in &mut self.attrs {
323 if let Some(list) = attr.meta_item_list() {
324 if attr.has_name(self.name) {
325 self.current_list = list.into_iter();
326 if let Some(nested) = self.current_list.next() {
336 fn size_hint(&self) -> (usize, Option<usize>) {
337 let lower = self.current_list.len();
342 pub trait AttributesExt {
343 /// Finds an attribute as List and returns the list of attributes nested inside.
344 fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
347 impl AttributesExt for [ast::Attribute] {
348 fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
349 ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), name }
353 pub trait NestedAttributesExt {
354 /// Returns `true` if the attribute list contains a specific `Word`
355 fn has_word(self, word: Symbol) -> bool;
358 impl<I: IntoIterator<Item = ast::NestedMetaItem>> NestedAttributesExt for I {
359 fn has_word(self, word: Symbol) -> bool {
360 self.into_iter().any(|attr| attr.is_word() && attr.has_name(word))
364 /// A portion of documentation, extracted from a `#[doc]` attribute.
366 /// Each variant contains the line number within the complete doc-comment where the fragment
367 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
369 /// Included files are kept separate from inline doc comments so that proper line-number
370 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
371 /// kept separate because of issue #42760.
372 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
373 pub enum DocFragment {
374 /// A doc fragment created from a `///` or `//!` doc comment.
375 SugaredDoc(usize, rustc_span::Span, String),
376 /// A doc fragment created from a "raw" `#[doc=""]` attribute.
377 RawDoc(usize, rustc_span::Span, String),
378 /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
379 /// given filename and the file contents.
380 Include(usize, rustc_span::Span, String, String),
384 pub fn as_str(&self) -> &str {
386 DocFragment::SugaredDoc(_, _, ref s) => &s[..],
387 DocFragment::RawDoc(_, _, ref s) => &s[..],
388 DocFragment::Include(_, _, _, ref s) => &s[..],
392 pub fn span(&self) -> rustc_span::Span {
394 DocFragment::SugaredDoc(_, span, _)
395 | DocFragment::RawDoc(_, span, _)
396 | DocFragment::Include(_, span, _, _) => span,
401 impl<'a> FromIterator<&'a DocFragment> for String {
402 fn from_iter<T>(iter: T) -> Self
404 T: IntoIterator<Item = &'a DocFragment>,
406 iter.into_iter().fold(String::new(), |mut acc, frag| {
411 DocFragment::SugaredDoc(_, _, ref docs)
412 | DocFragment::RawDoc(_, _, ref docs)
413 | DocFragment::Include(_, _, _, ref docs) => acc.push_str(docs),
421 #[derive(Clone, Debug, Default)]
422 pub struct Attributes {
423 pub doc_strings: Vec<DocFragment>,
424 pub other_attrs: Vec<ast::Attribute>,
425 pub cfg: Option<Arc<Cfg>>,
426 pub span: Option<rustc_span::Span>,
427 /// map from Rust paths to resolved defs and potential URL fragments
428 pub links: Vec<(String, Option<DefId>, Option<String>)>,
429 pub inner_docs: bool,
433 /// Extracts the content from an attribute `#[doc(cfg(content))]`.
434 pub fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
435 use rustc_ast::NestedMetaItem::MetaItem;
437 if let ast::MetaItemKind::List(ref nmis) = mi.kind {
439 if let MetaItem(ref cfg_mi) = nmis[0] {
440 if cfg_mi.has_name(sym::cfg) {
441 if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.kind {
442 if cfg_nmis.len() == 1 {
443 if let MetaItem(ref content_mi) = cfg_nmis[0] {
444 return Some(content_mi);
456 /// Reads a `MetaItem` from within an attribute, looks for whether it is a
457 /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
459 pub fn extract_include(mi: &ast::MetaItem) -> Option<(String, String)> {
460 mi.meta_item_list().and_then(|list| {
462 if meta.has_name(sym::include) {
463 // the actual compiled `#[doc(include="filename")]` gets expanded to
464 // `#[doc(include(file="filename", contents="file contents")]` so we need to
465 // look for that instead
466 return meta.meta_item_list().and_then(|list| {
467 let mut filename: Option<String> = None;
468 let mut contents: Option<String> = None;
471 if it.has_name(sym::file) {
472 if let Some(name) = it.value_str() {
473 filename = Some(name.to_string());
475 } else if it.has_name(sym::contents) {
476 if let Some(docs) = it.value_str() {
477 contents = Some(docs.to_string());
482 if let (Some(filename), Some(contents)) = (filename, contents) {
483 Some((filename, contents))
495 pub fn has_doc_flag(&self, flag: Symbol) -> bool {
496 for attr in &self.other_attrs {
497 if !attr.has_name(sym::doc) {
501 if let Some(items) = attr.meta_item_list() {
502 if items.iter().filter_map(|i| i.meta_item()).any(|it| it.has_name(flag)) {
511 pub fn from_ast(diagnostic: &::rustc_errors::Handler, attrs: &[ast::Attribute]) -> Attributes {
512 let mut doc_strings = vec![];
514 let mut cfg = Cfg::True;
515 let mut doc_line = 0;
517 let other_attrs = attrs
520 if let Some(value) = attr.doc_str() {
521 let value = beautify_doc_string(value);
522 let mk_fragment: fn(_, _, _) -> _ = if attr.is_doc_comment() {
523 DocFragment::SugaredDoc
529 doc_line += value.lines().count();
530 doc_strings.push(mk_fragment(line, attr.span, value));
533 sp = Some(attr.span);
537 if attr.has_name(sym::doc) {
538 if let Some(mi) = attr.meta() {
539 if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
540 // Extracted #[doc(cfg(...))]
541 match Cfg::parse(cfg_mi) {
542 Ok(new_cfg) => cfg &= new_cfg,
543 Err(e) => diagnostic.span_err(e.span, e.msg),
545 } else if let Some((filename, contents)) =
546 Attributes::extract_include(&mi)
549 doc_line += contents.lines().count();
550 doc_strings.push(DocFragment::Include(
551 line, attr.span, filename, contents,
561 // treat #[target_feature(enable = "feat")] attributes as if they were
562 // #[doc(cfg(target_feature = "feat"))] attributes as well
563 for attr in attrs.lists(sym::target_feature) {
564 if attr.has_name(sym::enable) {
565 if let Some(feat) = attr.value_str() {
566 let meta = attr::mk_name_value_item_str(
567 Ident::with_dummy_span(sym::target_feature),
571 if let Ok(feat_cfg) = Cfg::parse(&meta) {
578 let inner_docs = attrs
580 .find(|a| a.doc_str().is_some())
581 .map_or(true, |a| a.style == AttrStyle::Inner);
586 cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) },
593 /// Finds the `doc` attribute as a NameValue and returns the corresponding
595 pub fn doc_value(&self) -> Option<&str> {
596 self.doc_strings.first().map(|s| s.as_str())
599 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
601 pub fn collapsed_doc_value(&self) -> Option<String> {
602 if !self.doc_strings.is_empty() { Some(self.doc_strings.iter().collect()) } else { None }
605 /// Gets links as a vector
607 /// Cache must be populated before call
608 pub fn links(&self, krate: &CrateNum) -> Vec<(String, String)> {
609 use crate::html::format::href;
610 use crate::html::render::CURRENT_DEPTH;
614 .filter_map(|&(ref s, did, ref fragment)| {
617 if let Some((mut href, ..)) = href(did) {
618 if let Some(ref fragment) = *fragment {
620 href.push_str(fragment);
622 Some((s.clone(), href))
628 if let Some(ref fragment) = *fragment {
630 let url = match cache.extern_locations.get(krate) {
631 Some(&(_, _, ExternalLocation::Local)) => {
632 let depth = CURRENT_DEPTH.with(|l| l.get());
635 Some(&(_, _, ExternalLocation::Remote(ref s))) => s.to_string(),
636 Some(&(_, _, ExternalLocation::Unknown)) | None => {
637 String::from("https://doc.rust-lang.org/nightly")
640 // This is a primitive so the url is done "by hand".
641 let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
645 "{}{}std/primitive.{}.html{}",
647 if !url.ends_with('/') { "/" } else { "" },
653 panic!("This isn't a primitive?!");
661 pub fn get_doc_aliases(&self) -> FxHashSet<String> {
664 .filter(|a| a.has_name(sym::alias))
665 .filter_map(|a| a.value_str().map(|s| s.to_string().replace("\"", "")))
666 .filter(|v| !v.is_empty())
667 .collect::<FxHashSet<_>>()
671 impl PartialEq for Attributes {
672 fn eq(&self, rhs: &Self) -> bool {
673 self.doc_strings == rhs.doc_strings
674 && self.cfg == rhs.cfg
675 && self.span == rhs.span
676 && self.links == rhs.links
681 .eq(rhs.other_attrs.iter().map(|attr| attr.id))
685 impl Eq for Attributes {}
687 impl Hash for Attributes {
688 fn hash<H: Hasher>(&self, hasher: &mut H) {
689 self.doc_strings.hash(hasher);
690 self.cfg.hash(hasher);
691 self.span.hash(hasher);
692 self.links.hash(hasher);
693 for attr in &self.other_attrs {
694 attr.id.hash(hasher);
699 impl AttributesExt for Attributes {
700 fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
701 self.other_attrs.lists(name)
705 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
706 pub enum GenericBound {
707 TraitBound(PolyTrait, hir::TraitBoundModifier),
712 pub fn maybe_sized(cx: &DocContext<'_>) -> GenericBound {
713 let did = cx.tcx.require_lang_item(LangItem::Sized, None);
714 let empty = cx.tcx.intern_substs(&[]);
715 let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
716 inline::record_extern_fqn(cx, did, TypeKind::Trait);
717 GenericBound::TraitBound(
719 trait_: ResolvedPath { path, param_names: None, did, is_generic: false },
720 generic_params: Vec::new(),
722 hir::TraitBoundModifier::Maybe,
726 pub fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
727 use rustc_hir::TraitBoundModifier as TBM;
728 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
729 if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
736 pub fn get_poly_trait(&self) -> Option<PolyTrait> {
737 if let GenericBound::TraitBound(ref p, _) = *self {
738 return Some(p.clone());
743 pub fn get_trait_type(&self) -> Option<Type> {
744 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
752 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
753 pub struct Lifetime(pub String);
756 pub fn get_ref<'a>(&'a self) -> &'a str {
757 let Lifetime(ref s) = *self;
762 pub fn statik() -> Lifetime {
763 Lifetime("'static".to_string())
766 pub fn elided() -> Lifetime {
767 Lifetime("'_".to_string())
771 #[derive(Clone, Debug)]
772 pub enum WherePredicate {
773 BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
774 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
775 EqPredicate { lhs: Type, rhs: Type },
778 impl WherePredicate {
779 pub fn get_bounds(&self) -> Option<&[GenericBound]> {
781 WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
782 WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
788 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
789 pub enum GenericParamDefKind {
793 bounds: Vec<GenericBound>,
794 default: Option<Type>,
795 synthetic: Option<hir::SyntheticTyParamKind>,
803 impl GenericParamDefKind {
804 pub fn is_type(&self) -> bool {
806 GenericParamDefKind::Type { .. } => true,
811 // FIXME(eddyb) this either returns the default of a type parameter, or the
812 // type of a `const` parameter. It seems that the intention is to *visit*
813 // any embedded types, but `get_type` seems to be the wrong name for that.
814 pub fn get_type(&self) -> Option<Type> {
816 GenericParamDefKind::Type { default, .. } => default.clone(),
817 GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
818 GenericParamDefKind::Lifetime => None,
823 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
824 pub struct GenericParamDef {
826 pub kind: GenericParamDefKind,
829 impl GenericParamDef {
830 pub fn is_synthetic_type_param(&self) -> bool {
832 GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => false,
833 GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
837 pub fn is_type(&self) -> bool {
841 pub fn get_type(&self) -> Option<Type> {
845 pub fn get_bounds(&self) -> Option<&[GenericBound]> {
847 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
853 // maybe use a Generic enum and use Vec<Generic>?
854 #[derive(Clone, Debug, Default)]
855 pub struct Generics {
856 pub params: Vec<GenericParamDef>,
857 pub where_predicates: Vec<WherePredicate>,
860 #[derive(Clone, Debug)]
862 pub generics: Generics,
864 pub header: hir::FnHeader,
865 pub defaultness: Option<hir::Defaultness>,
866 pub all_types: Vec<(Type, TypeKind)>,
867 pub ret_types: Vec<(Type, TypeKind)>,
870 #[derive(Clone, Debug)]
871 pub struct TyMethod {
872 pub header: hir::FnHeader,
874 pub generics: Generics,
875 pub all_types: Vec<(Type, TypeKind)>,
876 pub ret_types: Vec<(Type, TypeKind)>,
879 #[derive(Clone, Debug)]
880 pub struct Function {
882 pub generics: Generics,
883 pub header: hir::FnHeader,
884 pub all_types: Vec<(Type, TypeKind)>,
885 pub ret_types: Vec<(Type, TypeKind)>,
888 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
890 pub inputs: Arguments,
892 pub c_variadic: bool,
893 pub attrs: Attributes,
897 pub fn self_type(&self) -> Option<SelfTy> {
898 self.inputs.values.get(0).and_then(|v| v.to_self())
901 /// Returns the sugared return type for an async function.
903 /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
904 /// will return `i32`.
908 /// This function will panic if the return type does not match the expected sugaring for async
910 pub fn sugared_async_return_type(&self) -> FnRetTy {
912 FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
913 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
914 let bindings = trait_.bindings().unwrap();
915 FnRetTy::Return(bindings[0].ty().clone())
917 _ => panic!("unexpected desugaring of async function"),
919 _ => panic!("unexpected desugaring of async function"),
924 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
925 pub struct Arguments {
926 pub values: Vec<Argument>,
929 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
930 pub struct Argument {
935 #[derive(Clone, PartialEq, Debug)]
938 SelfBorrowed(Option<Lifetime>, Mutability),
943 pub fn to_self(&self) -> Option<SelfTy> {
944 if self.name != "self" {
947 if self.type_.is_self_type() {
948 return Some(SelfValue);
951 BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
952 Some(SelfBorrowed(lifetime.clone(), mutability))
954 _ => Some(SelfExplicit(self.type_.clone())),
959 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
965 impl GetDefId for FnRetTy {
966 fn def_id(&self) -> Option<DefId> {
968 Return(ref ty) => ty.def_id(),
969 DefaultReturn => None,
974 #[derive(Clone, Debug)]
977 pub unsafety: hir::Unsafety,
978 pub items: Vec<Item>,
979 pub generics: Generics,
980 pub bounds: Vec<GenericBound>,
981 pub is_spotlight: bool,
985 #[derive(Clone, Debug)]
986 pub struct TraitAlias {
987 pub generics: Generics,
988 pub bounds: Vec<GenericBound>,
991 /// A trait reference, which may have higher ranked lifetimes.
992 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
993 pub struct PolyTrait {
995 pub generic_params: Vec<GenericParamDef>,
998 /// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
999 /// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
1000 /// importantly, it does not preserve mutability or boxes.
1001 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1003 /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
1006 param_names: Option<Vec<GenericBound>>,
1008 /// `true` if is a `T::Name` path for associated types.
1011 /// For parameterized types, so the consumer of the JSON don't go
1012 /// looking for types which don't exist anywhere.
1014 /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
1015 /// arrays, slices, and tuples.
1016 Primitive(PrimitiveType),
1017 /// `extern "ABI" fn`
1018 BareFunction(Box<BareFunctionDecl>),
1021 Array(Box<Type>, String),
1023 RawPointer(Mutability, Box<Type>),
1025 lifetime: Option<Lifetime>,
1026 mutability: Mutability,
1030 // `<Type as Trait>::Name`
1033 self_type: Box<Type>,
1040 // `impl TraitA + TraitB + ...`
1041 ImplTrait(Vec<GenericBound>),
1044 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1045 pub enum PrimitiveType {
1073 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1091 pub trait GetDefId {
1092 fn def_id(&self) -> Option<DefId>;
1095 impl<T: GetDefId> GetDefId for Option<T> {
1096 fn def_id(&self) -> Option<DefId> {
1097 self.as_ref().and_then(|d| d.def_id())
1102 pub fn primitive_type(&self) -> Option<PrimitiveType> {
1104 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1105 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1106 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1109 Some(PrimitiveType::Unit)
1111 Some(PrimitiveType::Tuple)
1114 RawPointer(..) => Some(PrimitiveType::RawPointer),
1115 BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
1116 BareFunction(..) => Some(PrimitiveType::Fn),
1117 Never => Some(PrimitiveType::Never),
1122 pub fn is_generic(&self) -> bool {
1124 ResolvedPath { is_generic, .. } => is_generic,
1129 pub fn is_self_type(&self) -> bool {
1131 Generic(ref name) => name == "Self",
1136 pub fn generics(&self) -> Option<Vec<Type>> {
1138 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1139 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
1142 .filter_map(|arg| match arg {
1143 GenericArg::Type(ty) => Some(ty.clone()),
1156 pub fn bindings(&self) -> Option<&[TypeBinding]> {
1158 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1159 if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
1169 pub fn is_full_generic(&self) -> bool {
1171 Type::Generic(_) => true,
1176 pub fn projection(&self) -> Option<(&Type, DefId, &str)> {
1177 let (self_, trait_, name) = match self {
1178 QPath { ref self_type, ref trait_, ref name } => (self_type, trait_, name),
1181 let trait_did = match **trait_ {
1182 ResolvedPath { did, .. } => did,
1185 Some((&self_, trait_did, name))
1189 impl GetDefId for Type {
1190 fn def_id(&self) -> Option<DefId> {
1192 ResolvedPath { did, .. } => Some(did),
1193 Primitive(p) => cache().primitive_locations.get(&p).cloned(),
1194 BorrowedRef { type_: box Generic(..), .. } => {
1195 Primitive(PrimitiveType::Reference).def_id()
1197 BorrowedRef { ref type_, .. } => type_.def_id(),
1200 Primitive(PrimitiveType::Unit).def_id()
1202 Primitive(PrimitiveType::Tuple).def_id()
1205 BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
1206 Never => Primitive(PrimitiveType::Never).def_id(),
1207 Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
1208 Array(..) => Primitive(PrimitiveType::Array).def_id(),
1209 RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(),
1210 QPath { ref self_type, .. } => self_type.def_id(),
1216 impl PrimitiveType {
1217 pub fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1219 sym::isize => Some(PrimitiveType::Isize),
1220 sym::i8 => Some(PrimitiveType::I8),
1221 sym::i16 => Some(PrimitiveType::I16),
1222 sym::i32 => Some(PrimitiveType::I32),
1223 sym::i64 => Some(PrimitiveType::I64),
1224 sym::i128 => Some(PrimitiveType::I128),
1225 sym::usize => Some(PrimitiveType::Usize),
1226 sym::u8 => Some(PrimitiveType::U8),
1227 sym::u16 => Some(PrimitiveType::U16),
1228 sym::u32 => Some(PrimitiveType::U32),
1229 sym::u64 => Some(PrimitiveType::U64),
1230 sym::u128 => Some(PrimitiveType::U128),
1231 sym::bool => Some(PrimitiveType::Bool),
1232 sym::char => Some(PrimitiveType::Char),
1233 sym::str => Some(PrimitiveType::Str),
1234 sym::f32 => Some(PrimitiveType::F32),
1235 sym::f64 => Some(PrimitiveType::F64),
1236 sym::array => Some(PrimitiveType::Array),
1237 sym::slice => Some(PrimitiveType::Slice),
1238 sym::tuple => Some(PrimitiveType::Tuple),
1239 sym::unit => Some(PrimitiveType::Unit),
1240 sym::pointer => Some(PrimitiveType::RawPointer),
1241 sym::reference => Some(PrimitiveType::Reference),
1242 kw::Fn => Some(PrimitiveType::Fn),
1243 sym::never => Some(PrimitiveType::Never),
1248 pub fn as_str(&self) -> &'static str {
1249 use self::PrimitiveType::*;
1272 RawPointer => "pointer",
1273 Reference => "reference",
1279 pub fn impls(&self, tcx: TyCtxt<'_>) -> &'static SmallVec<[DefId; 4]> {
1280 Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
1283 pub fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>> {
1284 static CELL: OnceCell<FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>>> = OnceCell::new();
1286 CELL.get_or_init(move || {
1287 use self::PrimitiveType::*;
1289 /// A macro to create a FxHashMap.
1294 /// let letters = map!{"a" => "b", "c" => "d"};
1297 /// Trailing commas are allowed.
1298 /// Commas between elements are required (even if the expression is a block).
1300 ($( $key: expr => $val: expr ),* $(,)*) => {{
1301 let mut map = ::rustc_data_structures::fx::FxHashMap::default();
1302 $( map.insert($key, $val); )*
1307 let single = |a: Option<DefId>| a.into_iter().collect();
1308 let both = |a: Option<DefId>, b: Option<DefId>| -> SmallVec<_> {
1309 a.into_iter().chain(b).collect()
1312 let lang_items = tcx.lang_items();
1314 Isize => single(lang_items.isize_impl()),
1315 I8 => single(lang_items.i8_impl()),
1316 I16 => single(lang_items.i16_impl()),
1317 I32 => single(lang_items.i32_impl()),
1318 I64 => single(lang_items.i64_impl()),
1319 I128 => single(lang_items.i128_impl()),
1320 Usize => single(lang_items.usize_impl()),
1321 U8 => single(lang_items.u8_impl()),
1322 U16 => single(lang_items.u16_impl()),
1323 U32 => single(lang_items.u32_impl()),
1324 U64 => single(lang_items.u64_impl()),
1325 U128 => single(lang_items.u128_impl()),
1326 F32 => both(lang_items.f32_impl(), lang_items.f32_runtime_impl()),
1327 F64 => both(lang_items.f64_impl(), lang_items.f64_runtime_impl()),
1328 Char => single(lang_items.char_impl()),
1329 Bool => single(lang_items.bool_impl()),
1330 Str => both(lang_items.str_impl(), lang_items.str_alloc_impl()),
1335 .chain(lang_items.slice_u8_impl())
1336 .chain(lang_items.slice_alloc_impl())
1337 .chain(lang_items.slice_u8_alloc_impl())
1340 Array => single(lang_items.array_impl()),
1341 Tuple => smallvec![],
1342 Unit => smallvec![],
1347 .chain(lang_items.mut_ptr_impl())
1348 .chain(lang_items.const_slice_ptr_impl())
1349 .chain(lang_items.mut_slice_ptr_impl())
1352 Reference => smallvec![],
1354 Never => smallvec![],
1359 pub fn to_url_str(&self) -> &'static str {
1364 impl From<ast::IntTy> for PrimitiveType {
1365 fn from(int_ty: ast::IntTy) -> PrimitiveType {
1367 ast::IntTy::Isize => PrimitiveType::Isize,
1368 ast::IntTy::I8 => PrimitiveType::I8,
1369 ast::IntTy::I16 => PrimitiveType::I16,
1370 ast::IntTy::I32 => PrimitiveType::I32,
1371 ast::IntTy::I64 => PrimitiveType::I64,
1372 ast::IntTy::I128 => PrimitiveType::I128,
1377 impl From<ast::UintTy> for PrimitiveType {
1378 fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1380 ast::UintTy::Usize => PrimitiveType::Usize,
1381 ast::UintTy::U8 => PrimitiveType::U8,
1382 ast::UintTy::U16 => PrimitiveType::U16,
1383 ast::UintTy::U32 => PrimitiveType::U32,
1384 ast::UintTy::U64 => PrimitiveType::U64,
1385 ast::UintTy::U128 => PrimitiveType::U128,
1390 impl From<ast::FloatTy> for PrimitiveType {
1391 fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1393 ast::FloatTy::F32 => PrimitiveType::F32,
1394 ast::FloatTy::F64 => PrimitiveType::F64,
1399 impl From<hir::PrimTy> for PrimitiveType {
1400 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1402 hir::PrimTy::Int(int_ty) => int_ty.into(),
1403 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1404 hir::PrimTy::Float(float_ty) => float_ty.into(),
1405 hir::PrimTy::Str => PrimitiveType::Str,
1406 hir::PrimTy::Bool => PrimitiveType::Bool,
1407 hir::PrimTy::Char => PrimitiveType::Char,
1412 #[derive(Clone, PartialEq, Eq, Debug)]
1413 pub enum Visibility {
1417 Restricted(DefId, Path),
1420 #[derive(Clone, Debug)]
1422 pub struct_type: doctree::StructType,
1423 pub generics: Generics,
1424 pub fields: Vec<Item>,
1425 pub fields_stripped: bool,
1428 #[derive(Clone, Debug)]
1430 pub struct_type: doctree::StructType,
1431 pub generics: Generics,
1432 pub fields: Vec<Item>,
1433 pub fields_stripped: bool,
1436 /// This is a more limited form of the standard Struct, different in that
1437 /// it lacks the things most items have (name, id, parameterization). Found
1438 /// only as a variant in an enum.
1439 #[derive(Clone, Debug)]
1440 pub struct VariantStruct {
1441 pub struct_type: doctree::StructType,
1442 pub fields: Vec<Item>,
1443 pub fields_stripped: bool,
1446 #[derive(Clone, Debug)]
1448 pub variants: IndexVec<VariantIdx, Item>,
1449 pub generics: Generics,
1450 pub variants_stripped: bool,
1453 #[derive(Clone, Debug)]
1454 pub struct Variant {
1455 pub kind: VariantKind,
1458 #[derive(Clone, Debug)]
1459 pub enum VariantKind {
1462 Struct(VariantStruct),
1465 #[derive(Clone, Debug)]
1467 pub filename: FileName,
1473 pub original: rustc_span::Span,
1477 pub fn empty() -> Span {
1479 filename: FileName::Anon(0),
1485 original: rustc_span::DUMMY_SP,
1489 pub fn span(&self) -> rustc_span::Span {
1494 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1498 pub segments: Vec<PathSegment>,
1502 pub fn last_name(&self) -> &str {
1503 self.segments.last().expect("segments were empty").name.as_str()
1507 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1508 pub enum GenericArg {
1514 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1515 pub enum GenericArgs {
1516 AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
1517 Parenthesized { inputs: Vec<Type>, output: Option<Type> },
1520 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1521 pub struct PathSegment {
1523 pub args: GenericArgs,
1526 #[derive(Clone, Debug)]
1527 pub struct Typedef {
1529 pub generics: Generics,
1530 // Type of target item.
1531 pub item_type: Option<Type>,
1534 impl GetDefId for Typedef {
1535 fn def_id(&self) -> Option<DefId> {
1540 #[derive(Clone, Debug)]
1541 pub struct OpaqueTy {
1542 pub bounds: Vec<GenericBound>,
1543 pub generics: Generics,
1546 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1547 pub struct BareFunctionDecl {
1548 pub unsafety: hir::Unsafety,
1549 pub generic_params: Vec<GenericParamDef>,
1554 #[derive(Clone, Debug)]
1557 pub mutability: Mutability,
1558 /// It's useful to have the value of a static documented, but I have no
1559 /// desire to represent expressions (that'd basically be all of the AST,
1560 /// which is huge!). So, have a string.
1564 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
1565 pub struct Constant {
1568 pub value: Option<String>,
1569 pub is_literal: bool,
1572 #[derive(Clone, PartialEq, Debug)]
1573 pub enum ImplPolarity {
1578 #[derive(Clone, Debug)]
1580 pub unsafety: hir::Unsafety,
1581 pub generics: Generics,
1582 pub provided_trait_methods: FxHashSet<String>,
1583 pub trait_: Option<Type>,
1585 pub items: Vec<Item>,
1586 pub polarity: Option<ImplPolarity>,
1587 pub synthetic: bool,
1588 pub blanket_impl: Option<Type>,
1591 #[derive(Clone, Debug)]
1593 // use source as str;
1594 Simple(String, ImportSource),
1599 #[derive(Clone, Debug)]
1600 pub struct ImportSource {
1602 pub did: Option<DefId>,
1605 #[derive(Clone, Debug)]
1608 pub imported_from: Option<String>,
1611 #[derive(Clone, Debug)]
1612 pub struct ProcMacro {
1613 pub kind: MacroKind,
1614 pub helpers: Vec<String>,
1617 #[derive(Clone, Debug)]
1618 pub struct Stability {
1619 pub level: stability::StabilityLevel,
1620 pub feature: String,
1622 pub unstable_reason: Option<String>,
1623 pub issue: Option<NonZeroU32>,
1626 #[derive(Clone, Debug)]
1627 pub struct Deprecation {
1628 pub since: Option<String>,
1629 pub note: Option<String>,
1630 pub is_since_rustc_version: bool,
1633 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
1634 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
1635 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1636 pub struct TypeBinding {
1638 pub kind: TypeBindingKind,
1641 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1642 pub enum TypeBindingKind {
1643 Equality { ty: Type },
1644 Constraint { bounds: Vec<GenericBound> },
1648 pub fn ty(&self) -> &Type {
1650 TypeBindingKind::Equality { ref ty } => ty,
1651 _ => panic!("expected equality type binding for parenthesized generic args"),