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;
20 use rustc_hir::Mutability;
21 use rustc_index::vec::IndexVec;
22 use rustc_middle::middle::stability;
23 use rustc_middle::ty::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_associated(&self) -> bool {
287 ItemEnum::TypedefItem(_, _) | ItemEnum::AssocTypeItem(_, _) => true,
293 #[derive(Clone, Debug)]
295 pub items: Vec<Item>,
299 pub struct ListAttributesIter<'a> {
300 attrs: slice::Iter<'a, ast::Attribute>,
301 current_list: vec::IntoIter<ast::NestedMetaItem>,
305 impl<'a> Iterator for ListAttributesIter<'a> {
306 type Item = ast::NestedMetaItem;
308 fn next(&mut self) -> Option<Self::Item> {
309 if let Some(nested) = self.current_list.next() {
313 for attr in &mut self.attrs {
314 if let Some(list) = attr.meta_item_list() {
315 if attr.has_name(self.name) {
316 self.current_list = list.into_iter();
317 if let Some(nested) = self.current_list.next() {
327 fn size_hint(&self) -> (usize, Option<usize>) {
328 let lower = self.current_list.len();
333 pub trait AttributesExt {
334 /// Finds an attribute as List and returns the list of attributes nested inside.
335 fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
338 impl AttributesExt for [ast::Attribute] {
339 fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
340 ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), name }
344 pub trait NestedAttributesExt {
345 /// Returns `true` if the attribute list contains a specific `Word`
346 fn has_word(self, word: Symbol) -> bool;
349 impl<I: IntoIterator<Item = ast::NestedMetaItem>> NestedAttributesExt for I {
350 fn has_word(self, word: Symbol) -> bool {
351 self.into_iter().any(|attr| attr.is_word() && attr.has_name(word))
355 /// A portion of documentation, extracted from a `#[doc]` attribute.
357 /// Each variant contains the line number within the complete doc-comment where the fragment
358 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
360 /// Included files are kept separate from inline doc comments so that proper line-number
361 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
362 /// kept separate because of issue #42760.
363 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
364 pub enum DocFragment {
365 /// A doc fragment created from a `///` or `//!` doc comment.
366 SugaredDoc(usize, rustc_span::Span, String),
367 /// A doc fragment created from a "raw" `#[doc=""]` attribute.
368 RawDoc(usize, rustc_span::Span, String),
369 /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
370 /// given filename and the file contents.
371 Include(usize, rustc_span::Span, String, String),
375 pub fn as_str(&self) -> &str {
377 DocFragment::SugaredDoc(_, _, ref s) => &s[..],
378 DocFragment::RawDoc(_, _, ref s) => &s[..],
379 DocFragment::Include(_, _, _, ref s) => &s[..],
383 pub fn span(&self) -> rustc_span::Span {
385 DocFragment::SugaredDoc(_, span, _)
386 | DocFragment::RawDoc(_, span, _)
387 | DocFragment::Include(_, span, _, _) => span,
392 impl<'a> FromIterator<&'a DocFragment> for String {
393 fn from_iter<T>(iter: T) -> Self
395 T: IntoIterator<Item = &'a DocFragment>,
397 iter.into_iter().fold(String::new(), |mut acc, frag| {
402 DocFragment::SugaredDoc(_, _, ref docs)
403 | DocFragment::RawDoc(_, _, ref docs)
404 | DocFragment::Include(_, _, _, ref docs) => acc.push_str(docs),
412 #[derive(Clone, Debug, Default)]
413 pub struct Attributes {
414 pub doc_strings: Vec<DocFragment>,
415 pub other_attrs: Vec<ast::Attribute>,
416 pub cfg: Option<Arc<Cfg>>,
417 pub span: Option<rustc_span::Span>,
418 /// map from Rust paths to resolved defs and potential URL fragments
419 pub links: Vec<(String, Option<DefId>, Option<String>)>,
420 pub inner_docs: bool,
424 /// Extracts the content from an attribute `#[doc(cfg(content))]`.
425 pub fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
426 use rustc_ast::NestedMetaItem::MetaItem;
428 if let ast::MetaItemKind::List(ref nmis) = mi.kind {
430 if let MetaItem(ref cfg_mi) = nmis[0] {
431 if cfg_mi.has_name(sym::cfg) {
432 if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.kind {
433 if cfg_nmis.len() == 1 {
434 if let MetaItem(ref content_mi) = cfg_nmis[0] {
435 return Some(content_mi);
447 /// Reads a `MetaItem` from within an attribute, looks for whether it is a
448 /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
450 pub fn extract_include(mi: &ast::MetaItem) -> Option<(String, String)> {
451 mi.meta_item_list().and_then(|list| {
453 if meta.has_name(sym::include) {
454 // the actual compiled `#[doc(include="filename")]` gets expanded to
455 // `#[doc(include(file="filename", contents="file contents")]` so we need to
456 // look for that instead
457 return meta.meta_item_list().and_then(|list| {
458 let mut filename: Option<String> = None;
459 let mut contents: Option<String> = None;
462 if it.has_name(sym::file) {
463 if let Some(name) = it.value_str() {
464 filename = Some(name.to_string());
466 } else if it.has_name(sym::contents) {
467 if let Some(docs) = it.value_str() {
468 contents = Some(docs.to_string());
473 if let (Some(filename), Some(contents)) = (filename, contents) {
474 Some((filename, contents))
486 pub fn has_doc_flag(&self, flag: Symbol) -> bool {
487 for attr in &self.other_attrs {
488 if !attr.has_name(sym::doc) {
492 if let Some(items) = attr.meta_item_list() {
493 if items.iter().filter_map(|i| i.meta_item()).any(|it| it.has_name(flag)) {
502 pub fn from_ast(diagnostic: &::rustc_errors::Handler, attrs: &[ast::Attribute]) -> Attributes {
503 let mut doc_strings = vec![];
505 let mut cfg = Cfg::True;
506 let mut doc_line = 0;
508 let other_attrs = attrs
511 if let Some(value) = attr.doc_str() {
512 let value = beautify_doc_string(value);
513 let mk_fragment: fn(_, _, _) -> _ = if attr.is_doc_comment() {
514 DocFragment::SugaredDoc
520 doc_line += value.lines().count();
521 doc_strings.push(mk_fragment(line, attr.span, value));
524 sp = Some(attr.span);
528 if attr.has_name(sym::doc) {
529 if let Some(mi) = attr.meta() {
530 if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
531 // Extracted #[doc(cfg(...))]
532 match Cfg::parse(cfg_mi) {
533 Ok(new_cfg) => cfg &= new_cfg,
534 Err(e) => diagnostic.span_err(e.span, e.msg),
536 } else if let Some((filename, contents)) =
537 Attributes::extract_include(&mi)
540 doc_line += contents.lines().count();
541 doc_strings.push(DocFragment::Include(
542 line, attr.span, filename, contents,
552 // treat #[target_feature(enable = "feat")] attributes as if they were
553 // #[doc(cfg(target_feature = "feat"))] attributes as well
554 for attr in attrs.lists(sym::target_feature) {
555 if attr.has_name(sym::enable) {
556 if let Some(feat) = attr.value_str() {
557 let meta = attr::mk_name_value_item_str(
558 Ident::with_dummy_span(sym::target_feature),
562 if let Ok(feat_cfg) = Cfg::parse(&meta) {
569 let inner_docs = attrs
571 .find(|a| a.doc_str().is_some())
572 .map_or(true, |a| a.style == AttrStyle::Inner);
577 cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) },
584 /// Finds the `doc` attribute as a NameValue and returns the corresponding
586 pub fn doc_value(&self) -> Option<&str> {
587 self.doc_strings.first().map(|s| s.as_str())
590 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
592 pub fn collapsed_doc_value(&self) -> Option<String> {
593 if !self.doc_strings.is_empty() { Some(self.doc_strings.iter().collect()) } else { None }
596 /// Gets links as a vector
598 /// Cache must be populated before call
599 pub fn links(&self, krate: &CrateNum) -> Vec<(String, String)> {
600 use crate::html::format::href;
601 use crate::html::render::CURRENT_DEPTH;
605 .filter_map(|&(ref s, did, ref fragment)| {
608 if let Some((mut href, ..)) = href(did) {
609 if let Some(ref fragment) = *fragment {
611 href.push_str(fragment);
613 Some((s.clone(), href))
619 if let Some(ref fragment) = *fragment {
621 let url = match cache.extern_locations.get(krate) {
622 Some(&(_, _, ExternalLocation::Local)) => {
623 let depth = CURRENT_DEPTH.with(|l| l.get());
626 Some(&(_, _, ExternalLocation::Remote(ref s))) => s.to_string(),
627 Some(&(_, _, ExternalLocation::Unknown)) | None => {
628 String::from("https://doc.rust-lang.org/nightly")
631 // This is a primitive so the url is done "by hand".
632 let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
636 "{}{}std/primitive.{}.html{}",
638 if !url.ends_with('/') { "/" } else { "" },
644 panic!("This isn't a primitive?!");
652 pub fn get_doc_aliases(&self) -> FxHashSet<String> {
655 .filter(|a| a.has_name(sym::alias))
656 .filter_map(|a| a.value_str().map(|s| s.to_string().replace("\"", "")))
657 .filter(|v| !v.is_empty())
658 .collect::<FxHashSet<_>>()
662 impl PartialEq for Attributes {
663 fn eq(&self, rhs: &Self) -> bool {
664 self.doc_strings == rhs.doc_strings
665 && self.cfg == rhs.cfg
666 && self.span == rhs.span
667 && self.links == rhs.links
672 .eq(rhs.other_attrs.iter().map(|attr| attr.id))
676 impl Eq for Attributes {}
678 impl Hash for Attributes {
679 fn hash<H: Hasher>(&self, hasher: &mut H) {
680 self.doc_strings.hash(hasher);
681 self.cfg.hash(hasher);
682 self.span.hash(hasher);
683 self.links.hash(hasher);
684 for attr in &self.other_attrs {
685 attr.id.hash(hasher);
690 impl AttributesExt for Attributes {
691 fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
692 self.other_attrs.lists(name)
696 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
697 pub enum GenericBound {
698 TraitBound(PolyTrait, hir::TraitBoundModifier),
703 pub fn maybe_sized(cx: &DocContext<'_>) -> GenericBound {
704 let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None);
705 let empty = cx.tcx.intern_substs(&[]);
706 let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
707 inline::record_extern_fqn(cx, did, TypeKind::Trait);
708 GenericBound::TraitBound(
710 trait_: ResolvedPath { path, param_names: None, did, is_generic: false },
711 generic_params: Vec::new(),
713 hir::TraitBoundModifier::Maybe,
717 pub fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
718 use rustc_hir::TraitBoundModifier as TBM;
719 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
720 if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
727 pub fn get_poly_trait(&self) -> Option<PolyTrait> {
728 if let GenericBound::TraitBound(ref p, _) = *self {
729 return Some(p.clone());
734 pub fn get_trait_type(&self) -> Option<Type> {
735 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
743 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
744 pub struct Lifetime(pub String);
747 pub fn get_ref<'a>(&'a self) -> &'a str {
748 let Lifetime(ref s) = *self;
753 pub fn statik() -> Lifetime {
754 Lifetime("'static".to_string())
757 pub fn elided() -> Lifetime {
758 Lifetime("'_".to_string())
762 #[derive(Clone, Debug)]
763 pub enum WherePredicate {
764 BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
765 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
766 EqPredicate { lhs: Type, rhs: Type },
769 impl WherePredicate {
770 pub fn get_bounds(&self) -> Option<&[GenericBound]> {
772 WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
773 WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
779 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
780 pub enum GenericParamDefKind {
784 bounds: Vec<GenericBound>,
785 default: Option<Type>,
786 synthetic: Option<hir::SyntheticTyParamKind>,
794 impl GenericParamDefKind {
795 pub fn is_type(&self) -> bool {
797 GenericParamDefKind::Type { .. } => true,
802 // FIXME(eddyb) this either returns the default of a type parameter, or the
803 // type of a `const` parameter. It seems that the intention is to *visit*
804 // any embedded types, but `get_type` seems to be the wrong name for that.
805 pub fn get_type(&self) -> Option<Type> {
807 GenericParamDefKind::Type { default, .. } => default.clone(),
808 GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
809 GenericParamDefKind::Lifetime => None,
814 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
815 pub struct GenericParamDef {
817 pub kind: GenericParamDefKind,
820 impl GenericParamDef {
821 pub fn is_synthetic_type_param(&self) -> bool {
823 GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => false,
824 GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
828 pub fn is_type(&self) -> bool {
832 pub fn get_type(&self) -> Option<Type> {
836 pub fn get_bounds(&self) -> Option<&[GenericBound]> {
838 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
844 // maybe use a Generic enum and use Vec<Generic>?
845 #[derive(Clone, Debug, Default)]
846 pub struct Generics {
847 pub params: Vec<GenericParamDef>,
848 pub where_predicates: Vec<WherePredicate>,
851 #[derive(Clone, Debug)]
853 pub generics: Generics,
855 pub header: hir::FnHeader,
856 pub defaultness: Option<hir::Defaultness>,
857 pub all_types: Vec<(Type, TypeKind)>,
858 pub ret_types: Vec<(Type, TypeKind)>,
861 #[derive(Clone, Debug)]
862 pub struct TyMethod {
863 pub header: hir::FnHeader,
865 pub generics: Generics,
866 pub all_types: Vec<(Type, TypeKind)>,
867 pub ret_types: Vec<(Type, TypeKind)>,
870 #[derive(Clone, Debug)]
871 pub struct Function {
873 pub generics: Generics,
874 pub header: hir::FnHeader,
875 pub all_types: Vec<(Type, TypeKind)>,
876 pub ret_types: Vec<(Type, TypeKind)>,
879 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
881 pub inputs: Arguments,
883 pub c_variadic: bool,
884 pub attrs: Attributes,
888 pub fn self_type(&self) -> Option<SelfTy> {
889 self.inputs.values.get(0).and_then(|v| v.to_self())
892 /// Returns the sugared return type for an async function.
894 /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
895 /// will return `i32`.
899 /// This function will panic if the return type does not match the expected sugaring for async
901 pub fn sugared_async_return_type(&self) -> FnRetTy {
903 FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
904 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
905 let bindings = trait_.bindings().unwrap();
906 FnRetTy::Return(bindings[0].ty().clone())
908 _ => panic!("unexpected desugaring of async function"),
910 _ => panic!("unexpected desugaring of async function"),
915 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
916 pub struct Arguments {
917 pub values: Vec<Argument>,
920 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
921 pub struct Argument {
926 #[derive(Clone, PartialEq, Debug)]
929 SelfBorrowed(Option<Lifetime>, Mutability),
934 pub fn to_self(&self) -> Option<SelfTy> {
935 if self.name != "self" {
938 if self.type_.is_self_type() {
939 return Some(SelfValue);
942 BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
943 Some(SelfBorrowed(lifetime.clone(), mutability))
945 _ => Some(SelfExplicit(self.type_.clone())),
950 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
956 impl GetDefId for FnRetTy {
957 fn def_id(&self) -> Option<DefId> {
959 Return(ref ty) => ty.def_id(),
960 DefaultReturn => None,
965 #[derive(Clone, Debug)]
968 pub unsafety: hir::Unsafety,
969 pub items: Vec<Item>,
970 pub generics: Generics,
971 pub bounds: Vec<GenericBound>,
972 pub is_spotlight: bool,
976 #[derive(Clone, Debug)]
977 pub struct TraitAlias {
978 pub generics: Generics,
979 pub bounds: Vec<GenericBound>,
982 /// A trait reference, which may have higher ranked lifetimes.
983 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
984 pub struct PolyTrait {
986 pub generic_params: Vec<GenericParamDef>,
989 /// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
990 /// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
991 /// importantly, it does not preserve mutability or boxes.
992 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
994 /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
997 param_names: Option<Vec<GenericBound>>,
999 /// `true` if is a `T::Name` path for associated types.
1002 /// For parameterized types, so the consumer of the JSON don't go
1003 /// looking for types which don't exist anywhere.
1005 /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
1006 /// arrays, slices, and tuples.
1007 Primitive(PrimitiveType),
1008 /// `extern "ABI" fn`
1009 BareFunction(Box<BareFunctionDecl>),
1012 Array(Box<Type>, String),
1014 RawPointer(Mutability, Box<Type>),
1016 lifetime: Option<Lifetime>,
1017 mutability: Mutability,
1021 // `<Type as Trait>::Name`
1024 self_type: Box<Type>,
1031 // `impl TraitA + TraitB + ...`
1032 ImplTrait(Vec<GenericBound>),
1035 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1036 pub enum PrimitiveType {
1064 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1082 pub trait GetDefId {
1083 fn def_id(&self) -> Option<DefId>;
1086 impl<T: GetDefId> GetDefId for Option<T> {
1087 fn def_id(&self) -> Option<DefId> {
1088 self.as_ref().and_then(|d| d.def_id())
1093 pub fn primitive_type(&self) -> Option<PrimitiveType> {
1095 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1096 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1097 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1100 Some(PrimitiveType::Unit)
1102 Some(PrimitiveType::Tuple)
1105 RawPointer(..) => Some(PrimitiveType::RawPointer),
1106 BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
1107 BareFunction(..) => Some(PrimitiveType::Fn),
1108 Never => Some(PrimitiveType::Never),
1113 pub fn is_generic(&self) -> bool {
1115 ResolvedPath { is_generic, .. } => is_generic,
1120 pub fn is_self_type(&self) -> bool {
1122 Generic(ref name) => name == "Self",
1127 pub fn generics(&self) -> Option<Vec<Type>> {
1129 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1130 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
1133 .filter_map(|arg| match arg {
1134 GenericArg::Type(ty) => Some(ty.clone()),
1147 pub fn bindings(&self) -> Option<&[TypeBinding]> {
1149 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1150 if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
1160 pub fn is_full_generic(&self) -> bool {
1162 Type::Generic(_) => true,
1167 pub fn projection(&self) -> Option<(&Type, DefId, &str)> {
1168 let (self_, trait_, name) = match self {
1169 QPath { ref self_type, ref trait_, ref name } => (self_type, trait_, name),
1172 let trait_did = match **trait_ {
1173 ResolvedPath { did, .. } => did,
1176 Some((&self_, trait_did, name))
1180 impl GetDefId for Type {
1181 fn def_id(&self) -> Option<DefId> {
1183 ResolvedPath { did, .. } => Some(did),
1184 Primitive(p) => cache().primitive_locations.get(&p).cloned(),
1185 BorrowedRef { type_: box Generic(..), .. } => {
1186 Primitive(PrimitiveType::Reference).def_id()
1188 BorrowedRef { ref type_, .. } => type_.def_id(),
1191 Primitive(PrimitiveType::Unit).def_id()
1193 Primitive(PrimitiveType::Tuple).def_id()
1196 BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
1197 Never => Primitive(PrimitiveType::Never).def_id(),
1198 Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
1199 Array(..) => Primitive(PrimitiveType::Array).def_id(),
1200 RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(),
1201 QPath { ref self_type, .. } => self_type.def_id(),
1207 impl PrimitiveType {
1208 pub fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1210 sym::isize => Some(PrimitiveType::Isize),
1211 sym::i8 => Some(PrimitiveType::I8),
1212 sym::i16 => Some(PrimitiveType::I16),
1213 sym::i32 => Some(PrimitiveType::I32),
1214 sym::i64 => Some(PrimitiveType::I64),
1215 sym::i128 => Some(PrimitiveType::I128),
1216 sym::usize => Some(PrimitiveType::Usize),
1217 sym::u8 => Some(PrimitiveType::U8),
1218 sym::u16 => Some(PrimitiveType::U16),
1219 sym::u32 => Some(PrimitiveType::U32),
1220 sym::u64 => Some(PrimitiveType::U64),
1221 sym::u128 => Some(PrimitiveType::U128),
1222 sym::bool => Some(PrimitiveType::Bool),
1223 sym::char => Some(PrimitiveType::Char),
1224 sym::str => Some(PrimitiveType::Str),
1225 sym::f32 => Some(PrimitiveType::F32),
1226 sym::f64 => Some(PrimitiveType::F64),
1227 sym::array => Some(PrimitiveType::Array),
1228 sym::slice => Some(PrimitiveType::Slice),
1229 sym::tuple => Some(PrimitiveType::Tuple),
1230 sym::unit => Some(PrimitiveType::Unit),
1231 sym::pointer => Some(PrimitiveType::RawPointer),
1232 sym::reference => Some(PrimitiveType::Reference),
1233 kw::Fn => Some(PrimitiveType::Fn),
1234 sym::never => Some(PrimitiveType::Never),
1239 pub fn as_str(&self) -> &'static str {
1240 use self::PrimitiveType::*;
1263 RawPointer => "pointer",
1264 Reference => "reference",
1270 pub fn impls(&self, tcx: TyCtxt<'_>) -> &'static SmallVec<[DefId; 4]> {
1271 Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
1274 pub fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>> {
1275 static CELL: OnceCell<FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>>> = OnceCell::new();
1277 CELL.get_or_init(move || {
1278 use self::PrimitiveType::*;
1280 /// A macro to create a FxHashMap.
1285 /// let letters = map!{"a" => "b", "c" => "d"};
1288 /// Trailing commas are allowed.
1289 /// Commas between elements are required (even if the expression is a block).
1291 ($( $key: expr => $val: expr ),* $(,)*) => {{
1292 let mut map = ::rustc_data_structures::fx::FxHashMap::default();
1293 $( map.insert($key, $val); )*
1298 let single = |a: Option<DefId>| a.into_iter().collect();
1299 let both = |a: Option<DefId>, b: Option<DefId>| -> SmallVec<_> {
1300 a.into_iter().chain(b).collect()
1303 let lang_items = tcx.lang_items();
1305 Isize => single(lang_items.isize_impl()),
1306 I8 => single(lang_items.i8_impl()),
1307 I16 => single(lang_items.i16_impl()),
1308 I32 => single(lang_items.i32_impl()),
1309 I64 => single(lang_items.i64_impl()),
1310 I128 => single(lang_items.i128_impl()),
1311 Usize => single(lang_items.usize_impl()),
1312 U8 => single(lang_items.u8_impl()),
1313 U16 => single(lang_items.u16_impl()),
1314 U32 => single(lang_items.u32_impl()),
1315 U64 => single(lang_items.u64_impl()),
1316 U128 => single(lang_items.u128_impl()),
1317 F32 => both(lang_items.f32_impl(), lang_items.f32_runtime_impl()),
1318 F64 => both(lang_items.f64_impl(), lang_items.f64_runtime_impl()),
1319 Char => single(lang_items.char_impl()),
1320 Bool => single(lang_items.bool_impl()),
1321 Str => both(lang_items.str_impl(), lang_items.str_alloc_impl()),
1326 .chain(lang_items.slice_u8_impl())
1327 .chain(lang_items.slice_alloc_impl())
1328 .chain(lang_items.slice_u8_alloc_impl())
1331 Array => single(lang_items.array_impl()),
1332 Tuple => smallvec![],
1333 Unit => smallvec![],
1338 .chain(lang_items.mut_ptr_impl())
1339 .chain(lang_items.const_slice_ptr_impl())
1340 .chain(lang_items.mut_slice_ptr_impl())
1343 Reference => smallvec![],
1345 Never => smallvec![],
1350 pub fn to_url_str(&self) -> &'static str {
1355 impl From<ast::IntTy> for PrimitiveType {
1356 fn from(int_ty: ast::IntTy) -> PrimitiveType {
1358 ast::IntTy::Isize => PrimitiveType::Isize,
1359 ast::IntTy::I8 => PrimitiveType::I8,
1360 ast::IntTy::I16 => PrimitiveType::I16,
1361 ast::IntTy::I32 => PrimitiveType::I32,
1362 ast::IntTy::I64 => PrimitiveType::I64,
1363 ast::IntTy::I128 => PrimitiveType::I128,
1368 impl From<ast::UintTy> for PrimitiveType {
1369 fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1371 ast::UintTy::Usize => PrimitiveType::Usize,
1372 ast::UintTy::U8 => PrimitiveType::U8,
1373 ast::UintTy::U16 => PrimitiveType::U16,
1374 ast::UintTy::U32 => PrimitiveType::U32,
1375 ast::UintTy::U64 => PrimitiveType::U64,
1376 ast::UintTy::U128 => PrimitiveType::U128,
1381 impl From<ast::FloatTy> for PrimitiveType {
1382 fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1384 ast::FloatTy::F32 => PrimitiveType::F32,
1385 ast::FloatTy::F64 => PrimitiveType::F64,
1390 impl From<hir::PrimTy> for PrimitiveType {
1391 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1393 hir::PrimTy::Int(int_ty) => int_ty.into(),
1394 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1395 hir::PrimTy::Float(float_ty) => float_ty.into(),
1396 hir::PrimTy::Str => PrimitiveType::Str,
1397 hir::PrimTy::Bool => PrimitiveType::Bool,
1398 hir::PrimTy::Char => PrimitiveType::Char,
1403 #[derive(Clone, PartialEq, Eq, Debug)]
1404 pub enum Visibility {
1408 Restricted(DefId, Path),
1411 #[derive(Clone, Debug)]
1413 pub struct_type: doctree::StructType,
1414 pub generics: Generics,
1415 pub fields: Vec<Item>,
1416 pub fields_stripped: bool,
1419 #[derive(Clone, Debug)]
1421 pub struct_type: doctree::StructType,
1422 pub generics: Generics,
1423 pub fields: Vec<Item>,
1424 pub fields_stripped: bool,
1427 /// This is a more limited form of the standard Struct, different in that
1428 /// it lacks the things most items have (name, id, parameterization). Found
1429 /// only as a variant in an enum.
1430 #[derive(Clone, Debug)]
1431 pub struct VariantStruct {
1432 pub struct_type: doctree::StructType,
1433 pub fields: Vec<Item>,
1434 pub fields_stripped: bool,
1437 #[derive(Clone, Debug)]
1439 pub variants: IndexVec<VariantIdx, Item>,
1440 pub generics: Generics,
1441 pub variants_stripped: bool,
1444 #[derive(Clone, Debug)]
1445 pub struct Variant {
1446 pub kind: VariantKind,
1449 #[derive(Clone, Debug)]
1450 pub enum VariantKind {
1453 Struct(VariantStruct),
1456 #[derive(Clone, Debug)]
1458 pub filename: FileName,
1464 pub original: rustc_span::Span,
1468 pub fn empty() -> Span {
1470 filename: FileName::Anon(0),
1476 original: rustc_span::DUMMY_SP,
1480 pub fn span(&self) -> rustc_span::Span {
1485 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1489 pub segments: Vec<PathSegment>,
1493 pub fn last_name(&self) -> &str {
1494 self.segments.last().expect("segments were empty").name.as_str()
1498 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1499 pub enum GenericArg {
1505 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1506 pub enum GenericArgs {
1507 AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
1508 Parenthesized { inputs: Vec<Type>, output: Option<Type> },
1511 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1512 pub struct PathSegment {
1514 pub args: GenericArgs,
1517 #[derive(Clone, Debug)]
1518 pub struct Typedef {
1520 pub generics: Generics,
1521 // Type of target item.
1522 pub item_type: Option<Type>,
1525 impl GetDefId for Typedef {
1526 fn def_id(&self) -> Option<DefId> {
1531 #[derive(Clone, Debug)]
1532 pub struct OpaqueTy {
1533 pub bounds: Vec<GenericBound>,
1534 pub generics: Generics,
1537 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1538 pub struct BareFunctionDecl {
1539 pub unsafety: hir::Unsafety,
1540 pub generic_params: Vec<GenericParamDef>,
1545 #[derive(Clone, Debug)]
1548 pub mutability: Mutability,
1549 /// It's useful to have the value of a static documented, but I have no
1550 /// desire to represent expressions (that'd basically be all of the AST,
1551 /// which is huge!). So, have a string.
1555 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
1556 pub struct Constant {
1559 pub value: Option<String>,
1560 pub is_literal: bool,
1563 #[derive(Clone, PartialEq, Debug)]
1564 pub enum ImplPolarity {
1569 #[derive(Clone, Debug)]
1571 pub unsafety: hir::Unsafety,
1572 pub generics: Generics,
1573 pub provided_trait_methods: FxHashSet<String>,
1574 pub trait_: Option<Type>,
1576 pub items: Vec<Item>,
1577 pub polarity: Option<ImplPolarity>,
1578 pub synthetic: bool,
1579 pub blanket_impl: Option<Type>,
1582 #[derive(Clone, Debug)]
1584 // use source as str;
1585 Simple(String, ImportSource),
1590 #[derive(Clone, Debug)]
1591 pub struct ImportSource {
1593 pub did: Option<DefId>,
1596 #[derive(Clone, Debug)]
1599 pub imported_from: Option<String>,
1602 #[derive(Clone, Debug)]
1603 pub struct ProcMacro {
1604 pub kind: MacroKind,
1605 pub helpers: Vec<String>,
1608 #[derive(Clone, Debug)]
1609 pub struct Stability {
1610 pub level: stability::StabilityLevel,
1611 pub feature: String,
1613 pub unstable_reason: Option<String>,
1614 pub issue: Option<NonZeroU32>,
1617 #[derive(Clone, Debug)]
1618 pub struct Deprecation {
1619 pub since: Option<String>,
1620 pub note: Option<String>,
1621 pub is_since_rustc_version: bool,
1624 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
1625 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
1626 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1627 pub struct TypeBinding {
1629 pub kind: TypeBindingKind,
1632 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1633 pub enum TypeBindingKind {
1634 Equality { ty: Type },
1635 Constraint { bounds: Vec<GenericBound> },
1639 pub fn ty(&self) -> &Type {
1641 TypeBindingKind::Equality { ref ty } => ty,
1642 _ => panic!("expected equality type binding for parenthesized generic args"),