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_ast
::ast
::{self, AttrStyle}
;
13 use rustc_ast
::util
::comments
::strip_doc_comment_decoration
;
14 use rustc_data_structures
::fx
::{FxHashMap, FxHashSet}
;
16 use rustc_hir
::def
::Res
;
17 use rustc_hir
::def_id
::{CrateNum, DefId, LOCAL_CRATE}
;
18 use rustc_hir
::lang_items
;
19 use rustc_hir
::Mutability
;
20 use rustc_index
::vec
::IndexVec
;
21 use rustc_middle
::middle
::stability
;
22 use rustc_span
::hygiene
::MacroKind
;
23 use rustc_span
::source_map
::DUMMY_SP
;
24 use rustc_span
::symbol
::{sym, Ident, Symbol}
;
25 use rustc_span
::{self, FileName}
;
26 use rustc_target
::abi
::VariantIdx
;
27 use rustc_target
::spec
::abi
::Abi
;
29 use crate::clean
::cfg
::Cfg
;
30 use crate::clean
::external_path
;
31 use crate::clean
::inline
;
32 use crate::clean
::types
::Type
::{QPath, ResolvedPath}
;
33 use crate::core
::DocContext
;
35 use crate::html
::item_type
::ItemType
;
36 use crate::html
::render
::{cache, ExternalLocation}
;
39 use self::ItemEnum
::*;
43 thread_local
!(pub static MAX_DEF_ID
: RefCell
<FxHashMap
<CrateNum
, DefId
>> = Default
::default());
45 #[derive(Clone, Debug)]
48 pub version
: Option
<String
>,
50 pub module
: Option
<Item
>,
51 pub externs
: Vec
<(CrateNum
, ExternalCrate
)>,
52 pub primitives
: Vec
<(DefId
, PrimitiveType
, Attributes
)>,
53 // These are later on moved into `CACHEKEY`, leaving the map empty.
54 // Only here so that they can be filtered through the rustdoc passes.
55 pub external_traits
: Rc
<RefCell
<FxHashMap
<DefId
, Trait
>>>,
56 pub masked_crates
: FxHashSet
<CrateNum
>,
60 #[derive(Clone, Debug)]
61 pub struct ExternalCrate
{
64 pub attrs
: Attributes
,
65 pub primitives
: Vec
<(DefId
, PrimitiveType
, Attributes
)>,
66 pub keywords
: Vec
<(DefId
, String
, Attributes
)>,
69 /// Anything with a source location and set of attributes and, optionally, a
70 /// name. That is, anything that can be documented. This doesn't correspond
71 /// directly to the AST's concept of an item; it's a strict superset.
76 /// Not everything has a name. E.g., impls
77 pub name
: Option
<String
>,
78 pub attrs
: Attributes
,
80 pub visibility
: Visibility
,
82 pub stability
: Option
<Stability
>,
83 pub deprecation
: Option
<Deprecation
>,
86 impl fmt
::Debug
for Item
{
87 fn fmt(&self, fmt
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
88 let fake
= self.is_fake();
89 let def_id
: &dyn fmt
::Debug
= if fake { &"**FAKE**" }
else { &self.def_id }
;
91 fmt
.debug_struct("Item")
92 .field("source", &self.source
)
93 .field("name", &self.name
)
94 .field("attrs", &self.attrs
)
95 .field("inner", &self.inner
)
96 .field("visibility", &self.visibility
)
97 .field("def_id", def_id
)
98 .field("stability", &self.stability
)
99 .field("deprecation", &self.deprecation
)
105 /// Finds the `doc` attribute as a NameValue and returns the corresponding
107 pub fn doc_value(&self) -> Option
<&str> {
108 self.attrs
.doc_value()
111 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
113 pub fn collapsed_doc_value(&self) -> Option
<String
> {
114 self.attrs
.collapsed_doc_value()
117 pub fn links(&self) -> Vec
<(String
, String
)> {
118 self.attrs
.links(&self.def_id
.krate
)
121 pub fn is_crate(&self) -> bool
{
123 StrippedItem(box ModuleItem(Module { is_crate: true, .. }
))
124 | ModuleItem(Module { is_crate: true, .. }
) => true,
128 pub fn is_mod(&self) -> bool
{
129 self.type_() == ItemType
::Module
131 pub fn is_trait(&self) -> bool
{
132 self.type_() == ItemType
::Trait
134 pub fn is_struct(&self) -> bool
{
135 self.type_() == ItemType
::Struct
137 pub fn is_enum(&self) -> bool
{
138 self.type_() == ItemType
::Enum
140 pub fn is_variant(&self) -> bool
{
141 self.type_() == ItemType
::Variant
143 pub fn is_associated_type(&self) -> bool
{
144 self.type_() == ItemType
::AssocType
146 pub fn is_associated_const(&self) -> bool
{
147 self.type_() == ItemType
::AssocConst
149 pub fn is_method(&self) -> bool
{
150 self.type_() == ItemType
::Method
152 pub fn is_ty_method(&self) -> bool
{
153 self.type_() == ItemType
::TyMethod
155 pub fn is_typedef(&self) -> bool
{
156 self.type_() == ItemType
::Typedef
158 pub fn is_primitive(&self) -> bool
{
159 self.type_() == ItemType
::Primitive
161 pub fn is_union(&self) -> bool
{
162 self.type_() == ItemType
::Union
164 pub fn is_import(&self) -> bool
{
165 self.type_() == ItemType
::Import
167 pub fn is_extern_crate(&self) -> bool
{
168 self.type_() == ItemType
::ExternCrate
170 pub fn is_keyword(&self) -> bool
{
171 self.type_() == ItemType
::Keyword
173 pub fn is_stripped(&self) -> bool
{
175 StrippedItem(..) => true,
179 pub fn has_stripped_fields(&self) -> Option
<bool
> {
181 StructItem(ref _struct
) => Some(_struct
.fields_stripped
),
182 UnionItem(ref union) => Some(union.fields_stripped
),
183 VariantItem(Variant { kind: VariantKind::Struct(ref vstruct) }
) => {
184 Some(vstruct
.fields_stripped
)
190 pub fn stability_class(&self) -> Option
<String
> {
191 self.stability
.as_ref().and_then(|ref s
| {
192 let mut classes
= Vec
::with_capacity(2);
194 if s
.level
== stability
::Unstable
{
195 classes
.push("unstable");
198 if s
.deprecation
.is_some() {
199 classes
.push("deprecated");
202 if !classes
.is_empty() { Some(classes.join(" ")) }
else { None }
206 pub fn stable_since(&self) -> Option
<&str> {
207 self.stability
.as_ref().map(|s
| &s
.since
[..])
210 pub fn is_non_exhaustive(&self) -> bool
{
211 self.attrs
.other_attrs
.iter().any(|a
| a
.check_name(sym
::non_exhaustive
))
214 /// Returns a documentation-level item type from the item.
215 pub fn type_(&self) -> ItemType
{
219 /// Returns the info in the item's `#[deprecated]` or `#[rustc_deprecated]` attributes.
221 /// If the item is not deprecated, returns `None`.
222 pub fn deprecation(&self) -> Option
<&Deprecation
> {
225 .or_else(|| self.stability
.as_ref().and_then(|s
| s
.deprecation
.as_ref()))
227 pub fn is_default(&self) -> bool
{
229 ItemEnum
::MethodItem(ref meth
) => {
230 if let Some(defaultness
) = meth
.defaultness
{
231 defaultness
.has_value() && !defaultness
.is_final()
240 /// See comments on next_def_id
241 pub fn is_fake(&self) -> bool
{
242 MAX_DEF_ID
.with(|m
| {
243 m
.borrow().get(&self.def_id
.krate
).map(|id
| self.def_id
>= *id
).unwrap_or(false)
248 #[derive(Clone, Debug)]
250 ExternCrateItem(String
, Option
<String
>),
255 FunctionItem(Function
),
257 TypedefItem(Typedef
, bool
/* is associated type */),
258 OpaqueTyItem(OpaqueTy
, bool
/* is associated type */),
260 ConstantItem(Constant
),
262 TraitAliasItem(TraitAlias
),
264 /// A method signature only. Used for required methods in traits (ie,
265 /// non-default-methods).
266 TyMethodItem(TyMethod
),
267 /// A method with a body.
269 StructFieldItem(Type
),
270 VariantItem(Variant
),
271 /// `fn`s from an extern block
272 ForeignFunctionItem(Function
),
273 /// `static`s from an extern block
274 ForeignStaticItem(Static
),
275 /// `type`s from an extern block
278 ProcMacroItem(ProcMacro
),
279 PrimitiveItem(PrimitiveType
),
280 AssocConstItem(Type
, Option
<String
>),
281 AssocTypeItem(Vec
<GenericBound
>, Option
<Type
>),
282 /// An item that has been stripped by a rustdoc pass
283 StrippedItem(Box
<ItemEnum
>),
288 pub fn is_associated(&self) -> bool
{
290 ItemEnum
::TypedefItem(_
, _
) | ItemEnum
::AssocTypeItem(_
, _
) => true,
296 #[derive(Clone, Debug)]
298 pub items
: Vec
<Item
>,
302 pub struct ListAttributesIter
<'a
> {
303 attrs
: slice
::Iter
<'a
, ast
::Attribute
>,
304 current_list
: vec
::IntoIter
<ast
::NestedMetaItem
>,
308 impl<'a
> Iterator
for ListAttributesIter
<'a
> {
309 type Item
= ast
::NestedMetaItem
;
311 fn next(&mut self) -> Option
<Self::Item
> {
312 if let Some(nested
) = self.current_list
.next() {
316 for attr
in &mut self.attrs
{
317 if let Some(list
) = attr
.meta_item_list() {
318 if attr
.check_name(self.name
) {
319 self.current_list
= list
.into_iter();
320 if let Some(nested
) = self.current_list
.next() {
330 fn size_hint(&self) -> (usize, Option
<usize>) {
331 let lower
= self.current_list
.len();
336 pub trait AttributesExt
{
337 /// Finds an attribute as List and returns the list of attributes nested inside.
338 fn lists(&self, name
: Symbol
) -> ListAttributesIter
<'_
>;
341 impl AttributesExt
for [ast
::Attribute
] {
342 fn lists(&self, name
: Symbol
) -> ListAttributesIter
<'_
> {
343 ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), name }
347 pub trait NestedAttributesExt
{
348 /// Returns `true` if the attribute list contains a specific `Word`
349 fn has_word(self, word
: Symbol
) -> bool
;
352 impl<I
: IntoIterator
<Item
= ast
::NestedMetaItem
>> NestedAttributesExt
for I
{
353 fn has_word(self, word
: Symbol
) -> bool
{
354 self.into_iter().any(|attr
| attr
.is_word() && attr
.check_name(word
))
358 /// A portion of documentation, extracted from a `#[doc]` attribute.
360 /// Each variant contains the line number within the complete doc-comment where the fragment
361 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
363 /// Included files are kept separate from inline doc comments so that proper line-number
364 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
365 /// kept separate because of issue #42760.
366 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
367 pub enum DocFragment
{
368 /// A doc fragment created from a `///` or `//!` doc comment.
369 SugaredDoc(usize, rustc_span
::Span
, String
),
370 /// A doc fragment created from a "raw" `#[doc=""]` attribute.
371 RawDoc(usize, rustc_span
::Span
, String
),
372 /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
373 /// given filename and the file contents.
374 Include(usize, rustc_span
::Span
, String
, String
),
378 pub fn as_str(&self) -> &str {
380 DocFragment
::SugaredDoc(_
, _
, ref s
) => &s
[..],
381 DocFragment
::RawDoc(_
, _
, ref s
) => &s
[..],
382 DocFragment
::Include(_
, _
, _
, ref s
) => &s
[..],
386 pub fn span(&self) -> rustc_span
::Span
{
388 DocFragment
::SugaredDoc(_
, span
, _
)
389 | DocFragment
::RawDoc(_
, span
, _
)
390 | DocFragment
::Include(_
, span
, _
, _
) => span
,
395 impl<'a
> FromIterator
<&'a DocFragment
> for String
{
396 fn from_iter
<T
>(iter
: T
) -> Self
398 T
: IntoIterator
<Item
= &'a DocFragment
>,
400 iter
.into_iter().fold(String
::new(), |mut acc
, frag
| {
405 DocFragment
::SugaredDoc(_
, _
, ref docs
)
406 | DocFragment
::RawDoc(_
, _
, ref docs
)
407 | DocFragment
::Include(_
, _
, _
, ref docs
) => acc
.push_str(docs
),
415 #[derive(Clone, Debug, Default)]
416 pub struct Attributes
{
417 pub doc_strings
: Vec
<DocFragment
>,
418 pub other_attrs
: Vec
<ast
::Attribute
>,
419 pub cfg
: Option
<Arc
<Cfg
>>,
420 pub span
: Option
<rustc_span
::Span
>,
421 /// map from Rust paths to resolved defs and potential URL fragments
422 pub links
: Vec
<(String
, Option
<DefId
>, Option
<String
>)>,
423 pub inner_docs
: bool
,
427 /// Extracts the content from an attribute `#[doc(cfg(content))]`.
428 pub fn extract_cfg(mi
: &ast
::MetaItem
) -> Option
<&ast
::MetaItem
> {
429 use rustc_ast
::ast
::NestedMetaItem
::MetaItem
;
431 if let ast
::MetaItemKind
::List(ref nmis
) = mi
.kind
{
433 if let MetaItem(ref cfg_mi
) = nmis
[0] {
434 if cfg_mi
.check_name(sym
::cfg
) {
435 if let ast
::MetaItemKind
::List(ref cfg_nmis
) = cfg_mi
.kind
{
436 if cfg_nmis
.len() == 1 {
437 if let MetaItem(ref content_mi
) = cfg_nmis
[0] {
438 return Some(content_mi
);
450 /// Reads a `MetaItem` from within an attribute, looks for whether it is a
451 /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
453 pub fn extract_include(mi
: &ast
::MetaItem
) -> Option
<(String
, String
)> {
454 mi
.meta_item_list().and_then(|list
| {
456 if meta
.check_name(sym
::include
) {
457 // the actual compiled `#[doc(include="filename")]` gets expanded to
458 // `#[doc(include(file="filename", contents="file contents")]` so we need to
459 // look for that instead
460 return meta
.meta_item_list().and_then(|list
| {
461 let mut filename
: Option
<String
> = None
;
462 let mut contents
: Option
<String
> = None
;
465 if it
.check_name(sym
::file
) {
466 if let Some(name
) = it
.value_str() {
467 filename
= Some(name
.to_string());
469 } else if it
.check_name(sym
::contents
) {
470 if let Some(docs
) = it
.value_str() {
471 contents
= Some(docs
.to_string());
476 if let (Some(filename
), Some(contents
)) = (filename
, contents
) {
477 Some((filename
, contents
))
489 /// Enforce the format of attributes inside `#[doc(...)]`.
490 pub fn check_doc_attributes(
491 diagnostic
: &::rustc_errors
::Handler
,
493 ) -> Option
<(String
, String
)> {
494 mi
.meta_item_list().and_then(|list
| {
496 if meta
.check_name(sym
::alias
) {
497 if !meta
.is_value_str()
500 .map(|s
| s
.to_string())
501 .unwrap_or_else(String
::new
)
506 "doc alias attribute expects a string: #[doc(alias = \"0\")]",
516 pub fn has_doc_flag(&self, flag
: Symbol
) -> bool
{
517 for attr
in &self.other_attrs
{
518 if !attr
.check_name(sym
::doc
) {
522 if let Some(items
) = attr
.meta_item_list() {
523 if items
.iter().filter_map(|i
| i
.meta_item()).any(|it
| it
.check_name(flag
)) {
532 pub fn from_ast(diagnostic
: &::rustc_errors
::Handler
, attrs
: &[ast
::Attribute
]) -> Attributes
{
533 let mut doc_strings
= vec
![];
535 let mut cfg
= Cfg
::True
;
536 let mut doc_line
= 0;
538 let other_attrs
= attrs
541 if let Some(value
) = attr
.doc_str() {
542 let (value
, mk_fragment
): (_
, fn(_
, _
, _
) -> _
) = if attr
.is_doc_comment() {
543 (strip_doc_comment_decoration(&value
.as_str()), DocFragment
::SugaredDoc
)
545 (value
.to_string(), DocFragment
::RawDoc
)
549 doc_line
+= value
.lines().count();
550 doc_strings
.push(mk_fragment(line
, attr
.span
, value
));
553 sp
= Some(attr
.span
);
557 if attr
.check_name(sym
::doc
) {
558 if let Some(mi
) = attr
.meta() {
559 Attributes
::check_doc_attributes(&diagnostic
, &mi
);
560 if let Some(cfg_mi
) = Attributes
::extract_cfg(&mi
) {
561 // Extracted #[doc(cfg(...))]
562 match Cfg
::parse(cfg_mi
) {
563 Ok(new_cfg
) => cfg
&= new_cfg
,
564 Err(e
) => diagnostic
.span_err(e
.span
, e
.msg
),
566 } else if let Some((filename
, contents
)) =
567 Attributes
::extract_include(&mi
)
570 doc_line
+= contents
.lines().count();
571 doc_strings
.push(DocFragment
::Include(
572 line
, attr
.span
, filename
, contents
,
582 // treat #[target_feature(enable = "feat")] attributes as if they were
583 // #[doc(cfg(target_feature = "feat"))] attributes as well
584 for attr
in attrs
.lists(sym
::target_feature
) {
585 if attr
.check_name(sym
::enable
) {
586 if let Some(feat
) = attr
.value_str() {
587 let meta
= attr
::mk_name_value_item_str(
588 Ident
::with_dummy_span(sym
::target_feature
),
592 if let Ok(feat_cfg
) = Cfg
::parse(&meta
) {
599 let inner_docs
= attrs
601 .find(|a
| a
.doc_str().is_some())
602 .map_or(true, |a
| a
.style
== AttrStyle
::Inner
);
607 cfg
: if cfg
== Cfg
::True { None }
else { Some(Arc::new(cfg)) }
,
614 /// Finds the `doc` attribute as a NameValue and returns the corresponding
616 pub fn doc_value(&self) -> Option
<&str> {
617 self.doc_strings
.first().map(|s
| s
.as_str())
620 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
622 pub fn collapsed_doc_value(&self) -> Option
<String
> {
623 if !self.doc_strings
.is_empty() { Some(self.doc_strings.iter().collect()) }
else { None }
626 /// Gets links as a vector
628 /// Cache must be populated before call
629 pub fn links(&self, krate
: &CrateNum
) -> Vec
<(String
, String
)> {
630 use crate::html
::format
::href
;
631 use crate::html
::render
::CURRENT_DEPTH
;
635 .filter_map(|&(ref s
, did
, ref fragment
)| {
638 if let Some((mut href
, ..)) = href(did
) {
639 if let Some(ref fragment
) = *fragment
{
641 href
.push_str(fragment
);
643 Some((s
.clone(), href
))
649 if let Some(ref fragment
) = *fragment
{
651 let url
= match cache
.extern_locations
.get(krate
) {
652 Some(&(_
, _
, ExternalLocation
::Local
)) => {
653 let depth
= CURRENT_DEPTH
.with(|l
| l
.get());
656 Some(&(_
, _
, ExternalLocation
::Remote(ref s
))) => s
.to_string(),
657 Some(&(_
, _
, ExternalLocation
::Unknown
)) | None
=> {
658 String
::from("https://doc.rust-lang.org/nightly")
661 // This is a primitive so the url is done "by hand".
662 let tail
= fragment
.find('
#').unwrap_or_else(|| fragment.len());
666 "{}{}std/primitive.{}.html{}",
668 if !url
.ends_with('
/'
) { "/" }
else { "" }
,
674 panic
!("This isn't a primitive?!");
682 pub fn get_doc_aliases(&self) -> FxHashSet
<String
> {
685 .filter(|a
| a
.check_name(sym
::alias
))
686 .filter_map(|a
| a
.value_str().map(|s
| s
.to_string().replace("\"", "")))
687 .filter(|v
| !v
.is_empty())
688 .collect
::<FxHashSet
<_
>>()
692 impl PartialEq
for Attributes
{
693 fn eq(&self, rhs
: &Self) -> bool
{
694 self.doc_strings
== rhs
.doc_strings
695 && self.cfg
== rhs
.cfg
696 && self.span
== rhs
.span
697 && self.links
== rhs
.links
702 .eq(rhs
.other_attrs
.iter().map(|attr
| attr
.id
))
706 impl Eq
for Attributes {}
708 impl Hash
for Attributes
{
709 fn hash
<H
: Hasher
>(&self, hasher
: &mut H
) {
710 self.doc_strings
.hash(hasher
);
711 self.cfg
.hash(hasher
);
712 self.span
.hash(hasher
);
713 self.links
.hash(hasher
);
714 for attr
in &self.other_attrs
{
715 attr
.id
.hash(hasher
);
720 impl AttributesExt
for Attributes
{
721 fn lists(&self, name
: Symbol
) -> ListAttributesIter
<'_
> {
722 self.other_attrs
.lists(name
)
726 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
727 pub enum GenericBound
{
728 TraitBound(PolyTrait
, hir
::TraitBoundModifier
),
733 pub fn maybe_sized(cx
: &DocContext
<'_
>) -> GenericBound
{
734 let did
= cx
.tcx
.require_lang_item(lang_items
::SizedTraitLangItem
, None
);
735 let empty
= cx
.tcx
.intern_substs(&[]);
736 let path
= external_path(cx
, cx
.tcx
.item_name(did
), Some(did
), false, vec
![], empty
);
737 inline
::record_extern_fqn(cx
, did
, TypeKind
::Trait
);
738 GenericBound
::TraitBound(
740 trait_
: ResolvedPath { path, param_names: None, did, is_generic: false }
,
741 generic_params
: Vec
::new(),
743 hir
::TraitBoundModifier
::Maybe
,
747 pub fn is_sized_bound(&self, cx
: &DocContext
<'_
>) -> bool
{
748 use rustc_hir
::TraitBoundModifier
as TBM
;
749 if let GenericBound
::TraitBound(PolyTrait { ref trait_, .. }
, TBM
::None
) = *self {
750 if trait_
.def_id() == cx
.tcx
.lang_items().sized_trait() {
757 pub fn get_poly_trait(&self) -> Option
<PolyTrait
> {
758 if let GenericBound
::TraitBound(ref p
, _
) = *self {
759 return Some(p
.clone());
764 pub fn get_trait_type(&self) -> Option
<Type
> {
765 if let GenericBound
::TraitBound(PolyTrait { ref trait_, .. }
, _
) = *self {
773 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
774 pub struct Lifetime(pub String
);
777 pub fn get_ref
<'a
>(&'a
self) -> &'a
str {
778 let Lifetime(ref s
) = *self;
783 pub fn statik() -> Lifetime
{
784 Lifetime("'static".to_string())
788 #[derive(Clone, Debug)]
789 pub enum WherePredicate
{
790 BoundPredicate { ty: Type, bounds: Vec<GenericBound> }
,
791 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> }
,
792 EqPredicate { lhs: Type, rhs: Type }
,
795 impl WherePredicate
{
796 pub fn get_bounds(&self) -> Option
<&[GenericBound
]> {
798 WherePredicate
::BoundPredicate { ref bounds, .. }
=> Some(bounds
),
799 WherePredicate
::RegionPredicate { ref bounds, .. }
=> Some(bounds
),
805 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
806 pub enum GenericParamDefKind
{
810 bounds
: Vec
<GenericBound
>,
811 default: Option
<Type
>,
812 synthetic
: Option
<hir
::SyntheticTyParamKind
>,
820 impl GenericParamDefKind
{
821 pub fn is_type(&self) -> bool
{
823 GenericParamDefKind
::Type { .. }
=> true,
828 // FIXME(eddyb) this either returns the default of a type parameter, or the
829 // type of a `const` parameter. It seems that the intention is to *visit*
830 // any embedded types, but `get_type` seems to be the wrong name for that.
831 pub fn get_type(&self) -> Option
<Type
> {
833 GenericParamDefKind
::Type { default, .. }
=> default.clone(),
834 GenericParamDefKind
::Const { ty, .. }
=> Some(ty
.clone()),
835 GenericParamDefKind
::Lifetime
=> None
,
840 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
841 pub struct GenericParamDef
{
843 pub kind
: GenericParamDefKind
,
846 impl GenericParamDef
{
847 pub fn is_synthetic_type_param(&self) -> bool
{
849 GenericParamDefKind
::Lifetime
| GenericParamDefKind
::Const { .. }
=> false,
850 GenericParamDefKind
::Type { ref synthetic, .. }
=> synthetic
.is_some(),
854 pub fn is_type(&self) -> bool
{
858 pub fn get_type(&self) -> Option
<Type
> {
862 pub fn get_bounds(&self) -> Option
<&[GenericBound
]> {
864 GenericParamDefKind
::Type { ref bounds, .. }
=> Some(bounds
),
870 // maybe use a Generic enum and use Vec<Generic>?
871 #[derive(Clone, Debug, Default)]
872 pub struct Generics
{
873 pub params
: Vec
<GenericParamDef
>,
874 pub where_predicates
: Vec
<WherePredicate
>,
877 #[derive(Clone, Debug)]
879 pub generics
: Generics
,
881 pub header
: hir
::FnHeader
,
882 pub defaultness
: Option
<hir
::Defaultness
>,
883 pub all_types
: Vec
<(Type
, TypeKind
)>,
884 pub ret_types
: Vec
<(Type
, TypeKind
)>,
887 #[derive(Clone, Debug)]
888 pub struct TyMethod
{
889 pub header
: hir
::FnHeader
,
891 pub generics
: Generics
,
892 pub all_types
: Vec
<(Type
, TypeKind
)>,
893 pub ret_types
: Vec
<(Type
, TypeKind
)>,
896 #[derive(Clone, Debug)]
897 pub struct Function
{
899 pub generics
: Generics
,
900 pub header
: hir
::FnHeader
,
901 pub all_types
: Vec
<(Type
, TypeKind
)>,
902 pub ret_types
: Vec
<(Type
, TypeKind
)>,
905 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
907 pub inputs
: Arguments
,
909 pub c_variadic
: bool
,
910 pub attrs
: Attributes
,
914 pub fn self_type(&self) -> Option
<SelfTy
> {
915 self.inputs
.values
.get(0).and_then(|v
| v
.to_self())
918 /// Returns the sugared return type for an async function.
920 /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
921 /// will return `i32`.
925 /// This function will panic if the return type does not match the expected sugaring for async
927 pub fn sugared_async_return_type(&self) -> FnRetTy
{
929 FnRetTy
::Return(Type
::ImplTrait(bounds
)) => match &bounds
[0] {
930 GenericBound
::TraitBound(PolyTrait { trait_, .. }
, ..) => {
931 let bindings
= trait_
.bindings().unwrap();
932 FnRetTy
::Return(bindings
[0].ty().clone())
934 _
=> panic
!("unexpected desugaring of async function"),
936 _
=> panic
!("unexpected desugaring of async function"),
941 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
942 pub struct Arguments
{
943 pub values
: Vec
<Argument
>,
946 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
947 pub struct Argument
{
952 #[derive(Clone, PartialEq, Debug)]
955 SelfBorrowed(Option
<Lifetime
>, Mutability
),
960 pub fn to_self(&self) -> Option
<SelfTy
> {
961 if self.name
!= "self" {
964 if self.type_
.is_self_type() {
965 return Some(SelfValue
);
968 BorrowedRef { ref lifetime, mutability, ref type_ }
if type_
.is_self_type() => {
969 Some(SelfBorrowed(lifetime
.clone(), mutability
))
971 _
=> Some(SelfExplicit(self.type_
.clone())),
976 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
982 impl GetDefId
for FnRetTy
{
983 fn def_id(&self) -> Option
<DefId
> {
985 Return(ref ty
) => ty
.def_id(),
986 DefaultReturn
=> None
,
991 #[derive(Clone, Debug)]
994 pub unsafety
: hir
::Unsafety
,
995 pub items
: Vec
<Item
>,
996 pub generics
: Generics
,
997 pub bounds
: Vec
<GenericBound
>,
1001 #[derive(Clone, Debug)]
1002 pub struct TraitAlias
{
1003 pub generics
: Generics
,
1004 pub bounds
: Vec
<GenericBound
>,
1007 /// A trait reference, which may have higher ranked lifetimes.
1008 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1009 pub struct PolyTrait
{
1011 pub generic_params
: Vec
<GenericParamDef
>,
1014 /// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
1015 /// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
1016 /// importantly, it does not preserve mutability or boxes.
1017 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1019 /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
1022 param_names
: Option
<Vec
<GenericBound
>>,
1024 /// `true` if is a `T::Name` path for associated types.
1027 /// For parameterized types, so the consumer of the JSON don't go
1028 /// looking for types which don't exist anywhere.
1030 /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
1031 /// arrays, slices, and tuples.
1032 Primitive(PrimitiveType
),
1033 /// `extern "ABI" fn`
1034 BareFunction(Box
<BareFunctionDecl
>),
1037 Array(Box
<Type
>, String
),
1039 RawPointer(Mutability
, Box
<Type
>),
1041 lifetime
: Option
<Lifetime
>,
1042 mutability
: Mutability
,
1046 // `<Type as Trait>::Name`
1049 self_type
: Box
<Type
>,
1056 // `impl TraitA + TraitB + ...`
1057 ImplTrait(Vec
<GenericBound
>),
1060 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1061 pub enum PrimitiveType
{
1089 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1107 pub trait GetDefId
{
1108 fn def_id(&self) -> Option
<DefId
>;
1111 impl<T
: GetDefId
> GetDefId
for Option
<T
> {
1112 fn def_id(&self) -> Option
<DefId
> {
1113 self.as_ref().and_then(|d
| d
.def_id())
1118 pub fn primitive_type(&self) -> Option
<PrimitiveType
> {
1120 Primitive(p
) | BorrowedRef { type_: box Primitive(p), .. }
=> Some(p
),
1121 Slice(..) | BorrowedRef { type_: box Slice(..), .. }
=> Some(PrimitiveType
::Slice
),
1122 Array(..) | BorrowedRef { type_: box Array(..), .. }
=> Some(PrimitiveType
::Array
),
1125 Some(PrimitiveType
::Unit
)
1127 Some(PrimitiveType
::Tuple
)
1130 RawPointer(..) => Some(PrimitiveType
::RawPointer
),
1131 BorrowedRef { type_: box Generic(..), .. }
=> Some(PrimitiveType
::Reference
),
1132 BareFunction(..) => Some(PrimitiveType
::Fn
),
1133 Never
=> Some(PrimitiveType
::Never
),
1138 pub fn is_generic(&self) -> bool
{
1140 ResolvedPath { is_generic, .. }
=> is_generic
,
1145 pub fn is_self_type(&self) -> bool
{
1147 Generic(ref name
) => name
== "Self",
1152 pub fn generics(&self) -> Option
<Vec
<Type
>> {
1154 ResolvedPath { ref path, .. }
=> path
.segments
.last().and_then(|seg
| {
1155 if let GenericArgs
::AngleBracketed { ref args, .. }
= seg
.args
{
1158 .filter_map(|arg
| match arg
{
1159 GenericArg
::Type(ty
) => Some(ty
.clone()),
1172 pub fn bindings(&self) -> Option
<&[TypeBinding
]> {
1174 ResolvedPath { ref path, .. }
=> path
.segments
.last().and_then(|seg
| {
1175 if let GenericArgs
::AngleBracketed { ref bindings, .. }
= seg
.args
{
1185 pub fn is_full_generic(&self) -> bool
{
1187 Type
::Generic(_
) => true,
1192 pub fn projection(&self) -> Option
<(&Type
, DefId
, &str)> {
1193 let (self_
, trait_
, name
) = match self {
1194 QPath { ref self_type, ref trait_, ref name }
=> (self_type
, trait_
, name
),
1197 let trait_did
= match **trait_
{
1198 ResolvedPath { did, .. }
=> did
,
1201 Some((&self_
, trait_did
, name
))
1205 impl GetDefId
for Type
{
1206 fn def_id(&self) -> Option
<DefId
> {
1208 ResolvedPath { did, .. }
=> Some(did
),
1209 Primitive(p
) => crate::html
::render
::cache().primitive_locations
.get(&p
).cloned(),
1210 BorrowedRef { type_: box Generic(..), .. }
=> {
1211 Primitive(PrimitiveType
::Reference
).def_id()
1213 BorrowedRef { ref type_, .. }
=> type_
.def_id(),
1216 Primitive(PrimitiveType
::Unit
).def_id()
1218 Primitive(PrimitiveType
::Tuple
).def_id()
1221 BareFunction(..) => Primitive(PrimitiveType
::Fn
).def_id(),
1222 Never
=> Primitive(PrimitiveType
::Never
).def_id(),
1223 Slice(..) => Primitive(PrimitiveType
::Slice
).def_id(),
1224 Array(..) => Primitive(PrimitiveType
::Array
).def_id(),
1225 RawPointer(..) => Primitive(PrimitiveType
::RawPointer
).def_id(),
1226 QPath { ref self_type, .. }
=> self_type
.def_id(),
1232 impl PrimitiveType
{
1233 pub fn from_str(s
: &str) -> Option
<PrimitiveType
> {
1235 "isize" => Some(PrimitiveType
::Isize
),
1236 "i8" => Some(PrimitiveType
::I8
),
1237 "i16" => Some(PrimitiveType
::I16
),
1238 "i32" => Some(PrimitiveType
::I32
),
1239 "i64" => Some(PrimitiveType
::I64
),
1240 "i128" => Some(PrimitiveType
::I128
),
1241 "usize" => Some(PrimitiveType
::Usize
),
1242 "u8" => Some(PrimitiveType
::U8
),
1243 "u16" => Some(PrimitiveType
::U16
),
1244 "u32" => Some(PrimitiveType
::U32
),
1245 "u64" => Some(PrimitiveType
::U64
),
1246 "u128" => Some(PrimitiveType
::U128
),
1247 "bool" => Some(PrimitiveType
::Bool
),
1248 "char" => Some(PrimitiveType
::Char
),
1249 "str" => Some(PrimitiveType
::Str
),
1250 "f32" => Some(PrimitiveType
::F32
),
1251 "f64" => Some(PrimitiveType
::F64
),
1252 "array" => Some(PrimitiveType
::Array
),
1253 "slice" => Some(PrimitiveType
::Slice
),
1254 "tuple" => Some(PrimitiveType
::Tuple
),
1255 "unit" => Some(PrimitiveType
::Unit
),
1256 "pointer" => Some(PrimitiveType
::RawPointer
),
1257 "reference" => Some(PrimitiveType
::Reference
),
1258 "fn" => Some(PrimitiveType
::Fn
),
1259 "never" => Some(PrimitiveType
::Never
),
1264 pub fn as_str(&self) -> &'
static str {
1265 use self::PrimitiveType
::*;
1288 RawPointer
=> "pointer",
1289 Reference
=> "reference",
1295 pub fn to_url_str(&self) -> &'
static str {
1300 impl From
<ast
::IntTy
> for PrimitiveType
{
1301 fn from(int_ty
: ast
::IntTy
) -> PrimitiveType
{
1303 ast
::IntTy
::Isize
=> PrimitiveType
::Isize
,
1304 ast
::IntTy
::I8
=> PrimitiveType
::I8
,
1305 ast
::IntTy
::I16
=> PrimitiveType
::I16
,
1306 ast
::IntTy
::I32
=> PrimitiveType
::I32
,
1307 ast
::IntTy
::I64
=> PrimitiveType
::I64
,
1308 ast
::IntTy
::I128
=> PrimitiveType
::I128
,
1313 impl From
<ast
::UintTy
> for PrimitiveType
{
1314 fn from(uint_ty
: ast
::UintTy
) -> PrimitiveType
{
1316 ast
::UintTy
::Usize
=> PrimitiveType
::Usize
,
1317 ast
::UintTy
::U8
=> PrimitiveType
::U8
,
1318 ast
::UintTy
::U16
=> PrimitiveType
::U16
,
1319 ast
::UintTy
::U32
=> PrimitiveType
::U32
,
1320 ast
::UintTy
::U64
=> PrimitiveType
::U64
,
1321 ast
::UintTy
::U128
=> PrimitiveType
::U128
,
1326 impl From
<ast
::FloatTy
> for PrimitiveType
{
1327 fn from(float_ty
: ast
::FloatTy
) -> PrimitiveType
{
1329 ast
::FloatTy
::F32
=> PrimitiveType
::F32
,
1330 ast
::FloatTy
::F64
=> PrimitiveType
::F64
,
1335 impl From
<hir
::PrimTy
> for PrimitiveType
{
1336 fn from(prim_ty
: hir
::PrimTy
) -> PrimitiveType
{
1338 hir
::PrimTy
::Int(int_ty
) => int_ty
.into(),
1339 hir
::PrimTy
::Uint(uint_ty
) => uint_ty
.into(),
1340 hir
::PrimTy
::Float(float_ty
) => float_ty
.into(),
1341 hir
::PrimTy
::Str
=> PrimitiveType
::Str
,
1342 hir
::PrimTy
::Bool
=> PrimitiveType
::Bool
,
1343 hir
::PrimTy
::Char
=> PrimitiveType
::Char
,
1348 #[derive(Clone, PartialEq, Eq, Debug)]
1349 pub enum Visibility
{
1353 Restricted(DefId
, Path
),
1356 #[derive(Clone, Debug)]
1358 pub struct_type
: doctree
::StructType
,
1359 pub generics
: Generics
,
1360 pub fields
: Vec
<Item
>,
1361 pub fields_stripped
: bool
,
1364 #[derive(Clone, Debug)]
1366 pub struct_type
: doctree
::StructType
,
1367 pub generics
: Generics
,
1368 pub fields
: Vec
<Item
>,
1369 pub fields_stripped
: bool
,
1372 /// This is a more limited form of the standard Struct, different in that
1373 /// it lacks the things most items have (name, id, parameterization). Found
1374 /// only as a variant in an enum.
1375 #[derive(Clone, Debug)]
1376 pub struct VariantStruct
{
1377 pub struct_type
: doctree
::StructType
,
1378 pub fields
: Vec
<Item
>,
1379 pub fields_stripped
: bool
,
1382 #[derive(Clone, Debug)]
1384 pub variants
: IndexVec
<VariantIdx
, Item
>,
1385 pub generics
: Generics
,
1386 pub variants_stripped
: bool
,
1389 #[derive(Clone, Debug)]
1390 pub struct Variant
{
1391 pub kind
: VariantKind
,
1394 #[derive(Clone, Debug)]
1395 pub enum VariantKind
{
1398 Struct(VariantStruct
),
1401 #[derive(Clone, Debug)]
1403 pub filename
: FileName
,
1409 pub original
: rustc_span
::Span
,
1413 pub fn empty() -> Span
{
1415 filename
: FileName
::Anon(0),
1421 original
: rustc_span
::DUMMY_SP
,
1425 pub fn span(&self) -> rustc_span
::Span
{
1430 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1434 pub segments
: Vec
<PathSegment
>,
1438 pub fn last_name(&self) -> &str {
1439 self.segments
.last().expect("segments were empty").name
.as_str()
1443 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1444 pub enum GenericArg
{
1450 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1451 pub enum GenericArgs
{
1452 AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> }
,
1453 Parenthesized { inputs: Vec<Type>, output: Option<Type> }
,
1456 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1457 pub struct PathSegment
{
1459 pub args
: GenericArgs
,
1462 #[derive(Clone, Debug)]
1463 pub struct Typedef
{
1465 pub generics
: Generics
,
1466 // Type of target item.
1467 pub item_type
: Option
<Type
>,
1470 impl GetDefId
for Typedef
{
1471 fn def_id(&self) -> Option
<DefId
> {
1476 #[derive(Clone, Debug)]
1477 pub struct OpaqueTy
{
1478 pub bounds
: Vec
<GenericBound
>,
1479 pub generics
: Generics
,
1482 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1483 pub struct BareFunctionDecl
{
1484 pub unsafety
: hir
::Unsafety
,
1485 pub generic_params
: Vec
<GenericParamDef
>,
1490 #[derive(Clone, Debug)]
1493 pub mutability
: Mutability
,
1494 /// It's useful to have the value of a static documented, but I have no
1495 /// desire to represent expressions (that'd basically be all of the AST,
1496 /// which is huge!). So, have a string.
1500 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
1501 pub struct Constant
{
1504 pub value
: Option
<String
>,
1505 pub is_literal
: bool
,
1508 #[derive(Clone, PartialEq, Debug)]
1509 pub enum ImplPolarity
{
1514 #[derive(Clone, Debug)]
1516 pub unsafety
: hir
::Unsafety
,
1517 pub generics
: Generics
,
1518 pub provided_trait_methods
: FxHashSet
<String
>,
1519 pub trait_
: Option
<Type
>,
1521 pub items
: Vec
<Item
>,
1522 pub polarity
: Option
<ImplPolarity
>,
1523 pub synthetic
: bool
,
1524 pub blanket_impl
: Option
<Type
>,
1527 #[derive(Clone, Debug)]
1529 // use source as str;
1530 Simple(String
, ImportSource
),
1535 #[derive(Clone, Debug)]
1536 pub struct ImportSource
{
1538 pub did
: Option
<DefId
>,
1541 #[derive(Clone, Debug)]
1544 pub imported_from
: Option
<String
>,
1547 #[derive(Clone, Debug)]
1548 pub struct ProcMacro
{
1549 pub kind
: MacroKind
,
1550 pub helpers
: Vec
<String
>,
1553 #[derive(Clone, Debug)]
1554 pub struct Stability
{
1555 pub level
: stability
::StabilityLevel
,
1556 pub feature
: Option
<String
>,
1558 pub deprecation
: Option
<Deprecation
>,
1559 pub unstable_reason
: Option
<String
>,
1560 pub issue
: Option
<NonZeroU32
>,
1563 #[derive(Clone, Debug)]
1564 pub struct Deprecation
{
1565 pub since
: Option
<String
>,
1566 pub note
: Option
<String
>,
1569 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
1570 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
1571 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1572 pub struct TypeBinding
{
1574 pub kind
: TypeBindingKind
,
1577 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1578 pub enum TypeBindingKind
{
1579 Equality { ty: Type }
,
1580 Constraint { bounds: Vec<GenericBound> }
,
1584 pub fn ty(&self) -> &Type
{
1586 TypeBindingKind
::Equality { ref ty }
=> ty
,
1587 _
=> panic
!("expected equality type binding for parenthesized generic args"),