1 use std
::cell
::RefCell
;
2 use std
::default::Default
;
4 use std
::path
::PathBuf
;
7 use std
::sync
::OnceLock
as OnceCell
;
8 use std
::{cmp, fmt, iter}
;
10 use arrayvec
::ArrayVec
;
13 use rustc_ast
::util
::comments
::beautify_doc_string
;
14 use rustc_ast
::{self as ast, AttrStyle}
;
15 use rustc_attr
::{ConstStability, Deprecation, Stability, StabilityLevel}
;
16 use rustc_const_eval
::const_eval
::is_unstable_const_fn
;
17 use rustc_data_structures
::fx
::{FxHashMap, FxHashSet}
;
18 use rustc_data_structures
::thin_vec
::ThinVec
;
20 use rustc_hir
::def
::{CtorKind, DefKind, Res}
;
21 use rustc_hir
::def_id
::{CrateNum, DefId, LOCAL_CRATE}
;
22 use rustc_hir
::lang_items
::LangItem
;
23 use rustc_hir
::{BodyId, Mutability}
;
24 use rustc_index
::vec
::IndexVec
;
25 use rustc_middle
::ty
::fast_reject
::SimplifiedType
;
26 use rustc_middle
::ty
::{self, TyCtxt}
;
27 use rustc_session
::Session
;
28 use rustc_span
::hygiene
::MacroKind
;
29 use rustc_span
::source_map
::DUMMY_SP
;
30 use rustc_span
::symbol
::{kw, sym, Ident, Symbol}
;
31 use rustc_span
::{self, FileName, Loc}
;
32 use rustc_target
::abi
::VariantIdx
;
33 use rustc_target
::spec
::abi
::Abi
;
34 use rustc_typeck
::check
::intrinsic
::intrinsic_operation_unsafety
;
36 use crate::clean
::cfg
::Cfg
;
37 use crate::clean
::external_path
;
38 use crate::clean
::inline
::{self, print_inlined_const}
;
39 use crate::clean
::utils
::{is_literal_expr, print_const_expr, print_evaluated_const}
;
40 use crate::clean
::Clean
;
41 use crate::core
::DocContext
;
42 use crate::formats
::cache
::Cache
;
43 use crate::formats
::item_type
::ItemType
;
44 use crate::html
::render
::Context
;
45 use crate::passes
::collect_intra_doc_links
::UrlFragment
;
47 pub(crate) use self::FnRetTy
::*;
48 pub(crate) use self::ItemKind
::*;
49 pub(crate) use self::SelfTy
::*;
50 pub(crate) use self::Type
::{
51 Array
, BareFunction
, BorrowedRef
, DynTrait
, Generic
, ImplTrait
, Infer
, Primitive
, QPath
,
52 RawPointer
, Slice
, Tuple
,
54 pub(crate) use self::Visibility
::{Inherited, Public}
;
59 pub(crate) type ItemIdSet
= FxHashSet
<ItemId
>;
61 #[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
62 pub(crate) enum ItemId
{
63 /// A "normal" item that uses a [`DefId`] for identification.
65 /// Identifier that is used for auto traits.
66 Auto { trait_: DefId, for_: DefId }
,
67 /// Identifier that is used for blanket implementations.
68 Blanket { impl_id: DefId, for_: DefId }
,
69 /// Identifier for primitive types.
70 Primitive(PrimitiveType
, CrateNum
),
75 pub(crate) fn is_local(self) -> bool
{
77 ItemId
::Auto { for_: id, .. }
78 | ItemId
::Blanket { for_: id, .. }
79 | ItemId
::DefId(id
) => id
.is_local(),
80 ItemId
::Primitive(_
, krate
) => krate
== LOCAL_CRATE
,
86 pub(crate) fn expect_def_id(self) -> DefId
{
88 .unwrap_or_else(|| panic
!("ItemId::expect_def_id: `{:?}` isn't a DefId", self))
92 pub(crate) fn as_def_id(self) -> Option
<DefId
> {
94 ItemId
::DefId(id
) => Some(id
),
100 pub(crate) fn krate(self) -> CrateNum
{
102 ItemId
::Auto { for_: id, .. }
103 | ItemId
::Blanket { for_: id, .. }
104 | ItemId
::DefId(id
) => id
.krate
,
105 ItemId
::Primitive(_
, krate
) => krate
,
110 impl From
<DefId
> for ItemId
{
111 fn from(id
: DefId
) -> Self {
116 /// The crate currently being documented.
117 #[derive(Clone, Debug)]
118 pub(crate) struct Crate
{
119 pub(crate) module
: Item
,
120 pub(crate) primitives
: ThinVec
<(DefId
, PrimitiveType
)>,
121 /// Only here so that they can be filtered through the rustdoc passes.
122 pub(crate) external_traits
: Rc
<RefCell
<FxHashMap
<DefId
, TraitWithExtraInfo
>>>,
125 // `Crate` is frequently moved by-value. Make sure it doesn't unintentionally get bigger.
126 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
127 rustc_data_structures
::static_assert_size
!(Crate
, 72);
130 pub(crate) fn name(&self, tcx
: TyCtxt
<'_
>) -> Symbol
{
131 ExternalCrate
::LOCAL
.name(tcx
)
134 pub(crate) fn src(&self, tcx
: TyCtxt
<'_
>) -> FileName
{
135 ExternalCrate
::LOCAL
.src(tcx
)
139 /// This struct is used to wrap additional information added by rustdoc on a `trait` item.
140 #[derive(Clone, Debug)]
141 pub(crate) struct TraitWithExtraInfo
{
142 pub(crate) trait_
: Trait
,
143 pub(crate) is_notable
: bool
,
146 #[derive(Copy, Clone, Debug)]
147 pub(crate) struct ExternalCrate
{
148 pub(crate) crate_num
: CrateNum
,
152 const LOCAL
: Self = Self { crate_num: LOCAL_CRATE }
;
155 pub(crate) fn def_id(&self) -> DefId
{
156 self.crate_num
.as_def_id()
159 pub(crate) fn src(&self, tcx
: TyCtxt
<'_
>) -> FileName
{
160 let krate_span
= tcx
.def_span(self.def_id());
161 tcx
.sess
.source_map().span_to_filename(krate_span
)
164 pub(crate) fn name(&self, tcx
: TyCtxt
<'_
>) -> Symbol
{
165 tcx
.crate_name(self.crate_num
)
168 pub(crate) fn src_root(&self, tcx
: TyCtxt
<'_
>) -> PathBuf
{
169 match self.src(tcx
) {
170 FileName
::Real(ref p
) => match p
.local_path_if_available().parent() {
171 Some(p
) => p
.to_path_buf(),
172 None
=> PathBuf
::new(),
178 /// Attempts to find where an external crate is located, given that we're
179 /// rendering in to the specified source destination.
180 pub(crate) fn location(
182 extern_url
: Option
<&str>,
183 extern_url_takes_precedence
: bool
,
184 dst
: &std
::path
::Path
,
186 ) -> ExternalLocation
{
187 use ExternalLocation
::*;
189 fn to_remote(url
: impl ToString
) -> ExternalLocation
{
190 let mut url
= url
.to_string();
191 if !url
.ends_with('
/'
) {
197 // See if there's documentation generated into the local directory
198 // WARNING: since rustdoc creates these directories as it generates documentation, this check is only accurate before rendering starts.
199 // Make sure to call `location()` by that time.
200 let local_location
= dst
.join(self.name(tcx
).as_str());
201 if local_location
.is_dir() {
205 if extern_url_takes_precedence
{
206 if let Some(url
) = extern_url
{
207 return to_remote(url
);
211 // Failing that, see if there's an attribute specifying where to find this
213 let did
= self.crate_num
.as_def_id();
214 tcx
.get_attrs(did
, sym
::doc
)
215 .flat_map(|attr
| attr
.meta_item_list().unwrap_or_default())
216 .filter(|a
| a
.has_name(sym
::html_root_url
))
217 .filter_map(|a
| a
.value_str())
220 .or_else(|| extern_url
.map(to_remote
)) // NOTE: only matters if `extern_url_takes_precedence` is false
221 .unwrap_or(Unknown
) // Well, at least we tried.
224 pub(crate) fn keywords(&self, tcx
: TyCtxt
<'_
>) -> ThinVec
<(DefId
, Symbol
)> {
225 let root
= self.def_id();
227 let as_keyword
= |res
: Res
<!>| {
228 if let Res
::Def(DefKind
::Mod
, def_id
) = res
{
229 let mut keyword
= None
;
231 .get_attrs(def_id
, sym
::doc
)
232 .flat_map(|attr
| attr
.meta_item_list().unwrap_or_default());
233 for meta
in meta_items
{
234 if meta
.has_name(sym
::keyword
) {
235 if let Some(v
) = meta
.value_str() {
241 return keyword
.map(|p
| (def_id
, p
));
251 let item
= tcx
.hir().item(id
);
253 hir
::ItemKind
::Mod(_
) => {
254 as_keyword(Res
::Def(DefKind
::Mod
, id
.def_id
.to_def_id()))
256 hir
::ItemKind
::Use(path
, hir
::UseKind
::Single
)
257 if tcx
.visibility(id
.def_id
).is_public() =>
259 as_keyword(path
.res
.expect_non_local())
260 .map(|(_
, prim
)| (id
.def_id
.to_def_id(), prim
))
267 tcx
.module_children(root
).iter().map(|item
| item
.res
).filter_map(as_keyword
).collect()
271 pub(crate) fn primitives(&self, tcx
: TyCtxt
<'_
>) -> ThinVec
<(DefId
, PrimitiveType
)> {
272 let root
= self.def_id();
274 // Collect all inner modules which are tagged as implementations of
277 // Note that this loop only searches the top-level items of the crate,
278 // and this is intentional. If we were to search the entire crate for an
279 // item tagged with `#[doc(primitive)]` then we would also have to
280 // search the entirety of external modules for items tagged
281 // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
282 // all that metadata unconditionally).
284 // In order to keep the metadata load under control, the
285 // `#[doc(primitive)]` feature is explicitly designed to only allow the
286 // primitive tags to show up as the top level items in a crate.
288 // Also note that this does not attempt to deal with modules tagged
289 // duplicately for the same primitive. This is handled later on when
290 // rendering by delegating everything to a hash map.
291 let as_primitive
= |res
: Res
<!>| {
292 if let Res
::Def(DefKind
::Mod
, def_id
) = res
{
295 .get_attrs(def_id
, sym
::doc
)
296 .flat_map(|attr
| attr
.meta_item_list().unwrap_or_default());
297 for meta
in meta_items
{
298 if let Some(v
) = meta
.value_str() {
299 if meta
.has_name(sym
::primitive
) {
300 prim
= PrimitiveType
::from_symbol(v
);
304 // FIXME: should warn on unknown primitives?
308 return prim
.map(|p
| (def_id
, p
));
319 let item
= tcx
.hir().item(id
);
321 hir
::ItemKind
::Mod(_
) => {
322 as_primitive(Res
::Def(DefKind
::Mod
, id
.def_id
.to_def_id()))
324 hir
::ItemKind
::Use(path
, hir
::UseKind
::Single
)
325 if tcx
.visibility(id
.def_id
).is_public() =>
327 as_primitive(path
.res
.expect_non_local()).map(|(_
, prim
)| {
328 // Pretend the primitive is local.
329 (id
.def_id
.to_def_id(), prim
)
337 tcx
.module_children(root
).iter().map(|item
| item
.res
).filter_map(as_primitive
).collect()
342 /// Indicates where an external crate can be found.
344 pub(crate) enum ExternalLocation
{
345 /// Remote URL root of the external crate
347 /// This external crate can be found in the local doc/ folder
349 /// The external crate could not be found.
353 /// Anything with a source location and set of attributes and, optionally, a
354 /// name. That is, anything that can be documented. This doesn't correspond
355 /// directly to the AST's concept of an item; it's a strict superset.
357 pub(crate) struct Item
{
358 /// The name of this item.
359 /// Optional because not every item has a name, e.g. impls.
360 pub(crate) name
: Option
<Symbol
>,
361 pub(crate) attrs
: Box
<Attributes
>,
362 pub(crate) visibility
: Visibility
,
363 /// Information about this item that is specific to what kind of item it is.
364 /// E.g., struct vs enum vs function.
365 pub(crate) kind
: Box
<ItemKind
>,
366 pub(crate) item_id
: ItemId
,
368 pub(crate) cfg
: Option
<Arc
<Cfg
>>,
371 /// NOTE: this does NOT unconditionally print every item, to avoid thousands of lines of logs.
372 /// If you want to see the debug output for attributes and the `kind` as well, use `{:#?}` instead of `{:?}`.
373 impl fmt
::Debug
for Item
{
374 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
375 let alternate
= f
.alternate();
376 // hand-picked fields that don't bloat the logs too much
377 let mut fmt
= f
.debug_struct("Item");
378 fmt
.field("name", &self.name
)
379 .field("visibility", &self.visibility
)
380 .field("item_id", &self.item_id
);
381 // allow printing the full item if someone really wants to
383 fmt
.field("attrs", &self.attrs
).field("kind", &self.kind
).field("cfg", &self.cfg
);
385 fmt
.field("kind", &self.type_());
386 fmt
.field("docs", &self.doc_value());
392 // `Item` is used a lot. Make sure it doesn't unintentionally get bigger.
393 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
394 rustc_data_structures
::static_assert_size
!(Item
, 56);
396 pub(crate) fn rustc_span(def_id
: DefId
, tcx
: TyCtxt
<'_
>) -> Span
{
397 Span
::new(def_id
.as_local().map_or_else(
398 || tcx
.def_span(def_id
),
401 hir
.span_with_body(hir
.local_def_id_to_hir_id(local
))
407 pub(crate) fn stability
<'tcx
>(&self, tcx
: TyCtxt
<'tcx
>) -> Option
<Stability
> {
408 self.item_id
.as_def_id().and_then(|did
| tcx
.lookup_stability(did
))
411 pub(crate) fn const_stability
<'tcx
>(&self, tcx
: TyCtxt
<'tcx
>) -> Option
<ConstStability
> {
412 self.item_id
.as_def_id().and_then(|did
| tcx
.lookup_const_stability(did
))
415 pub(crate) fn deprecation(&self, tcx
: TyCtxt
<'_
>) -> Option
<Deprecation
> {
416 self.item_id
.as_def_id().and_then(|did
| tcx
.lookup_deprecation(did
))
419 pub(crate) fn inner_docs(&self, tcx
: TyCtxt
<'_
>) -> bool
{
422 .map(|did
| tcx
.get_attrs_unchecked(did
).inner_docs())
426 pub(crate) fn span(&self, tcx
: TyCtxt
<'_
>) -> Span
{
427 let kind
= match &*self.kind
{
428 ItemKind
::StrippedItem(k
) => k
,
432 ItemKind
::ModuleItem(Module { span, .. }
) => *span
,
433 ItemKind
::ImplItem(Impl { kind: ImplKind::Auto, .. }
) => Span
::dummy(),
434 ItemKind
::ImplItem(Impl { kind: ImplKind::Blanket(_), .. }
) => {
435 if let ItemId
::Blanket { impl_id, .. }
= self.item_id
{
436 rustc_span(impl_id
, tcx
)
438 panic
!("blanket impl item has non-blanket ID")
442 self.item_id
.as_def_id().map(|did
| rustc_span(did
, tcx
)).unwrap_or_else(Span
::dummy
)
447 pub(crate) fn attr_span(&self, tcx
: TyCtxt
<'_
>) -> rustc_span
::Span
{
448 crate::passes
::span_of_attrs(&self.attrs
).unwrap_or_else(|| self.span(tcx
).inner())
451 /// Finds the `doc` attribute as a NameValue and returns the corresponding
453 pub(crate) fn doc_value(&self) -> Option
<String
> {
454 self.attrs
.doc_value()
457 /// Convenience wrapper around [`Self::from_def_id_and_parts`] which converts
458 /// `hir_id` to a [`DefId`]
459 pub(crate) fn from_hir_id_and_parts(
461 name
: Option
<Symbol
>,
463 cx
: &mut DocContext
<'_
>,
465 Item
::from_def_id_and_parts(cx
.tcx
.hir().local_def_id(hir_id
).to_def_id(), name
, kind
, cx
)
468 pub(crate) fn from_def_id_and_parts(
470 name
: Option
<Symbol
>,
472 cx
: &mut DocContext
<'_
>,
474 let ast_attrs
= cx
.tcx
.get_attrs_unchecked(def_id
);
476 Self::from_def_id_and_attrs_and_parts(
480 box ast_attrs
.clean(cx
),
482 ast_attrs
.cfg(cx
.tcx
, &cx
.cache
.hidden_cfg
),
486 pub(crate) fn from_def_id_and_attrs_and_parts(
488 name
: Option
<Symbol
>,
490 attrs
: Box
<Attributes
>,
491 cx
: &mut DocContext
<'_
>,
492 cfg
: Option
<Arc
<Cfg
>>,
494 trace
!("name={:?}, def_id={:?}", name
, def_id
);
496 // Primitives and Keywords are written in the source code as private modules.
497 // The modules need to be private so that nobody actually uses them, but the
498 // keywords and primitives that they are documenting are public.
499 let visibility
= if matches
!(&kind
, ItemKind
::KeywordItem(..) | ItemKind
::PrimitiveItem(..))
503 cx
.tcx
.visibility(def_id
).clean(cx
)
506 Item { item_id: def_id.into(), kind: box kind, name, attrs, visibility, cfg }
509 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
511 pub(crate) fn collapsed_doc_value(&self) -> Option
<String
> {
512 self.attrs
.collapsed_doc_value()
515 pub(crate) fn links(&self, cx
: &Context
<'_
>) -> Vec
<RenderedLink
> {
516 use crate::html
::format
::href
;
521 .map_or(&[][..], |v
| v
.as_slice())
523 .filter_map(|ItemLink { link: s, link_text, did, ref fragment }
| {
525 if let Ok((mut href
, ..)) = href(*did
, cx
) {
527 if let Some(ref fragment
) = *fragment
{
528 fragment
.render(&mut href
, cx
.tcx())
531 original_text
: s
.clone(),
532 new_text
: link_text
.clone(),
542 /// Find a list of all link names, without finding their href.
544 /// This is used for generating summary text, which does not include
545 /// the link text, but does need to know which `[]`-bracketed names
546 /// are actually links.
547 pub(crate) fn link_names(&self, cache
: &Cache
) -> Vec
<RenderedLink
> {
551 .map_or(&[][..], |v
| v
.as_slice())
553 .map(|ItemLink { link: s, link_text, .. }
| RenderedLink
{
554 original_text
: s
.clone(),
555 new_text
: link_text
.clone(),
561 pub(crate) fn is_crate(&self) -> bool
{
562 self.is_mod() && self.item_id
.as_def_id().map_or(false, |did
| did
.is_crate_root())
564 pub(crate) fn is_mod(&self) -> bool
{
565 self.type_() == ItemType
::Module
567 pub(crate) fn is_trait(&self) -> bool
{
568 self.type_() == ItemType
::Trait
570 pub(crate) fn is_struct(&self) -> bool
{
571 self.type_() == ItemType
::Struct
573 pub(crate) fn is_enum(&self) -> bool
{
574 self.type_() == ItemType
::Enum
576 pub(crate) fn is_variant(&self) -> bool
{
577 self.type_() == ItemType
::Variant
579 pub(crate) fn is_associated_type(&self) -> bool
{
580 matches
!(&*self.kind
, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..)))
582 pub(crate) fn is_ty_associated_type(&self) -> bool
{
583 matches
!(&*self.kind
, TyAssocTypeItem(..) | StrippedItem(box TyAssocTypeItem(..)))
585 pub(crate) fn is_associated_const(&self) -> bool
{
586 matches
!(&*self.kind
, AssocConstItem(..) | StrippedItem(box AssocConstItem(..)))
588 pub(crate) fn is_ty_associated_const(&self) -> bool
{
589 matches
!(&*self.kind
, TyAssocConstItem(..) | StrippedItem(box TyAssocConstItem(..)))
591 pub(crate) fn is_method(&self) -> bool
{
592 self.type_() == ItemType
::Method
594 pub(crate) fn is_ty_method(&self) -> bool
{
595 self.type_() == ItemType
::TyMethod
597 pub(crate) fn is_typedef(&self) -> bool
{
598 self.type_() == ItemType
::Typedef
600 pub(crate) fn is_primitive(&self) -> bool
{
601 self.type_() == ItemType
::Primitive
603 pub(crate) fn is_union(&self) -> bool
{
604 self.type_() == ItemType
::Union
606 pub(crate) fn is_import(&self) -> bool
{
607 self.type_() == ItemType
::Import
609 pub(crate) fn is_extern_crate(&self) -> bool
{
610 self.type_() == ItemType
::ExternCrate
612 pub(crate) fn is_keyword(&self) -> bool
{
613 self.type_() == ItemType
::Keyword
615 pub(crate) fn is_stripped(&self) -> bool
{
617 StrippedItem(..) => true,
618 ImportItem(ref i
) => !i
.should_be_displayed
,
622 pub(crate) fn has_stripped_entries(&self) -> Option
<bool
> {
624 StructItem(ref struct_
) => Some(struct_
.has_stripped_entries()),
625 UnionItem(ref union_
) => Some(union_
.has_stripped_entries()),
626 EnumItem(ref enum_
) => Some(enum_
.has_stripped_entries()),
627 VariantItem(ref v
) => v
.has_stripped_entries(),
632 pub(crate) fn stability_class(&self, tcx
: TyCtxt
<'_
>) -> Option
<String
> {
633 self.stability(tcx
).as_ref().and_then(|s
| {
634 let mut classes
= Vec
::with_capacity(2);
637 classes
.push("unstable");
640 // FIXME: what about non-staged API items that are deprecated?
641 if self.deprecation(tcx
).is_some() {
642 classes
.push("deprecated");
645 if !classes
.is_empty() { Some(classes.join(" ")) }
else { None }
649 pub(crate) fn stable_since(&self, tcx
: TyCtxt
<'_
>) -> Option
<Symbol
> {
650 match self.stability(tcx
)?
.level
{
651 StabilityLevel
::Stable { since, .. }
=> Some(since
),
652 StabilityLevel
::Unstable { .. }
=> None
,
656 pub(crate) fn const_stable_since(&self, tcx
: TyCtxt
<'_
>) -> Option
<Symbol
> {
657 match self.const_stability(tcx
)?
.level
{
658 StabilityLevel
::Stable { since, .. }
=> Some(since
),
659 StabilityLevel
::Unstable { .. }
=> None
,
663 pub(crate) fn is_non_exhaustive(&self) -> bool
{
664 self.attrs
.other_attrs
.iter().any(|a
| a
.has_name(sym
::non_exhaustive
))
667 /// Returns a documentation-level item type from the item.
668 pub(crate) fn type_(&self) -> ItemType
{
672 pub(crate) fn is_default(&self) -> bool
{
674 ItemKind
::MethodItem(_
, Some(defaultness
)) => {
675 defaultness
.has_value() && !defaultness
.is_final()
681 /// Returns a `FnHeader` if `self` is a function item, otherwise returns `None`.
682 pub(crate) fn fn_header(&self, tcx
: TyCtxt
<'_
>) -> Option
<hir
::FnHeader
> {
686 asyncness
: hir
::IsAsync
,
688 let sig
= tcx
.fn_sig(def_id
);
690 if tcx
.is_const_fn(def_id
) && is_unstable_const_fn(tcx
, def_id
).is_none() {
691 hir
::Constness
::Const
693 hir
::Constness
::NotConst
695 hir
::FnHeader { unsafety: sig.unsafety(), abi: sig.abi(), constness, asyncness }
697 let header
= match *self.kind
{
698 ItemKind
::ForeignFunctionItem(_
) => {
699 let abi
= tcx
.fn_sig(self.item_id
.as_def_id().unwrap()).abi();
701 unsafety
: if abi
== Abi
::RustIntrinsic
{
702 intrinsic_operation_unsafety(self.name
.unwrap())
704 hir
::Unsafety
::Unsafe
707 constness
: hir
::Constness
::NotConst
,
708 asyncness
: hir
::IsAsync
::NotAsync
,
711 ItemKind
::FunctionItem(_
) | ItemKind
::MethodItem(_
, _
) => {
712 let def_id
= self.item_id
.as_def_id().unwrap();
713 build_fn_header(def_id
, tcx
, tcx
.asyncness(def_id
))
715 ItemKind
::TyMethodItem(_
) => {
716 build_fn_header(self.item_id
.as_def_id().unwrap(), tcx
, hir
::IsAsync
::NotAsync
)
724 #[derive(Clone, Debug)]
725 pub(crate) enum ItemKind
{
727 /// The crate's name, *not* the name it's imported as.
734 FunctionItem(Function
),
736 TypedefItem(Typedef
),
737 OpaqueTyItem(OpaqueTy
),
739 ConstantItem(Constant
),
741 TraitAliasItem(TraitAlias
),
743 /// A required method in a trait declaration meaning it's only a function signature.
744 TyMethodItem(Function
),
745 /// A method in a trait impl or a provided method in a trait declaration.
747 /// Compared to [TyMethodItem], it also contains a method body.
748 MethodItem(Function
, Option
<hir
::Defaultness
>),
749 StructFieldItem(Type
),
750 VariantItem(Variant
),
751 /// `fn`s from an extern block
752 ForeignFunctionItem(Function
),
753 /// `static`s from an extern block
754 ForeignStaticItem(Static
),
755 /// `type`s from an extern block
758 ProcMacroItem(ProcMacro
),
759 PrimitiveItem(PrimitiveType
),
760 /// A required associated constant in a trait declaration.
761 TyAssocConstItem(Type
),
762 /// An associated associated constant in a trait impl or a provided one in a trait declaration.
763 AssocConstItem(Type
, ConstantKind
),
764 /// A required associated type in a trait declaration.
766 /// The bounds may be non-empty if there is a `where` clause.
767 TyAssocTypeItem(Box
<Generics
>, Vec
<GenericBound
>),
768 /// An associated type in a trait impl or a provided one in a trait declaration.
769 AssocTypeItem(Typedef
, Vec
<GenericBound
>),
770 /// An item that has been stripped by a rustdoc pass
771 StrippedItem(Box
<ItemKind
>),
776 /// Some items contain others such as structs (for their fields) and Enums
777 /// (for their variants). This method returns those contained items.
778 pub(crate) fn inner_items(&self) -> impl Iterator
<Item
= &Item
> {
780 StructItem(s
) => s
.fields
.iter(),
781 UnionItem(u
) => u
.fields
.iter(),
782 VariantItem(Variant
::Struct(v
)) => v
.fields
.iter(),
783 VariantItem(Variant
::Tuple(v
)) => v
.iter(),
784 EnumItem(e
) => e
.variants
.iter(),
785 TraitItem(t
) => t
.items
.iter(),
786 ImplItem(i
) => i
.items
.iter(),
787 ModuleItem(m
) => m
.items
.iter(),
788 ExternCrateItem { .. }
800 | ForeignFunctionItem(_
)
801 | ForeignStaticItem(_
)
806 | TyAssocConstItem(_
)
807 | AssocConstItem(_
, _
)
808 | TyAssocTypeItem(..)
811 | KeywordItem(_
) => [].iter(),
816 #[derive(Clone, Debug)]
817 pub(crate) struct Module
{
818 pub(crate) items
: Vec
<Item
>,
819 pub(crate) span
: Span
,
822 pub(crate) trait AttributesExt
{
823 type AttributeIterator
<'a
>: Iterator
<Item
= ast
::NestedMetaItem
>
827 fn lists
<'a
>(&'a
self, name
: Symbol
) -> Self::AttributeIterator
<'a
>;
829 fn span(&self) -> Option
<rustc_span
::Span
>;
831 fn inner_docs(&self) -> bool
;
833 fn other_attrs(&self) -> Vec
<ast
::Attribute
>;
835 fn cfg(&self, tcx
: TyCtxt
<'_
>, hidden_cfg
: &FxHashSet
<Cfg
>) -> Option
<Arc
<Cfg
>>;
838 impl AttributesExt
for [ast
::Attribute
] {
839 type AttributeIterator
<'a
> = impl Iterator
<Item
= ast
::NestedMetaItem
> + 'a
;
841 fn lists
<'a
>(&'a
self, name
: Symbol
) -> Self::AttributeIterator
<'a
> {
843 .filter(move |attr
| attr
.has_name(name
))
844 .filter_map(ast
::Attribute
::meta_item_list
)
848 /// Return the span of the first doc-comment, if it exists.
849 fn span(&self) -> Option
<rustc_span
::Span
> {
850 self.iter().find(|attr
| attr
.doc_str().is_some()).map(|attr
| attr
.span
)
853 /// Returns whether the first doc-comment is an inner attribute.
855 //// If there are no doc-comments, return true.
856 /// FIXME(#78591): Support both inner and outer attributes on the same item.
857 fn inner_docs(&self) -> bool
{
858 self.iter().find(|a
| a
.doc_str().is_some()).map_or(true, |a
| a
.style
== AttrStyle
::Inner
)
861 fn other_attrs(&self) -> Vec
<ast
::Attribute
> {
862 self.iter().filter(|attr
| attr
.doc_str().is_none()).cloned().collect()
865 fn cfg(&self, tcx
: TyCtxt
<'_
>, hidden_cfg
: &FxHashSet
<Cfg
>) -> Option
<Arc
<Cfg
>> {
867 let doc_cfg_active
= tcx
.features().doc_cfg
;
868 let doc_auto_cfg_active
= tcx
.features().doc_auto_cfg
;
870 fn single
<T
: IntoIterator
>(it
: T
) -> Option
<T
::Item
> {
871 let mut iter
= it
.into_iter();
872 let item
= iter
.next()?
;
873 if iter
.next().is_some() {
879 let mut cfg
= if doc_cfg_active
|| doc_auto_cfg_active
{
880 let mut doc_cfg
= self
882 .filter(|attr
| attr
.has_name(sym
::doc
))
883 .flat_map(|attr
| attr
.meta_item_list().unwrap_or_default())
884 .filter(|attr
| attr
.has_name(sym
::cfg
))
886 if doc_cfg
.peek().is_some() && doc_cfg_active
{
888 .filter_map(|attr
| Cfg
::parse(attr
.meta_item()?
).ok())
889 .fold(Cfg
::True
, |cfg
, new_cfg
| cfg
& new_cfg
)
890 } else if doc_auto_cfg_active
{
892 .filter(|attr
| attr
.has_name(sym
::cfg
))
893 .filter_map(|attr
| single(attr
.meta_item_list()?
))
895 Cfg
::parse_without(attr
.meta_item()?
, hidden_cfg
).ok().flatten()
897 .fold(Cfg
::True
, |cfg
, new_cfg
| cfg
& new_cfg
)
905 for attr
in self.iter() {
907 if attr
.doc_str().is_none() && attr
.has_name(sym
::doc
) {
909 if let Some(list
) = attr
.meta().as_ref().and_then(|mi
| mi
.meta_item_list()) {
912 if !item
.has_name(sym
::cfg
) {
916 if let Some(cfg_mi
) = item
918 .and_then(|item
| rustc_expand
::config
::parse_cfg(item
, sess
))
920 match Cfg
::parse(cfg_mi
) {
921 Ok(new_cfg
) => cfg
&= new_cfg
,
923 sess
.span_err(e
.span
, e
.msg
);
932 // treat #[target_feature(enable = "feat")] attributes as if they were
933 // #[doc(cfg(target_feature = "feat"))] attributes as well
934 for attr
in self.lists(sym
::target_feature
) {
935 if attr
.has_name(sym
::enable
) {
936 if let Some(feat
) = attr
.value_str() {
937 let meta
= attr
::mk_name_value_item_str(
938 Ident
::with_dummy_span(sym
::target_feature
),
942 if let Ok(feat_cfg
) = Cfg
::parse(&meta
) {
949 if cfg
== Cfg
::True { None }
else { Some(Arc::new(cfg)) }
953 pub(crate) trait NestedAttributesExt
{
954 /// Returns `true` if the attribute list contains a specific `word`
955 fn has_word(self, word
: Symbol
) -> bool
957 Self: std
::marker
::Sized
,
959 <Self as NestedAttributesExt
>::get_word_attr(self, word
).is_some()
962 /// Returns `Some(attr)` if the attribute list contains 'attr'
963 /// corresponding to a specific `word`
964 fn get_word_attr(self, word
: Symbol
) -> Option
<ast
::NestedMetaItem
>;
967 impl<I
: Iterator
<Item
= ast
::NestedMetaItem
>> NestedAttributesExt
for I
{
968 fn get_word_attr(mut self, word
: Symbol
) -> Option
<ast
::NestedMetaItem
> {
969 self.find(|attr
| attr
.is_word() && attr
.has_name(word
))
973 /// A portion of documentation, extracted from a `#[doc]` attribute.
975 /// Each variant contains the line number within the complete doc-comment where the fragment
976 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
978 /// Included files are kept separate from inline doc comments so that proper line-number
979 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
980 /// kept separate because of issue #42760.
981 #[derive(Clone, PartialEq, Eq, Debug)]
982 pub(crate) struct DocFragment
{
983 pub(crate) span
: rustc_span
::Span
,
984 /// The module this doc-comment came from.
986 /// This allows distinguishing between the original documentation and a pub re-export.
987 /// If it is `None`, the item was not re-exported.
988 pub(crate) parent_module
: Option
<DefId
>,
989 pub(crate) doc
: Symbol
,
990 pub(crate) kind
: DocFragmentKind
,
991 pub(crate) indent
: usize,
994 // `DocFragment` is used a lot. Make sure it doesn't unintentionally get bigger.
995 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
996 rustc_data_structures
::static_assert_size
!(DocFragment
, 32);
998 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
999 pub(crate) enum DocFragmentKind
{
1000 /// A doc fragment created from a `///` or `//!` doc comment.
1002 /// A doc fragment created from a "raw" `#[doc=""]` attribute.
1006 /// The goal of this function is to apply the `DocFragment` transformation that is required when
1007 /// transforming into the final Markdown, which is applying the computed indent to each line in
1008 /// each doc fragment (a `DocFragment` can contain multiple lines in case of `#[doc = ""]`).
1010 /// Note: remove the trailing newline where appropriate
1011 fn add_doc_fragment(out
: &mut String
, frag
: &DocFragment
) {
1012 let s
= frag
.doc
.as_str();
1013 let mut iter
= s
.lines();
1018 while let Some(line
) = iter
.next() {
1019 if line
.chars().any(|c
| !c
.is_whitespace()) {
1020 assert
!(line
.len() >= frag
.indent
);
1021 out
.push_str(&line
[frag
.indent
..]);
1029 /// Collapse a collection of [`DocFragment`]s into one string,
1030 /// handling indentation and newlines as needed.
1031 pub(crate) fn collapse_doc_fragments(doc_strings
: &[DocFragment
]) -> String
{
1032 let mut acc
= String
::new();
1033 for frag
in doc_strings
{
1034 add_doc_fragment(&mut acc
, frag
);
1040 /// Removes excess indentation on comments in order for the Markdown
1041 /// to be parsed correctly. This is necessary because the convention for
1042 /// writing documentation is to provide a space between the /// or //! marker
1043 /// and the doc text, but Markdown is whitespace-sensitive. For example,
1044 /// a block of text with four-space indentation is parsed as a code block,
1045 /// so if we didn't unindent comments, these list items
1052 /// would be parsed as if they were in a code block, which is likely not what the user intended.
1053 fn unindent_doc_fragments(docs
: &mut Vec
<DocFragment
>) {
1054 // `add` is used in case the most common sugared doc syntax is used ("/// "). The other
1055 // fragments kind's lines are never starting with a whitespace unless they are using some
1056 // markdown formatting requiring it. Therefore, if the doc block have a mix between the two,
1057 // we need to take into account the fact that the minimum indent minus one (to take this
1058 // whitespace into account).
1063 // #[doc = "another"]
1065 // In this case, you want "hello! another" and not "hello! another".
1066 let add
= if docs
.windows(2).any(|arr
| arr
[0].kind
!= arr
[1].kind
)
1067 && docs
.iter().any(|d
| d
.kind
== DocFragmentKind
::SugaredDoc
)
1069 // In case we have a mix of sugared doc comments and "raw" ones, we want the sugared one to
1070 // "decide" how much the minimum indent will be.
1076 // `min_indent` is used to know how much whitespaces from the start of each lines must be
1077 // removed. Example:
1080 // #[doc = "another"]
1082 // In here, the `min_indent` is 1 (because non-sugared fragment are always counted with minimum
1083 // 1 whitespace), meaning that "hello!" will be considered a codeblock because it starts with 4
1084 // (5 - 1) whitespaces.
1085 let Some(min_indent
) = docs
1088 fragment
.doc
.as_str().lines().fold(usize::MAX
, |min_indent
, line
| {
1089 if line
.chars().all(|c
| c
.is_whitespace()) {
1092 // Compare against either space or tab, ignoring whether they are
1094 let whitespace
= line
.chars().take_while(|c
| *c
== ' '
|| *c
== '
\t'
).count();
1095 cmp
::min(min_indent
, whitespace
)
1096 + if fragment
.kind
== DocFragmentKind
::SugaredDoc { 0 }
else { add }
1105 for fragment
in docs
{
1106 if fragment
.doc
== kw
::Empty
{
1110 let min_indent
= if fragment
.kind
!= DocFragmentKind
::SugaredDoc
&& min_indent
> 0 {
1116 fragment
.indent
= min_indent
;
1120 /// A link that has not yet been rendered.
1122 /// This link will be turned into a rendered link by [`Item::links`].
1123 #[derive(Clone, Debug, PartialEq, Eq)]
1124 pub(crate) struct ItemLink
{
1125 /// The original link written in the markdown
1126 pub(crate) link
: String
,
1127 /// The link text displayed in the HTML.
1129 /// This may not be the same as `link` if there was a disambiguator
1130 /// in an intra-doc link (e.g. \[`fn@f`\])
1131 pub(crate) link_text
: String
,
1132 pub(crate) did
: DefId
,
1133 /// The url fragment to append to the link
1134 pub(crate) fragment
: Option
<UrlFragment
>,
1137 pub struct RenderedLink
{
1138 /// The text the link was original written as.
1140 /// This could potentially include disambiguators and backticks.
1141 pub(crate) original_text
: String
,
1142 /// The text to display in the HTML
1143 pub(crate) new_text
: String
,
1144 /// The URL to put in the `href`
1145 pub(crate) href
: String
,
1148 /// The attributes on an [`Item`], including attributes like `#[derive(...)]` and `#[inline]`,
1149 /// as well as doc comments.
1150 #[derive(Clone, Debug, Default)]
1151 pub(crate) struct Attributes
{
1152 pub(crate) doc_strings
: Vec
<DocFragment
>,
1153 pub(crate) other_attrs
: Vec
<ast
::Attribute
>,
1157 pub(crate) fn lists(&self, name
: Symbol
) -> impl Iterator
<Item
= ast
::NestedMetaItem
> + '_
{
1158 self.other_attrs
.lists(name
)
1161 pub(crate) fn has_doc_flag(&self, flag
: Symbol
) -> bool
{
1162 for attr
in &self.other_attrs
{
1163 if !attr
.has_name(sym
::doc
) {
1167 if let Some(items
) = attr
.meta_item_list() {
1168 if items
.iter().filter_map(|i
| i
.meta_item()).any(|it
| it
.has_name(flag
)) {
1177 pub(crate) fn from_ast(
1178 attrs
: &[ast
::Attribute
],
1179 additional_attrs
: Option
<(&[ast
::Attribute
], DefId
)>,
1181 // Additional documentation should be shown before the original documentation.
1182 let attrs1
= additional_attrs
1184 .flat_map(|(attrs
, def_id
)| attrs
.iter().map(move |attr
| (attr
, Some(def_id
))));
1185 let attrs2
= attrs
.iter().map(|attr
| (attr
, None
));
1186 Attributes
::from_ast_iter(attrs1
.chain(attrs2
), false)
1189 pub(crate) fn from_ast_iter
<'a
>(
1190 attrs
: impl Iterator
<Item
= (&'a ast
::Attribute
, Option
<DefId
>)>,
1193 let mut doc_strings
= Vec
::new();
1194 let mut other_attrs
= Vec
::new();
1195 for (attr
, parent_module
) in attrs
{
1196 if let Some((doc_str
, comment_kind
)) = attr
.doc_str_and_comment_kind() {
1197 trace
!("got doc_str={doc_str:?}");
1198 let doc
= beautify_doc_string(doc_str
, comment_kind
);
1199 let kind
= if attr
.is_doc_comment() {
1200 DocFragmentKind
::SugaredDoc
1202 DocFragmentKind
::RawDoc
1204 let fragment
= DocFragment { span: attr.span, doc, kind, parent_module, indent: 0 }
;
1205 doc_strings
.push(fragment
);
1206 } else if !doc_only
{
1207 other_attrs
.push(attr
.clone());
1211 unindent_doc_fragments(&mut doc_strings
);
1213 Attributes { doc_strings, other_attrs }
1216 /// Finds the `doc` attribute as a NameValue and returns the corresponding
1218 pub(crate) fn doc_value(&self) -> Option
<String
> {
1219 let mut iter
= self.doc_strings
.iter();
1221 let ori
= iter
.next()?
;
1222 let mut out
= String
::new();
1223 add_doc_fragment(&mut out
, ori
);
1224 for new_frag
in iter
{
1225 add_doc_fragment(&mut out
, new_frag
);
1228 if out
.is_empty() { None }
else { Some(out) }
1231 /// Return the doc-comments on this item, grouped by the module they came from.
1232 /// The module can be different if this is a re-export with added documentation.
1234 /// The last newline is not trimmed so the produced strings are reusable between
1235 /// early and late doc link resolution regardless of their position.
1236 pub(crate) fn prepare_to_doc_link_resolution(&self) -> FxHashMap
<Option
<DefId
>, String
> {
1237 let mut res
= FxHashMap
::default();
1238 for fragment
in &self.doc_strings
{
1239 let out_str
= res
.entry(fragment
.parent_module
).or_default();
1240 add_doc_fragment(out_str
, fragment
);
1245 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
1247 pub(crate) fn collapsed_doc_value(&self) -> Option
<String
> {
1248 if self.doc_strings
.is_empty() {
1251 Some(collapse_doc_fragments(&self.doc_strings
))
1255 pub(crate) fn get_doc_aliases(&self) -> Box
<[Symbol
]> {
1256 let mut aliases
= FxHashSet
::default();
1258 for attr
in self.other_attrs
.lists(sym
::doc
).filter(|a
| a
.has_name(sym
::alias
)) {
1259 if let Some(values
) = attr
.meta_item_list() {
1261 match l
.literal().unwrap().kind
{
1262 ast
::LitKind
::Str(s
, _
) => {
1265 _
=> unreachable
!(),
1269 aliases
.insert(attr
.value_str().unwrap());
1272 aliases
.into_iter().collect
::<Vec
<_
>>().into()
1276 impl PartialEq
for Attributes
{
1277 fn eq(&self, rhs
: &Self) -> bool
{
1278 self.doc_strings
== rhs
.doc_strings
1282 .map(|attr
| attr
.id
)
1283 .eq(rhs
.other_attrs
.iter().map(|attr
| attr
.id
))
1287 impl Eq
for Attributes {}
1289 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1290 pub(crate) enum GenericBound
{
1291 TraitBound(PolyTrait
, hir
::TraitBoundModifier
),
1296 pub(crate) fn maybe_sized(cx
: &mut DocContext
<'_
>) -> GenericBound
{
1297 let did
= cx
.tcx
.require_lang_item(LangItem
::Sized
, None
);
1298 let empty
= cx
.tcx
.intern_substs(&[]);
1299 let path
= external_path(cx
, did
, false, vec
![], empty
);
1300 inline
::record_extern_fqn(cx
, did
, ItemType
::Trait
);
1301 GenericBound
::TraitBound(
1302 PolyTrait { trait_: path, generic_params: Vec::new() }
,
1303 hir
::TraitBoundModifier
::Maybe
,
1307 pub(crate) fn is_sized_bound(&self, cx
: &DocContext
<'_
>) -> bool
{
1308 use rustc_hir
::TraitBoundModifier
as TBM
;
1309 if let GenericBound
::TraitBound(PolyTrait { ref trait_, .. }
, TBM
::None
) = *self {
1310 if Some(trait_
.def_id()) == cx
.tcx
.lang_items().sized_trait() {
1317 pub(crate) fn get_poly_trait(&self) -> Option
<PolyTrait
> {
1318 if let GenericBound
::TraitBound(ref p
, _
) = *self {
1319 return Some(p
.clone());
1324 pub(crate) fn get_trait_path(&self) -> Option
<Path
> {
1325 if let GenericBound
::TraitBound(PolyTrait { ref trait_, .. }
, _
) = *self {
1326 Some(trait_
.clone())
1333 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1334 pub(crate) struct Lifetime(pub Symbol
);
1337 pub(crate) fn statik() -> Lifetime
{
1338 Lifetime(kw
::StaticLifetime
)
1341 pub(crate) fn elided() -> Lifetime
{
1342 Lifetime(kw
::UnderscoreLifetime
)
1346 #[derive(Clone, Debug)]
1347 pub(crate) enum WherePredicate
{
1348 BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<Lifetime> }
,
1349 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> }
,
1350 EqPredicate { lhs: Type, rhs: Term }
,
1353 impl WherePredicate
{
1354 pub(crate) fn get_bounds(&self) -> Option
<&[GenericBound
]> {
1356 WherePredicate
::BoundPredicate { ref bounds, .. }
=> Some(bounds
),
1357 WherePredicate
::RegionPredicate { ref bounds, .. }
=> Some(bounds
),
1363 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1364 pub(crate) enum GenericParamDefKind
{
1365 Lifetime { outlives: Vec<Lifetime> }
,
1366 Type { did: DefId, bounds: Vec<GenericBound>, default: Option<Box<Type>>, synthetic: bool }
,
1367 Const { did: DefId, ty: Box<Type>, default: Option<Box<String>> }
,
1370 impl GenericParamDefKind
{
1371 pub(crate) fn is_type(&self) -> bool
{
1372 matches
!(self, GenericParamDefKind
::Type { .. }
)
1376 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1377 pub(crate) struct GenericParamDef
{
1378 pub(crate) name
: Symbol
,
1379 pub(crate) kind
: GenericParamDefKind
,
1382 // `GenericParamDef` is used in many places. Make sure it doesn't unintentionally get bigger.
1383 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
1384 rustc_data_structures
::static_assert_size
!(GenericParamDef
, 56);
1386 impl GenericParamDef
{
1387 pub(crate) fn is_synthetic_type_param(&self) -> bool
{
1389 GenericParamDefKind
::Lifetime { .. }
| GenericParamDefKind
::Const { .. }
=> false,
1390 GenericParamDefKind
::Type { synthetic, .. }
=> synthetic
,
1394 pub(crate) fn is_type(&self) -> bool
{
1398 pub(crate) fn get_bounds(&self) -> Option
<&[GenericBound
]> {
1400 GenericParamDefKind
::Type { ref bounds, .. }
=> Some(bounds
),
1406 // maybe use a Generic enum and use Vec<Generic>?
1407 #[derive(Clone, Debug, Default)]
1408 pub(crate) struct Generics
{
1409 pub(crate) params
: Vec
<GenericParamDef
>,
1410 pub(crate) where_predicates
: Vec
<WherePredicate
>,
1414 pub(crate) fn is_empty(&self) -> bool
{
1415 self.params
.is_empty() && self.where_predicates
.is_empty()
1419 #[derive(Clone, Debug)]
1420 pub(crate) struct Function
{
1421 pub(crate) decl
: FnDecl
,
1422 pub(crate) generics
: Generics
,
1425 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1426 pub(crate) struct FnDecl
{
1427 pub(crate) inputs
: Arguments
,
1428 pub(crate) output
: FnRetTy
,
1429 pub(crate) c_variadic
: bool
,
1433 pub(crate) fn self_type(&self) -> Option
<SelfTy
> {
1434 self.inputs
.values
.get(0).and_then(|v
| v
.to_self())
1437 /// Returns the sugared return type for an async function.
1439 /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
1440 /// will return `i32`.
1444 /// This function will panic if the return type does not match the expected sugaring for async
1446 pub(crate) fn sugared_async_return_type(&self) -> FnRetTy
{
1447 match &self.output
{
1448 FnRetTy
::Return(Type
::ImplTrait(bounds
)) => match &bounds
[0] {
1449 GenericBound
::TraitBound(PolyTrait { trait_, .. }
, ..) => {
1450 let bindings
= trait_
.bindings().unwrap();
1451 let ret_ty
= bindings
[0].term();
1452 let ty
= ret_ty
.ty().expect("Unexpected constant return term");
1453 FnRetTy
::Return(ty
.clone())
1455 _
=> panic
!("unexpected desugaring of async function"),
1457 _
=> panic
!("unexpected desugaring of async function"),
1462 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1463 pub(crate) struct Arguments
{
1464 pub(crate) values
: Vec
<Argument
>,
1467 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1468 pub(crate) struct Argument
{
1469 pub(crate) type_
: Type
,
1470 pub(crate) name
: Symbol
,
1471 /// This field is used to represent "const" arguments from the `rustc_legacy_const_generics`
1472 /// feature. More information in <https://github.com/rust-lang/rust/issues/83167>.
1473 pub(crate) is_const
: bool
,
1476 #[derive(Clone, PartialEq, Debug)]
1477 pub(crate) enum SelfTy
{
1479 SelfBorrowed(Option
<Lifetime
>, Mutability
),
1484 pub(crate) fn to_self(&self) -> Option
<SelfTy
> {
1485 if self.name
!= kw
::SelfLower
{
1488 if self.type_
.is_self_type() {
1489 return Some(SelfValue
);
1492 BorrowedRef { ref lifetime, mutability, ref type_ }
if type_
.is_self_type() => {
1493 Some(SelfBorrowed(lifetime
.clone(), mutability
))
1495 _
=> Some(SelfExplicit(self.type_
.clone())),
1500 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1501 pub(crate) enum FnRetTy
{
1507 pub(crate) fn as_return(&self) -> Option
<&Type
> {
1509 Return(ret
) => Some(ret
),
1510 DefaultReturn
=> None
,
1515 #[derive(Clone, Debug)]
1516 pub(crate) struct Trait
{
1517 pub(crate) unsafety
: hir
::Unsafety
,
1518 pub(crate) items
: Vec
<Item
>,
1519 pub(crate) generics
: Generics
,
1520 pub(crate) bounds
: Vec
<GenericBound
>,
1521 pub(crate) is_auto
: bool
,
1524 #[derive(Clone, Debug)]
1525 pub(crate) struct TraitAlias
{
1526 pub(crate) generics
: Generics
,
1527 pub(crate) bounds
: Vec
<GenericBound
>,
1530 /// A trait reference, which may have higher ranked lifetimes.
1531 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1532 pub(crate) struct PolyTrait
{
1533 pub(crate) trait_
: Path
,
1534 pub(crate) generic_params
: Vec
<GenericParamDef
>,
1537 /// Rustdoc's representation of types, mostly based on the [`hir::Ty`].
1538 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1539 pub(crate) enum Type
{
1540 /// A named type, which could be a trait.
1542 /// This is mostly Rustdoc's version of [`hir::Path`].
1543 /// It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics.
1544 Path { path: Path }
,
1545 /// A `dyn Trait` object: `dyn for<'a> Trait<'a> + Send + 'static`
1546 DynTrait(Vec
<PolyTrait
>, Option
<Lifetime
>),
1547 /// A type parameter.
1549 /// A primitive (aka, builtin) type.
1550 Primitive(PrimitiveType
),
1551 /// A function pointer: `extern "ABI" fn(...) -> ...`
1552 BareFunction(Box
<BareFunctionDecl
>),
1553 /// A tuple type: `(i32, &str)`.
1555 /// A slice type (does *not* include the `&`): `[i32]`
1559 /// The `String` field is a stringified version of the array's length parameter.
1560 Array(Box
<Type
>, String
),
1561 /// A raw pointer type: `*const i32`, `*mut i32`
1562 RawPointer(Mutability
, Box
<Type
>),
1563 /// A reference type: `&i32`, `&'a mut Foo`
1564 BorrowedRef { lifetime: Option<Lifetime>, mutability: Mutability, type_: Box<Type> }
,
1566 /// A qualified path to an associated item: `<Type as Trait>::Name`
1568 assoc
: Box
<PathSegment
>,
1569 self_type
: Box
<Type
>,
1570 /// FIXME: compute this field on demand.
1571 should_show_cast
: bool
,
1575 /// A type that is inferred: `_`
1578 /// An `impl Trait`: `impl TraitA + TraitB + ...`
1579 ImplTrait(Vec
<GenericBound
>),
1582 // `Type` is used a lot. Make sure it doesn't unintentionally get bigger.
1583 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
1584 rustc_data_structures
::static_assert_size
!(Type
, 72);
1587 /// When comparing types for equality, it can help to ignore `&` wrapping.
1588 pub(crate) fn without_borrowed_ref(&self) -> &Type
{
1589 let mut result
= self;
1590 while let Type
::BorrowedRef { type_, .. }
= result
{
1596 /// Check if two types are "potentially the same".
1597 /// This is different from `Eq`, because it knows that things like
1598 /// `Placeholder` are possible matches for everything.
1599 pub(crate) fn is_same(&self, other
: &Self, cache
: &Cache
) -> bool
{
1600 match (self, other
) {
1602 (Type
::Tuple(a
), Type
::Tuple(b
)) => {
1603 a
.len() == b
.len() && a
.iter().zip(b
).all(|(a
, b
)| a
.is_same(b
, cache
))
1605 (Type
::Slice(a
), Type
::Slice(b
)) => a
.is_same(b
, cache
),
1606 (Type
::Array(a
, al
), Type
::Array(b
, bl
)) => al
== bl
&& a
.is_same(b
, cache
),
1607 (Type
::RawPointer(mutability
, type_
), Type
::RawPointer(b_mutability
, b_type_
)) => {
1608 mutability
== b_mutability
&& type_
.is_same(b_type_
, cache
)
1611 Type
::BorrowedRef { mutability, type_, .. }
,
1612 Type
::BorrowedRef { mutability: b_mutability, type_: b_type_, .. }
,
1613 ) => mutability
== b_mutability
&& type_
.is_same(b_type_
, cache
),
1614 // Placeholders and generics are equal to all other types.
1615 (Type
::Infer
, _
) | (_
, Type
::Infer
) => true,
1616 (Type
::Generic(_
), _
) | (_
, Type
::Generic(_
)) => true,
1617 // Other cases, such as primitives, just use recursion.
1620 .and_then(|a
| Some((a
, b
.def_id(cache
)?
)))
1621 .map(|(a
, b
)| a
== b
)
1626 pub(crate) fn primitive_type(&self) -> Option
<PrimitiveType
> {
1628 Primitive(p
) | BorrowedRef { type_: box Primitive(p), .. }
=> Some(p
),
1629 Slice(..) | BorrowedRef { type_: box Slice(..), .. }
=> Some(PrimitiveType
::Slice
),
1630 Array(..) | BorrowedRef { type_: box Array(..), .. }
=> Some(PrimitiveType
::Array
),
1633 Some(PrimitiveType
::Unit
)
1635 Some(PrimitiveType
::Tuple
)
1638 RawPointer(..) => Some(PrimitiveType
::RawPointer
),
1639 BareFunction(..) => Some(PrimitiveType
::Fn
),
1644 /// Checks if this is a `T::Name` path for an associated type.
1645 pub(crate) fn is_assoc_ty(&self) -> bool
{
1647 Type
::Path { path, .. }
=> path
.is_assoc_ty(),
1652 pub(crate) fn is_self_type(&self) -> bool
{
1654 Generic(name
) => name
== kw
::SelfUpper
,
1659 pub(crate) fn generics(&self) -> Option
<Vec
<&Type
>> {
1661 Type
::Path { path, .. }
=> path
.generics(),
1666 pub(crate) fn is_full_generic(&self) -> bool
{
1667 matches
!(self, Type
::Generic(_
))
1670 pub(crate) fn is_impl_trait(&self) -> bool
{
1671 matches
!(self, Type
::ImplTrait(_
))
1674 pub(crate) fn is_primitive(&self) -> bool
{
1675 self.primitive_type().is_some()
1678 pub(crate) fn projection(&self) -> Option
<(&Type
, DefId
, PathSegment
)> {
1679 if let QPath { self_type, trait_, assoc, .. }
= self {
1680 Some((self_type
, trait_
.def_id(), *assoc
.clone()))
1686 fn inner_def_id(&self, cache
: Option
<&Cache
>) -> Option
<DefId
> {
1687 let t
: PrimitiveType
= match *self {
1688 Type
::Path { ref path }
=> return Some(path
.def_id()),
1689 DynTrait(ref bounds
, _
) => return Some(bounds
[0].trait_
.def_id()),
1690 Primitive(p
) => return cache
.and_then(|c
| c
.primitive_locations
.get(&p
).cloned()),
1691 BorrowedRef { type_: box Generic(..), .. }
=> PrimitiveType
::Reference
,
1692 BorrowedRef { ref type_, .. }
=> return type_
.inner_def_id(cache
),
1697 PrimitiveType
::Tuple
1700 BareFunction(..) => PrimitiveType
::Fn
,
1701 Slice(..) => PrimitiveType
::Slice
,
1702 Array(..) => PrimitiveType
::Array
,
1703 RawPointer(..) => PrimitiveType
::RawPointer
,
1704 QPath { ref self_type, .. }
=> return self_type
.inner_def_id(cache
),
1705 Generic(_
) | Infer
| ImplTrait(_
) => return None
,
1707 cache
.and_then(|c
| Primitive(t
).def_id(c
))
1710 /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s.
1712 /// [clean]: crate::clean
1713 pub(crate) fn def_id(&self, cache
: &Cache
) -> Option
<DefId
> {
1714 self.inner_def_id(Some(cache
))
1718 /// A primitive (aka, builtin) type.
1720 /// This represents things like `i32`, `str`, etc.
1722 /// N.B. This has to be different from [`hir::PrimTy`] because it also includes types that aren't
1723 /// paths, like [`Self::Unit`].
1724 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1725 pub(crate) enum PrimitiveType
{
1753 type SimplifiedTypes
= FxHashMap
<PrimitiveType
, ArrayVec
<SimplifiedType
, 3>>;
1754 impl PrimitiveType
{
1755 pub(crate) fn from_hir(prim
: hir
::PrimTy
) -> PrimitiveType
{
1756 use ast
::{FloatTy, IntTy, UintTy}
;
1758 hir
::PrimTy
::Int(IntTy
::Isize
) => PrimitiveType
::Isize
,
1759 hir
::PrimTy
::Int(IntTy
::I8
) => PrimitiveType
::I8
,
1760 hir
::PrimTy
::Int(IntTy
::I16
) => PrimitiveType
::I16
,
1761 hir
::PrimTy
::Int(IntTy
::I32
) => PrimitiveType
::I32
,
1762 hir
::PrimTy
::Int(IntTy
::I64
) => PrimitiveType
::I64
,
1763 hir
::PrimTy
::Int(IntTy
::I128
) => PrimitiveType
::I128
,
1764 hir
::PrimTy
::Uint(UintTy
::Usize
) => PrimitiveType
::Usize
,
1765 hir
::PrimTy
::Uint(UintTy
::U8
) => PrimitiveType
::U8
,
1766 hir
::PrimTy
::Uint(UintTy
::U16
) => PrimitiveType
::U16
,
1767 hir
::PrimTy
::Uint(UintTy
::U32
) => PrimitiveType
::U32
,
1768 hir
::PrimTy
::Uint(UintTy
::U64
) => PrimitiveType
::U64
,
1769 hir
::PrimTy
::Uint(UintTy
::U128
) => PrimitiveType
::U128
,
1770 hir
::PrimTy
::Float(FloatTy
::F32
) => PrimitiveType
::F32
,
1771 hir
::PrimTy
::Float(FloatTy
::F64
) => PrimitiveType
::F64
,
1772 hir
::PrimTy
::Str
=> PrimitiveType
::Str
,
1773 hir
::PrimTy
::Bool
=> PrimitiveType
::Bool
,
1774 hir
::PrimTy
::Char
=> PrimitiveType
::Char
,
1778 pub(crate) fn from_symbol(s
: Symbol
) -> Option
<PrimitiveType
> {
1780 sym
::isize => Some(PrimitiveType
::Isize
),
1781 sym
::i8 => Some(PrimitiveType
::I8
),
1782 sym
::i16 => Some(PrimitiveType
::I16
),
1783 sym
::i32 => Some(PrimitiveType
::I32
),
1784 sym
::i64 => Some(PrimitiveType
::I64
),
1785 sym
::i128
=> Some(PrimitiveType
::I128
),
1786 sym
::usize => Some(PrimitiveType
::Usize
),
1787 sym
::u8 => Some(PrimitiveType
::U8
),
1788 sym
::u16 => Some(PrimitiveType
::U16
),
1789 sym
::u32 => Some(PrimitiveType
::U32
),
1790 sym
::u64 => Some(PrimitiveType
::U64
),
1791 sym
::u128
=> Some(PrimitiveType
::U128
),
1792 sym
::bool
=> Some(PrimitiveType
::Bool
),
1793 sym
::char => Some(PrimitiveType
::Char
),
1794 sym
::str => Some(PrimitiveType
::Str
),
1795 sym
::f32 => Some(PrimitiveType
::F32
),
1796 sym
::f64 => Some(PrimitiveType
::F64
),
1797 sym
::array
=> Some(PrimitiveType
::Array
),
1798 sym
::slice
=> Some(PrimitiveType
::Slice
),
1799 sym
::tuple
=> Some(PrimitiveType
::Tuple
),
1800 sym
::unit
=> Some(PrimitiveType
::Unit
),
1801 sym
::pointer
=> Some(PrimitiveType
::RawPointer
),
1802 sym
::reference
=> Some(PrimitiveType
::Reference
),
1803 kw
::Fn
=> Some(PrimitiveType
::Fn
),
1804 sym
::never
=> Some(PrimitiveType
::Never
),
1809 pub(crate) fn simplified_types() -> &'
static SimplifiedTypes
{
1810 use ty
::fast_reject
::SimplifiedTypeGen
::*;
1811 use ty
::{FloatTy, IntTy, UintTy}
;
1812 use PrimitiveType
::*;
1813 static CELL
: OnceCell
<SimplifiedTypes
> = OnceCell
::new();
1815 let single
= |x
| iter
::once(x
).collect();
1816 CELL
.get_or_init(move || {
1818 Isize
=> single(IntSimplifiedType(IntTy
::Isize
)),
1819 I8
=> single(IntSimplifiedType(IntTy
::I8
)),
1820 I16
=> single(IntSimplifiedType(IntTy
::I16
)),
1821 I32
=> single(IntSimplifiedType(IntTy
::I32
)),
1822 I64
=> single(IntSimplifiedType(IntTy
::I64
)),
1823 I128
=> single(IntSimplifiedType(IntTy
::I128
)),
1824 Usize
=> single(UintSimplifiedType(UintTy
::Usize
)),
1825 U8
=> single(UintSimplifiedType(UintTy
::U8
)),
1826 U16
=> single(UintSimplifiedType(UintTy
::U16
)),
1827 U32
=> single(UintSimplifiedType(UintTy
::U32
)),
1828 U64
=> single(UintSimplifiedType(UintTy
::U64
)),
1829 U128
=> single(UintSimplifiedType(UintTy
::U128
)),
1830 F32
=> single(FloatSimplifiedType(FloatTy
::F32
)),
1831 F64
=> single(FloatSimplifiedType(FloatTy
::F64
)),
1832 Str
=> single(StrSimplifiedType
),
1833 Bool
=> single(BoolSimplifiedType
),
1834 Char
=> single(CharSimplifiedType
),
1835 Array
=> single(ArraySimplifiedType
),
1836 Slice
=> single(SliceSimplifiedType
),
1837 // FIXME: If we ever add an inherent impl for tuples
1838 // with different lengths, they won't show in rustdoc.
1840 // Either manually update this arrayvec at this point
1841 // or start with a more complex refactoring.
1842 Tuple
=> [TupleSimplifiedType(1), TupleSimplifiedType(2), TupleSimplifiedType(3)].into(),
1843 Unit
=> single(TupleSimplifiedType(0)),
1844 RawPointer
=> [PtrSimplifiedType(Mutability
::Not
), PtrSimplifiedType(Mutability
::Mut
)].into_iter().collect(),
1845 Reference
=> [RefSimplifiedType(Mutability
::Not
), RefSimplifiedType(Mutability
::Mut
)].into_iter().collect(),
1846 // FIXME: This will be wrong if we ever add inherent impls
1847 // for function pointers.
1848 Fn
=> ArrayVec
::new(),
1849 Never
=> single(NeverSimplifiedType
),
1854 pub(crate) fn impls
<'tcx
>(&self, tcx
: TyCtxt
<'tcx
>) -> impl Iterator
<Item
= DefId
> + 'tcx
{
1855 Self::simplified_types()
1859 .flat_map(move |&simp
| tcx
.incoherent_impls(simp
))
1863 pub(crate) fn all_impls(tcx
: TyCtxt
<'_
>) -> impl Iterator
<Item
= DefId
> + '_
{
1864 Self::simplified_types()
1867 .flat_map(move |&simp
| tcx
.incoherent_impls(simp
))
1871 pub(crate) fn as_sym(&self) -> Symbol
{
1872 use PrimitiveType
::*;
1874 Isize
=> sym
::isize,
1880 Usize
=> sym
::usize,
1891 Array
=> sym
::array
,
1892 Slice
=> sym
::slice
,
1893 Tuple
=> sym
::tuple
,
1895 RawPointer
=> sym
::pointer
,
1896 Reference
=> sym
::reference
,
1898 Never
=> sym
::never
,
1902 /// Returns the DefId of the module with `doc(primitive)` for this primitive type.
1903 /// Panics if there is no such module.
1905 /// This gives precedence to primitives defined in the current crate, and deprioritizes primitives defined in `core`,
1906 /// but otherwise, if multiple crates define the same primitive, there is no guarantee of which will be picked.
1907 /// In particular, if a crate depends on both `std` and another crate that also defines `doc(primitive)`, then
1908 /// it's entirely random whether `std` or the other crate is picked. (no_std crates are usually fine unless multiple dependencies define a primitive.)
1909 pub(crate) fn primitive_locations(tcx
: TyCtxt
<'_
>) -> &FxHashMap
<PrimitiveType
, DefId
> {
1910 static PRIMITIVE_LOCATIONS
: OnceCell
<FxHashMap
<PrimitiveType
, DefId
>> = OnceCell
::new();
1911 PRIMITIVE_LOCATIONS
.get_or_init(|| {
1912 let mut primitive_locations
= FxHashMap
::default();
1913 // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate.
1914 // This is a degenerate case that I don't plan to support.
1915 for &crate_num
in tcx
.crates(()) {
1916 let e
= ExternalCrate { crate_num }
;
1917 let crate_name
= e
.name(tcx
);
1918 debug
!(?crate_num
, ?crate_name
);
1919 for &(def_id
, prim
) in &e
.primitives(tcx
) {
1920 // HACK: try to link to std instead where possible
1921 if crate_name
== sym
::core
&& primitive_locations
.contains_key(&prim
) {
1924 primitive_locations
.insert(prim
, def_id
);
1927 let local_primitives
= ExternalCrate { crate_num: LOCAL_CRATE }
.primitives(tcx
);
1928 for (def_id
, prim
) in local_primitives
{
1929 primitive_locations
.insert(prim
, def_id
);
1936 impl From
<ast
::IntTy
> for PrimitiveType
{
1937 fn from(int_ty
: ast
::IntTy
) -> PrimitiveType
{
1939 ast
::IntTy
::Isize
=> PrimitiveType
::Isize
,
1940 ast
::IntTy
::I8
=> PrimitiveType
::I8
,
1941 ast
::IntTy
::I16
=> PrimitiveType
::I16
,
1942 ast
::IntTy
::I32
=> PrimitiveType
::I32
,
1943 ast
::IntTy
::I64
=> PrimitiveType
::I64
,
1944 ast
::IntTy
::I128
=> PrimitiveType
::I128
,
1949 impl From
<ast
::UintTy
> for PrimitiveType
{
1950 fn from(uint_ty
: ast
::UintTy
) -> PrimitiveType
{
1952 ast
::UintTy
::Usize
=> PrimitiveType
::Usize
,
1953 ast
::UintTy
::U8
=> PrimitiveType
::U8
,
1954 ast
::UintTy
::U16
=> PrimitiveType
::U16
,
1955 ast
::UintTy
::U32
=> PrimitiveType
::U32
,
1956 ast
::UintTy
::U64
=> PrimitiveType
::U64
,
1957 ast
::UintTy
::U128
=> PrimitiveType
::U128
,
1962 impl From
<ast
::FloatTy
> for PrimitiveType
{
1963 fn from(float_ty
: ast
::FloatTy
) -> PrimitiveType
{
1965 ast
::FloatTy
::F32
=> PrimitiveType
::F32
,
1966 ast
::FloatTy
::F64
=> PrimitiveType
::F64
,
1971 impl From
<ty
::IntTy
> for PrimitiveType
{
1972 fn from(int_ty
: ty
::IntTy
) -> PrimitiveType
{
1974 ty
::IntTy
::Isize
=> PrimitiveType
::Isize
,
1975 ty
::IntTy
::I8
=> PrimitiveType
::I8
,
1976 ty
::IntTy
::I16
=> PrimitiveType
::I16
,
1977 ty
::IntTy
::I32
=> PrimitiveType
::I32
,
1978 ty
::IntTy
::I64
=> PrimitiveType
::I64
,
1979 ty
::IntTy
::I128
=> PrimitiveType
::I128
,
1984 impl From
<ty
::UintTy
> for PrimitiveType
{
1985 fn from(uint_ty
: ty
::UintTy
) -> PrimitiveType
{
1987 ty
::UintTy
::Usize
=> PrimitiveType
::Usize
,
1988 ty
::UintTy
::U8
=> PrimitiveType
::U8
,
1989 ty
::UintTy
::U16
=> PrimitiveType
::U16
,
1990 ty
::UintTy
::U32
=> PrimitiveType
::U32
,
1991 ty
::UintTy
::U64
=> PrimitiveType
::U64
,
1992 ty
::UintTy
::U128
=> PrimitiveType
::U128
,
1997 impl From
<ty
::FloatTy
> for PrimitiveType
{
1998 fn from(float_ty
: ty
::FloatTy
) -> PrimitiveType
{
2000 ty
::FloatTy
::F32
=> PrimitiveType
::F32
,
2001 ty
::FloatTy
::F64
=> PrimitiveType
::F64
,
2006 impl From
<hir
::PrimTy
> for PrimitiveType
{
2007 fn from(prim_ty
: hir
::PrimTy
) -> PrimitiveType
{
2009 hir
::PrimTy
::Int(int_ty
) => int_ty
.into(),
2010 hir
::PrimTy
::Uint(uint_ty
) => uint_ty
.into(),
2011 hir
::PrimTy
::Float(float_ty
) => float_ty
.into(),
2012 hir
::PrimTy
::Str
=> PrimitiveType
::Str
,
2013 hir
::PrimTy
::Bool
=> PrimitiveType
::Bool
,
2014 hir
::PrimTy
::Char
=> PrimitiveType
::Char
,
2019 #[derive(Copy, Clone, Debug)]
2020 pub(crate) enum Visibility
{
2023 /// Visibility inherited from parent.
2025 /// For example, this is the visibility of private items and of enum variants.
2027 /// `pub(crate)`, `pub(super)`, or `pub(in path::to::somewhere)`
2032 pub(crate) fn is_public(&self) -> bool
{
2033 matches
!(self, Visibility
::Public
)
2037 #[derive(Clone, Debug)]
2038 pub(crate) struct Struct
{
2039 pub(crate) struct_type
: CtorKind
,
2040 pub(crate) generics
: Generics
,
2041 pub(crate) fields
: Vec
<Item
>,
2045 pub(crate) fn has_stripped_entries(&self) -> bool
{
2046 self.fields
.iter().any(|f
| f
.is_stripped())
2050 #[derive(Clone, Debug)]
2051 pub(crate) struct Union
{
2052 pub(crate) generics
: Generics
,
2053 pub(crate) fields
: Vec
<Item
>,
2057 pub(crate) fn has_stripped_entries(&self) -> bool
{
2058 self.fields
.iter().any(|f
| f
.is_stripped())
2062 /// This is a more limited form of the standard Struct, different in that
2063 /// it lacks the things most items have (name, id, parameterization). Found
2064 /// only as a variant in an enum.
2065 #[derive(Clone, Debug)]
2066 pub(crate) struct VariantStruct
{
2067 pub(crate) struct_type
: CtorKind
,
2068 pub(crate) fields
: Vec
<Item
>,
2071 impl VariantStruct
{
2072 pub(crate) fn has_stripped_entries(&self) -> bool
{
2073 self.fields
.iter().any(|f
| f
.is_stripped())
2077 #[derive(Clone, Debug)]
2078 pub(crate) struct Enum
{
2079 pub(crate) variants
: IndexVec
<VariantIdx
, Item
>,
2080 pub(crate) generics
: Generics
,
2084 pub(crate) fn has_stripped_entries(&self) -> bool
{
2085 self.variants
.iter().any(|f
| f
.is_stripped())
2088 pub(crate) fn variants(&self) -> impl Iterator
<Item
= &Item
> {
2089 self.variants
.iter().filter(|v
| !v
.is_stripped())
2093 #[derive(Clone, Debug)]
2094 pub(crate) enum Variant
{
2097 Struct(VariantStruct
),
2101 pub(crate) fn has_stripped_entries(&self) -> Option
<bool
> {
2103 Self::Struct(ref struct_
) => Some(struct_
.has_stripped_entries()),
2104 Self::CLike
| Self::Tuple(_
) => None
,
2109 /// Small wrapper around [`rustc_span::Span`] that adds helper methods
2110 /// and enforces calling [`rustc_span::Span::source_callsite()`].
2111 #[derive(Copy, Clone, Debug)]
2112 pub(crate) struct Span(rustc_span
::Span
);
2115 /// Wraps a [`rustc_span::Span`]. In case this span is the result of a macro expansion, the
2116 /// span will be updated to point to the macro invocation instead of the macro definition.
2118 /// (See rust-lang/rust#39726)
2119 pub(crate) fn new(sp
: rustc_span
::Span
) -> Self {
2120 Self(sp
.source_callsite())
2123 pub(crate) fn inner(&self) -> rustc_span
::Span
{
2127 pub(crate) fn dummy() -> Self {
2128 Self(rustc_span
::DUMMY_SP
)
2131 pub(crate) fn is_dummy(&self) -> bool
{
2135 pub(crate) fn filename(&self, sess
: &Session
) -> FileName
{
2136 sess
.source_map().span_to_filename(self.0)
2139 pub(crate) fn lo(&self, sess
: &Session
) -> Loc
{
2140 sess
.source_map().lookup_char_pos(self.0.lo())
2143 pub(crate) fn hi(&self, sess
: &Session
) -> Loc
{
2144 sess
.source_map().lookup_char_pos(self.0.hi())
2147 pub(crate) fn cnum(&self, sess
: &Session
) -> CrateNum
{
2148 // FIXME: is there a time when the lo and hi crate would be different?
2149 self.lo(sess
).file
.cnum
2153 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2154 pub(crate) struct Path
{
2155 pub(crate) res
: Res
,
2156 pub(crate) segments
: Vec
<PathSegment
>,
2160 pub(crate) fn def_id(&self) -> DefId
{
2164 pub(crate) fn last(&self) -> Symbol
{
2165 self.segments
.last().expect("segments were empty").name
2168 pub(crate) fn whole_name(&self) -> String
{
2171 .map(|s
| if s
.name
== kw
::PathRoot { String::new() }
else { s.name.to_string() }
)
2172 .intersperse("::".into())
2176 /// Checks if this is a `T::Name` path for an associated type.
2177 pub(crate) fn is_assoc_ty(&self) -> bool
{
2179 Res
::SelfTy { .. }
if self.segments
.len() != 1 => true,
2180 Res
::Def(DefKind
::TyParam
, _
) if self.segments
.len() != 1 => true,
2181 Res
::Def(DefKind
::AssocTy
, _
) => true,
2186 pub(crate) fn generics(&self) -> Option
<Vec
<&Type
>> {
2187 self.segments
.last().and_then(|seg
| {
2188 if let GenericArgs
::AngleBracketed { ref args, .. }
= seg
.args
{
2191 .filter_map(|arg
| match arg
{
2192 GenericArg
::Type(ty
) => Some(ty
),
2203 pub(crate) fn bindings(&self) -> Option
<&[TypeBinding
]> {
2204 self.segments
.last().and_then(|seg
| {
2205 if let GenericArgs
::AngleBracketed { ref bindings, .. }
= seg
.args
{
2214 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2215 pub(crate) enum GenericArg
{
2218 Const(Box
<Constant
>),
2222 // `GenericArg` can occur many times in a single `Path`, so make sure it
2223 // doesn't increase in size unexpectedly.
2224 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2225 rustc_data_structures
::static_assert_size
!(GenericArg
, 80);
2227 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2228 pub(crate) enum GenericArgs
{
2229 AngleBracketed { args: Box<[GenericArg]>, bindings: ThinVec<TypeBinding> }
,
2230 Parenthesized { inputs: Box<[Type]>, output: Option<Box<Type>> }
,
2233 // `GenericArgs` is in every `PathSegment`, so its size can significantly
2234 // affect rustdoc's memory usage.
2235 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2236 rustc_data_structures
::static_assert_size
!(GenericArgs
, 32);
2238 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2239 pub(crate) struct PathSegment
{
2240 pub(crate) name
: Symbol
,
2241 pub(crate) args
: GenericArgs
,
2244 // `PathSegment` usually occurs multiple times in every `Path`, so its size can
2245 // significantly affect rustdoc's memory usage.
2246 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2247 rustc_data_structures
::static_assert_size
!(PathSegment
, 40);
2249 #[derive(Clone, Debug)]
2250 pub(crate) struct Typedef
{
2251 pub(crate) type_
: Type
,
2252 pub(crate) generics
: Generics
,
2253 /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
2254 /// alias instead of the final type. This will always have the final type, regardless of whether
2255 /// `type_` came from HIR or from metadata.
2257 /// If `item_type.is_none()`, `type_` is guaranteed to come from metadata (and therefore hold the
2259 pub(crate) item_type
: Option
<Type
>,
2262 #[derive(Clone, Debug)]
2263 pub(crate) struct OpaqueTy
{
2264 pub(crate) bounds
: Vec
<GenericBound
>,
2265 pub(crate) generics
: Generics
,
2268 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2269 pub(crate) struct BareFunctionDecl
{
2270 pub(crate) unsafety
: hir
::Unsafety
,
2271 pub(crate) generic_params
: Vec
<GenericParamDef
>,
2272 pub(crate) decl
: FnDecl
,
2273 pub(crate) abi
: Abi
,
2276 #[derive(Clone, Debug)]
2277 pub(crate) struct Static
{
2278 pub(crate) type_
: Type
,
2279 pub(crate) mutability
: Mutability
,
2280 pub(crate) expr
: Option
<BodyId
>,
2283 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2284 pub(crate) struct Constant
{
2285 pub(crate) type_
: Type
,
2286 pub(crate) kind
: ConstantKind
,
2289 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2290 pub(crate) enum Term
{
2296 pub(crate) fn ty(&self) -> Option
<&Type
> {
2297 if let Term
::Type(ty
) = self { Some(ty) }
else { None }
2301 impl From
<Type
> for Term
{
2302 fn from(ty
: Type
) -> Self {
2307 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2308 pub(crate) enum ConstantKind
{
2309 /// This is the wrapper around `ty::Const` for a non-local constant. Because it doesn't have a
2310 /// `BodyId`, we need to handle it on its own.
2312 /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified
2313 /// by a DefId. So this field must be different from `Extern`.
2314 TyConst { expr: String }
,
2315 /// A constant (expression) that's not an item or associated item. These are usually found
2316 /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
2317 /// used to define explicit discriminant values for enum variants.
2318 Anonymous { body: BodyId }
,
2319 /// A constant from a different crate.
2320 Extern { def_id: DefId }
,
2321 /// `const FOO: u32 = ...;`
2322 Local { def_id: DefId, body: BodyId }
,
2326 pub(crate) fn expr(&self, tcx
: TyCtxt
<'_
>) -> String
{
2330 pub(crate) fn value(&self, tcx
: TyCtxt
<'_
>) -> Option
<String
> {
2331 self.kind
.value(tcx
)
2334 pub(crate) fn is_literal(&self, tcx
: TyCtxt
<'_
>) -> bool
{
2335 self.kind
.is_literal(tcx
)
2340 pub(crate) fn expr(&self, tcx
: TyCtxt
<'_
>) -> String
{
2342 ConstantKind
::TyConst { ref expr }
=> expr
.clone(),
2343 ConstantKind
::Extern { def_id }
=> print_inlined_const(tcx
, def_id
),
2344 ConstantKind
::Local { body, .. }
| ConstantKind
::Anonymous { body }
=> {
2345 print_const_expr(tcx
, body
)
2350 pub(crate) fn value(&self, tcx
: TyCtxt
<'_
>) -> Option
<String
> {
2352 ConstantKind
::TyConst { .. }
| ConstantKind
::Anonymous { .. }
=> None
,
2353 ConstantKind
::Extern { def_id }
| ConstantKind
::Local { def_id, .. }
=> {
2354 print_evaluated_const(tcx
, def_id
)
2359 pub(crate) fn is_literal(&self, tcx
: TyCtxt
<'_
>) -> bool
{
2361 ConstantKind
::TyConst { .. }
=> false,
2362 ConstantKind
::Extern { def_id }
=> def_id
.as_local().map_or(false, |def_id
| {
2363 is_literal_expr(tcx
, tcx
.hir().local_def_id_to_hir_id(def_id
))
2365 ConstantKind
::Local { body, .. }
| ConstantKind
::Anonymous { body }
=> {
2366 is_literal_expr(tcx
, body
.hir_id
)
2372 #[derive(Clone, Debug)]
2373 pub(crate) struct Impl
{
2374 pub(crate) unsafety
: hir
::Unsafety
,
2375 pub(crate) generics
: Generics
,
2376 pub(crate) trait_
: Option
<Path
>,
2377 pub(crate) for_
: Type
,
2378 pub(crate) items
: Vec
<Item
>,
2379 pub(crate) polarity
: ty
::ImplPolarity
,
2380 pub(crate) kind
: ImplKind
,
2384 pub(crate) fn provided_trait_methods(&self, tcx
: TyCtxt
<'_
>) -> FxHashSet
<Symbol
> {
2387 .map(|t
| t
.def_id())
2388 .map(|did
| tcx
.provided_trait_methods(did
).map(|meth
| meth
.name
).collect())
2389 .unwrap_or_default()
2393 #[derive(Clone, Debug)]
2394 pub(crate) enum ImplKind
{
2402 pub(crate) fn is_auto(&self) -> bool
{
2403 matches
!(self, ImplKind
::Auto
)
2406 pub(crate) fn is_blanket(&self) -> bool
{
2407 matches
!(self, ImplKind
::Blanket(_
))
2410 pub(crate) fn is_tuple_variadic(&self) -> bool
{
2411 matches
!(self, ImplKind
::TupleVaradic
)
2414 pub(crate) fn as_blanket_ty(&self) -> Option
<&Type
> {
2416 ImplKind
::Blanket(ty
) => Some(ty
),
2422 #[derive(Clone, Debug)]
2423 pub(crate) struct Import
{
2424 pub(crate) kind
: ImportKind
,
2425 pub(crate) source
: ImportSource
,
2426 pub(crate) should_be_displayed
: bool
,
2430 pub(crate) fn new_simple(
2432 source
: ImportSource
,
2433 should_be_displayed
: bool
,
2435 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2438 pub(crate) fn new_glob(source
: ImportSource
, should_be_displayed
: bool
) -> Self {
2439 Self { kind: ImportKind::Glob, source, should_be_displayed }
2443 #[derive(Clone, Debug)]
2444 pub(crate) enum ImportKind
{
2445 // use source as str;
2451 #[derive(Clone, Debug)]
2452 pub(crate) struct ImportSource
{
2453 pub(crate) path
: Path
,
2454 pub(crate) did
: Option
<DefId
>,
2457 #[derive(Clone, Debug)]
2458 pub(crate) struct Macro
{
2459 pub(crate) source
: String
,
2462 #[derive(Clone, Debug)]
2463 pub(crate) struct ProcMacro
{
2464 pub(crate) kind
: MacroKind
,
2465 pub(crate) helpers
: Vec
<Symbol
>,
2468 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
2469 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
2470 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2471 pub(crate) struct TypeBinding
{
2472 pub(crate) assoc
: PathSegment
,
2473 pub(crate) kind
: TypeBindingKind
,
2476 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2477 pub(crate) enum TypeBindingKind
{
2478 Equality { term: Term }
,
2479 Constraint { bounds: Vec<GenericBound> }
,
2483 pub(crate) fn term(&self) -> &Term
{
2485 TypeBindingKind
::Equality { ref term }
=> term
,
2486 _
=> panic
!("expected equality type binding for parenthesized generic args"),
2491 /// The type, lifetime, or constant that a private type alias's parameter should be
2492 /// replaced with when expanding a use of that type alias.
2497 /// type PrivAlias<T> = Vec<T>;
2499 /// pub fn public_fn() -> PrivAlias<i32> { vec![] }
2502 /// `public_fn`'s docs will show it as returning `Vec<i32>`, since `PrivAlias` is private.
2503 /// [`SubstParam`] is used to record that `T` should be mapped to `i32`.
2504 pub(crate) enum SubstParam
{
2511 pub(crate) fn as_ty(&self) -> Option
<&Type
> {
2512 if let Self::Type(ty
) = self { Some(ty) }
else { None }
2515 pub(crate) fn as_lt(&self) -> Option
<&Lifetime
> {
2516 if let Self::Lifetime(lt
) = self { Some(lt) }
else { None }