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
,
1409 // Type of target item.
1410 pub item_type
: Option
<Type
>,
1413 impl GetDefId
for Typedef
{
1414 fn def_id(&self) -> Option
<DefId
> {
1419 #[derive(Clone, Debug)]
1420 pub struct OpaqueTy
{
1421 pub bounds
: Vec
<GenericBound
>,
1422 pub generics
: Generics
,
1425 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1426 pub struct BareFunctionDecl
{
1427 pub unsafety
: hir
::Unsafety
,
1428 pub generic_params
: Vec
<GenericParamDef
>,
1433 #[derive(Clone, Debug)]
1436 pub mutability
: Mutability
,
1437 /// It's useful to have the value of a static documented, but I have no
1438 /// desire to represent expressions (that'd basically be all of the AST,
1439 /// which is huge!). So, have a string.
1443 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
1444 pub struct Constant
{
1447 pub value
: Option
<String
>,
1448 pub is_literal
: bool
,
1451 #[derive(Clone, PartialEq, Debug)]
1452 pub enum ImplPolarity
{
1457 #[derive(Clone, Debug)]
1459 pub unsafety
: hir
::Unsafety
,
1460 pub generics
: Generics
,
1461 pub provided_trait_methods
: FxHashSet
<String
>,
1462 pub trait_
: Option
<Type
>,
1464 pub items
: Vec
<Item
>,
1465 pub polarity
: Option
<ImplPolarity
>,
1466 pub synthetic
: bool
,
1467 pub blanket_impl
: Option
<Type
>,
1470 #[derive(Clone, Debug)]
1472 // use source as str;
1473 Simple(String
, ImportSource
),
1478 #[derive(Clone, Debug)]
1479 pub struct ImportSource
{
1481 pub did
: Option
<DefId
>,
1484 #[derive(Clone, Debug)]
1487 pub imported_from
: Option
<String
>,
1490 #[derive(Clone, Debug)]
1491 pub struct ProcMacro
{
1492 pub kind
: MacroKind
,
1493 pub helpers
: Vec
<String
>,
1496 #[derive(Clone, Debug)]
1497 pub struct Stability
{
1498 pub level
: stability
::StabilityLevel
,
1499 pub feature
: Option
<String
>,
1501 pub deprecation
: Option
<Deprecation
>,
1502 pub unstable_reason
: Option
<String
>,
1503 pub issue
: Option
<NonZeroU32
>,
1506 #[derive(Clone, Debug)]
1507 pub struct Deprecation
{
1508 pub since
: Option
<String
>,
1509 pub note
: Option
<String
>,
1512 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
1513 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
1514 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1515 pub struct TypeBinding
{
1517 pub kind
: TypeBindingKind
,
1520 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1521 pub enum TypeBindingKind
{
1522 Equality { ty: Type }
,
1523 Constraint { bounds: Vec<GenericBound> }
,
1527 pub fn ty(&self) -> &Type
{
1529 TypeBindingKind
::Equality { ref ty }
=> ty
,
1530 _
=> panic
!("expected equality type binding for parenthesized generic args"),