1 use std
::cell
::RefCell
;
2 use std
::default::Default
;
6 use std
::lazy
::SyncOnceCell
as OnceCell
;
7 use std
::path
::PathBuf
;
12 use arrayvec
::ArrayVec
;
15 use rustc_ast
::util
::comments
::beautify_doc_string
;
16 use rustc_ast
::{self as ast, AttrStyle}
;
17 use rustc_attr
::{ConstStability, Deprecation, Stability, StabilityLevel}
;
18 use rustc_const_eval
::const_eval
::is_unstable_const_fn
;
19 use rustc_data_structures
::fx
::{FxHashMap, FxHashSet}
;
20 use rustc_data_structures
::thin_vec
::ThinVec
;
22 use rustc_hir
::def
::{CtorKind, DefKind, Res}
;
23 use rustc_hir
::def_id
::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}
;
24 use rustc_hir
::lang_items
::LangItem
;
25 use rustc_hir
::{BodyId, Mutability}
;
26 use rustc_index
::vec
::IndexVec
;
27 use rustc_middle
::ty
::fast_reject
::SimplifiedType
;
28 use rustc_middle
::ty
::{self, TyCtxt}
;
29 use rustc_session
::Session
;
30 use rustc_span
::hygiene
::MacroKind
;
31 use rustc_span
::source_map
::DUMMY_SP
;
32 use rustc_span
::symbol
::{kw, sym, Ident, Symbol}
;
33 use rustc_span
::{self, FileName, Loc}
;
34 use rustc_target
::abi
::VariantIdx
;
35 use rustc_target
::spec
::abi
::Abi
;
36 use rustc_typeck
::check
::intrinsic
::intrinsic_operation_unsafety
;
38 use crate::clean
::cfg
::Cfg
;
39 use crate::clean
::external_path
;
40 use crate::clean
::inline
::{self, print_inlined_const}
;
41 use crate::clean
::utils
::{is_literal_expr, print_const_expr, print_evaluated_const}
;
42 use crate::clean
::Clean
;
43 use crate::core
::DocContext
;
44 use crate::formats
::cache
::Cache
;
45 use crate::formats
::item_type
::ItemType
;
46 use crate::html
::render
::Context
;
47 use crate::passes
::collect_intra_doc_links
::UrlFragment
;
49 crate use self::FnRetTy
::*;
50 crate use self::ItemKind
::*;
51 crate use self::SelfTy
::*;
52 crate use self::Type
::{
53 Array
, BareFunction
, BorrowedRef
, DynTrait
, Generic
, ImplTrait
, Infer
, Primitive
, QPath
,
54 RawPointer
, Slice
, Tuple
,
56 crate use self::Visibility
::{Inherited, Public}
;
58 crate type ItemIdSet
= FxHashSet
<ItemId
>;
60 #[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
62 /// A "normal" item that uses a [`DefId`] for identification.
64 /// Identifier that is used for auto traits.
65 Auto { trait_: DefId, for_: DefId }
,
66 /// Identifier that is used for blanket implementations.
67 Blanket { impl_id: DefId, for_: DefId }
,
68 /// Identifier for primitive types.
69 Primitive(PrimitiveType
, CrateNum
),
74 crate fn is_local(self) -> bool
{
76 ItemId
::Auto { for_: id, .. }
77 | ItemId
::Blanket { for_: id, .. }
78 | ItemId
::DefId(id
) => id
.is_local(),
79 ItemId
::Primitive(_
, krate
) => krate
== LOCAL_CRATE
,
85 crate fn expect_def_id(self) -> DefId
{
87 .unwrap_or_else(|| panic
!("ItemId::expect_def_id: `{:?}` isn't a DefId", self))
91 crate fn as_def_id(self) -> Option
<DefId
> {
93 ItemId
::DefId(id
) => Some(id
),
99 crate fn krate(self) -> CrateNum
{
101 ItemId
::Auto { for_: id, .. }
102 | ItemId
::Blanket { for_: id, .. }
103 | ItemId
::DefId(id
) => id
.krate
,
104 ItemId
::Primitive(_
, krate
) => krate
,
109 crate fn index(self) -> Option
<DefIndex
> {
111 ItemId
::DefId(id
) => Some(id
.index
),
117 impl From
<DefId
> for ItemId
{
118 fn from(id
: DefId
) -> Self {
123 /// The crate currently being documented.
124 #[derive(Clone, Debug)]
127 crate primitives
: ThinVec
<(DefId
, PrimitiveType
)>,
128 /// Only here so that they can be filtered through the rustdoc passes.
129 crate external_traits
: Rc
<RefCell
<FxHashMap
<DefId
, TraitWithExtraInfo
>>>,
132 // `Crate` is frequently moved by-value. Make sure it doesn't unintentionally get bigger.
133 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
134 rustc_data_structures
::static_assert_size
!(Crate
, 72);
137 crate fn name(&self, tcx
: TyCtxt
<'_
>) -> Symbol
{
138 ExternalCrate
::LOCAL
.name(tcx
)
141 crate fn src(&self, tcx
: TyCtxt
<'_
>) -> FileName
{
142 ExternalCrate
::LOCAL
.src(tcx
)
146 /// This struct is used to wrap additional information added by rustdoc on a `trait` item.
147 #[derive(Clone, Debug)]
148 crate struct TraitWithExtraInfo
{
150 crate is_notable
: bool
,
153 #[derive(Copy, Clone, Debug)]
154 crate struct ExternalCrate
{
155 crate crate_num
: CrateNum
,
159 const LOCAL
: Self = Self { crate_num: LOCAL_CRATE }
;
162 crate fn def_id(&self) -> DefId
{
163 DefId { krate: self.crate_num, index: CRATE_DEF_INDEX }
166 crate fn src(&self, tcx
: TyCtxt
<'_
>) -> FileName
{
167 let krate_span
= tcx
.def_span(self.def_id());
168 tcx
.sess
.source_map().span_to_filename(krate_span
)
171 crate fn name(&self, tcx
: TyCtxt
<'_
>) -> Symbol
{
172 tcx
.crate_name(self.crate_num
)
175 crate fn src_root(&self, tcx
: TyCtxt
<'_
>) -> PathBuf
{
176 match self.src(tcx
) {
177 FileName
::Real(ref p
) => match p
.local_path_if_available().parent() {
178 Some(p
) => p
.to_path_buf(),
179 None
=> PathBuf
::new(),
185 /// Attempts to find where an external crate is located, given that we're
186 /// rendering in to the specified source destination.
189 extern_url
: Option
<&str>,
190 extern_url_takes_precedence
: bool
,
191 dst
: &std
::path
::Path
,
193 ) -> ExternalLocation
{
194 use ExternalLocation
::*;
196 fn to_remote(url
: impl ToString
) -> ExternalLocation
{
197 let mut url
= url
.to_string();
198 if !url
.ends_with('
/'
) {
204 // See if there's documentation generated into the local directory
205 // WARNING: since rustdoc creates these directories as it generates documentation, this check is only accurate before rendering starts.
206 // Make sure to call `location()` by that time.
207 let local_location
= dst
.join(self.name(tcx
).as_str());
208 if local_location
.is_dir() {
212 if extern_url_takes_precedence
{
213 if let Some(url
) = extern_url
{
214 return to_remote(url
);
218 // Failing that, see if there's an attribute specifying where to find this
220 let did
= DefId { krate: self.crate_num, index: CRATE_DEF_INDEX }
;
223 .filter(|a
| a
.has_name(sym
::html_root_url
))
224 .filter_map(|a
| a
.value_str())
227 .or_else(|| extern_url
.map(to_remote
)) // NOTE: only matters if `extern_url_takes_precedence` is false
228 .unwrap_or(Unknown
) // Well, at least we tried.
231 crate fn keywords(&self, tcx
: TyCtxt
<'_
>) -> ThinVec
<(DefId
, Symbol
)> {
232 let root
= self.def_id();
234 let as_keyword
= |res
: Res
<!>| {
235 if let Res
::Def(DefKind
::Mod
, def_id
) = res
{
236 let attrs
= tcx
.get_attrs(def_id
);
237 let mut keyword
= None
;
238 for attr
in attrs
.lists(sym
::doc
) {
239 if attr
.has_name(sym
::keyword
) {
240 if let Some(v
) = attr
.value_str() {
246 return keyword
.map(|p
| (def_id
, p
));
256 let item
= tcx
.hir().item(id
);
258 hir
::ItemKind
::Mod(_
) => {
259 as_keyword(Res
::Def(DefKind
::Mod
, id
.def_id
.to_def_id()))
261 hir
::ItemKind
::Use(path
, hir
::UseKind
::Single
)
262 if tcx
.visibility(id
.def_id
).is_public() =>
264 as_keyword(path
.res
.expect_non_local())
265 .map(|(_
, prim
)| (id
.def_id
.to_def_id(), prim
))
272 tcx
.module_children(root
).iter().map(|item
| item
.res
).filter_map(as_keyword
).collect()
276 crate fn primitives(&self, tcx
: TyCtxt
<'_
>) -> ThinVec
<(DefId
, PrimitiveType
)> {
277 let root
= self.def_id();
279 // Collect all inner modules which are tagged as implementations of
282 // Note that this loop only searches the top-level items of the crate,
283 // and this is intentional. If we were to search the entire crate for an
284 // item tagged with `#[doc(primitive)]` then we would also have to
285 // search the entirety of external modules for items tagged
286 // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
287 // all that metadata unconditionally).
289 // In order to keep the metadata load under control, the
290 // `#[doc(primitive)]` feature is explicitly designed to only allow the
291 // primitive tags to show up as the top level items in a crate.
293 // Also note that this does not attempt to deal with modules tagged
294 // duplicately for the same primitive. This is handled later on when
295 // rendering by delegating everything to a hash map.
296 let as_primitive
= |res
: Res
<!>| {
297 if let Res
::Def(DefKind
::Mod
, def_id
) = res
{
298 let attrs
= tcx
.get_attrs(def_id
);
300 for attr
in attrs
.lists(sym
::doc
) {
301 if let Some(v
) = attr
.value_str() {
302 if attr
.has_name(sym
::primitive
) {
303 prim
= PrimitiveType
::from_symbol(v
);
307 // FIXME: should warn on unknown primitives?
311 return prim
.map(|p
| (def_id
, p
));
322 let item
= tcx
.hir().item(id
);
324 hir
::ItemKind
::Mod(_
) => {
325 as_primitive(Res
::Def(DefKind
::Mod
, id
.def_id
.to_def_id()))
327 hir
::ItemKind
::Use(path
, hir
::UseKind
::Single
)
328 if tcx
.visibility(id
.def_id
).is_public() =>
330 as_primitive(path
.res
.expect_non_local()).map(|(_
, prim
)| {
331 // Pretend the primitive is local.
332 (id
.def_id
.to_def_id(), prim
)
340 tcx
.module_children(root
).iter().map(|item
| item
.res
).filter_map(as_primitive
).collect()
345 /// Indicates where an external crate can be found.
347 crate enum ExternalLocation
{
348 /// Remote URL root of the external crate
350 /// This external crate can be found in the local doc/ folder
352 /// The external crate could not be found.
356 /// Anything with a source location and set of attributes and, optionally, a
357 /// name. That is, anything that can be documented. This doesn't correspond
358 /// directly to the AST's concept of an item; it's a strict superset.
361 /// The name of this item.
362 /// Optional because not every item has a name, e.g. impls.
363 crate name
: Option
<Symbol
>,
364 crate attrs
: Box
<Attributes
>,
365 crate visibility
: Visibility
,
366 /// Information about this item that is specific to what kind of item it is.
367 /// E.g., struct vs enum vs function.
368 crate kind
: Box
<ItemKind
>,
369 crate def_id
: ItemId
,
371 crate cfg
: Option
<Arc
<Cfg
>>,
374 /// NOTE: this does NOT unconditionally print every item, to avoid thousands of lines of logs.
375 /// If you want to see the debug output for attributes and the `kind` as well, use `{:#?}` instead of `{:?}`.
376 impl fmt
::Debug
for Item
{
377 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
378 let alternate
= f
.alternate();
379 // hand-picked fields that don't bloat the logs too much
380 let mut fmt
= f
.debug_struct("Item");
381 fmt
.field("name", &self.name
)
382 .field("visibility", &self.visibility
)
383 .field("def_id", &self.def_id
);
384 // allow printing the full item if someone really wants to
386 fmt
.field("attrs", &self.attrs
).field("kind", &self.kind
).field("cfg", &self.cfg
);
388 fmt
.field("kind", &self.type_());
389 fmt
.field("docs", &self.doc_value());
395 // `Item` is used a lot. Make sure it doesn't unintentionally get bigger.
396 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
397 rustc_data_structures
::static_assert_size
!(Item
, 56);
399 crate fn rustc_span(def_id
: DefId
, tcx
: TyCtxt
<'_
>) -> Span
{
400 Span
::new(def_id
.as_local().map_or_else(
401 || tcx
.def_span(def_id
),
404 hir
.span_with_body(hir
.local_def_id_to_hir_id(local
))
410 crate fn stability
<'tcx
>(&self, tcx
: TyCtxt
<'tcx
>) -> Option
<Stability
> {
411 self.def_id
.as_def_id().and_then(|did
| tcx
.lookup_stability(did
))
414 crate fn const_stability
<'tcx
>(&self, tcx
: TyCtxt
<'tcx
>) -> Option
<ConstStability
> {
415 self.def_id
.as_def_id().and_then(|did
| tcx
.lookup_const_stability(did
))
418 crate fn deprecation(&self, tcx
: TyCtxt
<'_
>) -> Option
<Deprecation
> {
419 self.def_id
.as_def_id().and_then(|did
| tcx
.lookup_deprecation(did
))
422 crate fn inner_docs(&self, tcx
: TyCtxt
<'_
>) -> bool
{
423 self.def_id
.as_def_id().map(|did
| tcx
.get_attrs(did
).inner_docs()).unwrap_or(false)
426 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.def_id
{
436 rustc_span(impl_id
, tcx
)
438 panic
!("blanket impl item has non-blanket ID")
442 self.def_id
.as_def_id().map(|did
| rustc_span(did
, tcx
)).unwrap_or_else(Span
::dummy
)
447 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 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 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 crate fn from_def_id_and_parts(
470 name
: Option
<Symbol
>,
472 cx
: &mut DocContext
<'_
>,
474 let ast_attrs
= cx
.tcx
.get_attrs(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 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 { def_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 crate fn collapsed_doc_value(&self) -> Option
<String
> {
512 self.attrs
.collapsed_doc_value()
515 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()).unwrap()
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 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 crate fn is_crate(&self) -> bool
{
562 self.is_mod() && self.def_id
.as_def_id().map_or(false, |did
| did
.index
== CRATE_DEF_INDEX
)
564 crate fn is_mod(&self) -> bool
{
565 self.type_() == ItemType
::Module
567 crate fn is_trait(&self) -> bool
{
568 self.type_() == ItemType
::Trait
570 crate fn is_struct(&self) -> bool
{
571 self.type_() == ItemType
::Struct
573 crate fn is_enum(&self) -> bool
{
574 self.type_() == ItemType
::Enum
576 crate fn is_variant(&self) -> bool
{
577 self.type_() == ItemType
::Variant
579 crate fn is_associated_type(&self) -> bool
{
580 self.type_() == ItemType
::AssocType
582 crate fn is_associated_const(&self) -> bool
{
583 self.type_() == ItemType
::AssocConst
585 crate fn is_method(&self) -> bool
{
586 self.type_() == ItemType
::Method
588 crate fn is_ty_method(&self) -> bool
{
589 self.type_() == ItemType
::TyMethod
591 crate fn is_typedef(&self) -> bool
{
592 self.type_() == ItemType
::Typedef
594 crate fn is_primitive(&self) -> bool
{
595 self.type_() == ItemType
::Primitive
597 crate fn is_union(&self) -> bool
{
598 self.type_() == ItemType
::Union
600 crate fn is_import(&self) -> bool
{
601 self.type_() == ItemType
::Import
603 crate fn is_extern_crate(&self) -> bool
{
604 self.type_() == ItemType
::ExternCrate
606 crate fn is_keyword(&self) -> bool
{
607 self.type_() == ItemType
::Keyword
609 crate fn is_stripped(&self) -> bool
{
611 StrippedItem(..) => true,
612 ImportItem(ref i
) => !i
.should_be_displayed
,
616 crate fn has_stripped_fields(&self) -> Option
<bool
> {
618 StructItem(ref _struct
) => Some(_struct
.fields_stripped
),
619 UnionItem(ref union) => Some(union.fields_stripped
),
620 VariantItem(Variant
::Struct(ref vstruct
)) => Some(vstruct
.fields_stripped
),
625 crate fn stability_class(&self, tcx
: TyCtxt
<'_
>) -> Option
<String
> {
626 self.stability(tcx
).as_ref().and_then(|s
| {
627 let mut classes
= Vec
::with_capacity(2);
629 if s
.level
.is_unstable() {
630 classes
.push("unstable");
633 // FIXME: what about non-staged API items that are deprecated?
634 if self.deprecation(tcx
).is_some() {
635 classes
.push("deprecated");
638 if !classes
.is_empty() { Some(classes.join(" ")) }
else { None }
642 crate fn stable_since(&self, tcx
: TyCtxt
<'_
>) -> Option
<Symbol
> {
643 match self.stability(tcx
)?
.level
{
644 StabilityLevel
::Stable { since, .. }
=> Some(since
),
645 StabilityLevel
::Unstable { .. }
=> None
,
649 crate fn const_stable_since(&self, tcx
: TyCtxt
<'_
>) -> Option
<Symbol
> {
650 match self.const_stability(tcx
)?
.level
{
651 StabilityLevel
::Stable { since, .. }
=> Some(since
),
652 StabilityLevel
::Unstable { .. }
=> None
,
656 crate fn is_non_exhaustive(&self) -> bool
{
657 self.attrs
.other_attrs
.iter().any(|a
| a
.has_name(sym
::non_exhaustive
))
660 /// Returns a documentation-level item type from the item.
661 crate fn type_(&self) -> ItemType
{
665 crate fn is_default(&self) -> bool
{
667 ItemKind
::MethodItem(_
, Some(defaultness
)) => {
668 defaultness
.has_value() && !defaultness
.is_final()
674 /// Returns a `FnHeader` if `self` is a function item, otherwise returns `None`.
675 crate fn fn_header(&self, tcx
: TyCtxt
<'_
>) -> Option
<hir
::FnHeader
> {
679 asyncness
: hir
::IsAsync
,
681 let sig
= tcx
.fn_sig(def_id
);
683 if tcx
.is_const_fn(def_id
) && is_unstable_const_fn(tcx
, def_id
).is_none() {
684 hir
::Constness
::Const
686 hir
::Constness
::NotConst
688 hir
::FnHeader { unsafety: sig.unsafety(), abi: sig.abi(), constness, asyncness }
690 let header
= match *self.kind
{
691 ItemKind
::ForeignFunctionItem(_
) => {
692 let abi
= tcx
.fn_sig(self.def_id
.as_def_id().unwrap()).abi();
694 unsafety
: if abi
== Abi
::RustIntrinsic
{
695 intrinsic_operation_unsafety(self.name
.unwrap())
697 hir
::Unsafety
::Unsafe
700 constness
: hir
::Constness
::NotConst
,
701 asyncness
: hir
::IsAsync
::NotAsync
,
704 ItemKind
::FunctionItem(_
) | ItemKind
::MethodItem(_
, _
) => {
705 let def_id
= self.def_id
.as_def_id().unwrap();
706 build_fn_header(def_id
, tcx
, tcx
.asyncness(def_id
))
708 ItemKind
::TyMethodItem(_
) => {
709 build_fn_header(self.def_id
.as_def_id().unwrap(), tcx
, hir
::IsAsync
::NotAsync
)
717 #[derive(Clone, Debug)]
718 crate enum ItemKind
{
720 /// The crate's name, *not* the name it's imported as.
727 FunctionItem(Function
),
729 TypedefItem(Typedef
, bool
/* is associated type */),
730 OpaqueTyItem(OpaqueTy
),
732 ConstantItem(Constant
),
734 TraitAliasItem(TraitAlias
),
736 /// A method signature only. Used for required methods in traits (ie,
737 /// non-default-methods).
738 TyMethodItem(Function
),
739 /// A method with a body.
740 MethodItem(Function
, Option
<hir
::Defaultness
>),
741 StructFieldItem(Type
),
742 VariantItem(Variant
),
743 /// `fn`s from an extern block
744 ForeignFunctionItem(Function
),
745 /// `static`s from an extern block
746 ForeignStaticItem(Static
),
747 /// `type`s from an extern block
750 ProcMacroItem(ProcMacro
),
751 PrimitiveItem(PrimitiveType
),
752 AssocConstItem(Type
, Option
<ConstantKind
>),
753 /// An associated item in a trait or trait impl.
755 /// The bounds may be non-empty if there is a `where` clause.
756 /// The `Option<Type>` is the default concrete type (e.g. `trait Trait { type Target = usize; }`)
757 AssocTypeItem(Box
<Generics
>, Vec
<GenericBound
>, Option
<Type
>),
758 /// An item that has been stripped by a rustdoc pass
759 StrippedItem(Box
<ItemKind
>),
764 /// Some items contain others such as structs (for their fields) and Enums
765 /// (for their variants). This method returns those contained items.
766 crate fn inner_items(&self) -> impl Iterator
<Item
= &Item
> {
768 StructItem(s
) => s
.fields
.iter(),
769 UnionItem(u
) => u
.fields
.iter(),
770 VariantItem(Variant
::Struct(v
)) => v
.fields
.iter(),
771 VariantItem(Variant
::Tuple(v
)) => v
.iter(),
772 EnumItem(e
) => e
.variants
.iter(),
773 TraitItem(t
) => t
.items
.iter(),
774 ImplItem(i
) => i
.items
.iter(),
775 ModuleItem(m
) => m
.items
.iter(),
776 ExternCrateItem { .. }
788 | ForeignFunctionItem(_
)
789 | ForeignStaticItem(_
)
794 | AssocConstItem(_
, _
)
797 | KeywordItem(_
) => [].iter(),
802 #[derive(Clone, Debug)]
803 crate struct Module
{
804 crate items
: Vec
<Item
>,
808 crate trait AttributesExt
{
809 type AttributeIterator
<'a
>: Iterator
<Item
= ast
::NestedMetaItem
>
813 fn lists
<'a
>(&'a
self, name
: Symbol
) -> Self::AttributeIterator
<'a
>;
815 fn span(&self) -> Option
<rustc_span
::Span
>;
817 fn inner_docs(&self) -> bool
;
819 fn other_attrs(&self) -> Vec
<ast
::Attribute
>;
821 fn cfg(&self, tcx
: TyCtxt
<'_
>, hidden_cfg
: &FxHashSet
<Cfg
>) -> Option
<Arc
<Cfg
>>;
824 impl AttributesExt
for [ast
::Attribute
] {
825 type AttributeIterator
<'a
> = impl Iterator
<Item
= ast
::NestedMetaItem
> + 'a
;
827 fn lists
<'a
>(&'a
self, name
: Symbol
) -> Self::AttributeIterator
<'a
> {
829 .filter(move |attr
| attr
.has_name(name
))
830 .filter_map(ast
::Attribute
::meta_item_list
)
834 /// Return the span of the first doc-comment, if it exists.
835 fn span(&self) -> Option
<rustc_span
::Span
> {
836 self.iter().find(|attr
| attr
.doc_str().is_some()).map(|attr
| attr
.span
)
839 /// Returns whether the first doc-comment is an inner attribute.
841 //// If there are no doc-comments, return true.
842 /// FIXME(#78591): Support both inner and outer attributes on the same item.
843 fn inner_docs(&self) -> bool
{
844 self.iter().find(|a
| a
.doc_str().is_some()).map_or(true, |a
| a
.style
== AttrStyle
::Inner
)
847 fn other_attrs(&self) -> Vec
<ast
::Attribute
> {
848 self.iter().filter(|attr
| attr
.doc_str().is_none()).cloned().collect()
851 fn cfg(&self, tcx
: TyCtxt
<'_
>, hidden_cfg
: &FxHashSet
<Cfg
>) -> Option
<Arc
<Cfg
>> {
853 let doc_cfg_active
= tcx
.features().doc_cfg
;
854 let doc_auto_cfg_active
= tcx
.features().doc_auto_cfg
;
856 fn single
<T
: IntoIterator
>(it
: T
) -> Option
<T
::Item
> {
857 let mut iter
= it
.into_iter();
858 let item
= iter
.next()?
;
859 if iter
.next().is_some() {
865 let mut cfg
= if doc_cfg_active
|| doc_auto_cfg_active
{
866 let mut doc_cfg
= self
868 .filter(|attr
| attr
.has_name(sym
::doc
))
869 .flat_map(|attr
| attr
.meta_item_list().unwrap_or_else(Vec
::new
))
870 .filter(|attr
| attr
.has_name(sym
::cfg
))
872 if doc_cfg
.peek().is_some() && doc_cfg_active
{
874 .filter_map(|attr
| Cfg
::parse(attr
.meta_item()?
).ok())
875 .fold(Cfg
::True
, |cfg
, new_cfg
| cfg
& new_cfg
)
876 } else if doc_auto_cfg_active
{
878 .filter(|attr
| attr
.has_name(sym
::cfg
))
879 .filter_map(|attr
| single(attr
.meta_item_list()?
))
881 Cfg
::parse_without(attr
.meta_item()?
, hidden_cfg
).ok().flatten()
883 .fold(Cfg
::True
, |cfg
, new_cfg
| cfg
& new_cfg
)
891 for attr
in self.iter() {
893 if attr
.doc_str().is_none() && attr
.has_name(sym
::doc
) {
895 if let Some(list
) = attr
.meta().as_ref().and_then(|mi
| mi
.meta_item_list()) {
898 if !item
.has_name(sym
::cfg
) {
902 if let Some(cfg_mi
) = item
904 .and_then(|item
| rustc_expand
::config
::parse_cfg(item
, sess
))
906 match Cfg
::parse(cfg_mi
) {
907 Ok(new_cfg
) => cfg
&= new_cfg
,
909 sess
.span_err(e
.span
, e
.msg
);
918 // treat #[target_feature(enable = "feat")] attributes as if they were
919 // #[doc(cfg(target_feature = "feat"))] attributes as well
920 for attr
in self.lists(sym
::target_feature
) {
921 if attr
.has_name(sym
::enable
) {
922 if let Some(feat
) = attr
.value_str() {
923 let meta
= attr
::mk_name_value_item_str(
924 Ident
::with_dummy_span(sym
::target_feature
),
928 if let Ok(feat_cfg
) = Cfg
::parse(&meta
) {
935 if cfg
== Cfg
::True { None }
else { Some(Arc::new(cfg)) }
939 crate trait NestedAttributesExt
{
940 /// Returns `true` if the attribute list contains a specific `word`
941 fn has_word(self, word
: Symbol
) -> bool
943 Self: std
::marker
::Sized
,
945 <Self as NestedAttributesExt
>::get_word_attr(self, word
).is_some()
948 /// Returns `Some(attr)` if the attribute list contains 'attr'
949 /// corresponding to a specific `word`
950 fn get_word_attr(self, word
: Symbol
) -> Option
<ast
::NestedMetaItem
>;
953 impl<I
: Iterator
<Item
= ast
::NestedMetaItem
>> NestedAttributesExt
for I
{
954 fn get_word_attr(mut self, word
: Symbol
) -> Option
<ast
::NestedMetaItem
> {
955 self.find(|attr
| attr
.is_word() && attr
.has_name(word
))
959 /// A portion of documentation, extracted from a `#[doc]` attribute.
961 /// Each variant contains the line number within the complete doc-comment where the fragment
962 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
964 /// Included files are kept separate from inline doc comments so that proper line-number
965 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
966 /// kept separate because of issue #42760.
967 #[derive(Clone, PartialEq, Eq, Debug)]
968 crate struct DocFragment
{
969 crate span
: rustc_span
::Span
,
970 /// The module this doc-comment came from.
972 /// This allows distinguishing between the original documentation and a pub re-export.
973 /// If it is `None`, the item was not re-exported.
974 crate parent_module
: Option
<DefId
>,
976 crate kind
: DocFragmentKind
,
980 // `DocFragment` is used a lot. Make sure it doesn't unintentionally get bigger.
981 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
982 rustc_data_structures
::static_assert_size
!(DocFragment
, 32);
984 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
985 crate enum DocFragmentKind
{
986 /// A doc fragment created from a `///` or `//!` doc comment.
988 /// A doc fragment created from a "raw" `#[doc=""]` attribute.
992 /// The goal of this function is to apply the `DocFragment` transformation that is required when
993 /// transforming into the final Markdown, which is applying the computed indent to each line in
994 /// each doc fragment (a `DocFragment` can contain multiple lines in case of `#[doc = ""]`).
996 /// Note: remove the trailing newline where appropriate
997 fn add_doc_fragment(out
: &mut String
, frag
: &DocFragment
) {
998 let s
= frag
.doc
.as_str();
999 let mut iter
= s
.lines();
1004 while let Some(line
) = iter
.next() {
1005 if line
.chars().any(|c
| !c
.is_whitespace()) {
1006 assert
!(line
.len() >= frag
.indent
);
1007 out
.push_str(&line
[frag
.indent
..]);
1015 /// Collapse a collection of [`DocFragment`]s into one string,
1016 /// handling indentation and newlines as needed.
1017 crate fn collapse_doc_fragments(doc_strings
: &[DocFragment
]) -> String
{
1018 let mut acc
= String
::new();
1019 for frag
in doc_strings
{
1020 add_doc_fragment(&mut acc
, frag
);
1026 /// A link that has not yet been rendered.
1028 /// This link will be turned into a rendered link by [`Item::links`].
1029 #[derive(Clone, Debug, PartialEq, Eq)]
1030 crate struct ItemLink
{
1031 /// The original link written in the markdown
1033 /// The link text displayed in the HTML.
1035 /// This may not be the same as `link` if there was a disambiguator
1036 /// in an intra-doc link (e.g. \[`fn@f`\])
1037 crate link_text
: String
,
1039 /// The url fragment to append to the link
1040 crate fragment
: Option
<UrlFragment
>,
1043 pub struct RenderedLink
{
1044 /// The text the link was original written as.
1046 /// This could potentially include disambiguators and backticks.
1047 crate original_text
: String
,
1048 /// The text to display in the HTML
1049 crate new_text
: String
,
1050 /// The URL to put in the `href`
1054 /// The attributes on an [`Item`], including attributes like `#[derive(...)]` and `#[inline]`,
1055 /// as well as doc comments.
1056 #[derive(Clone, Debug, Default)]
1057 crate struct Attributes
{
1058 crate doc_strings
: Vec
<DocFragment
>,
1059 crate other_attrs
: Vec
<ast
::Attribute
>,
1063 crate fn lists(&self, name
: Symbol
) -> impl Iterator
<Item
= ast
::NestedMetaItem
> + '_
{
1064 self.other_attrs
.lists(name
)
1067 crate fn has_doc_flag(&self, flag
: Symbol
) -> bool
{
1068 for attr
in &self.other_attrs
{
1069 if !attr
.has_name(sym
::doc
) {
1073 if let Some(items
) = attr
.meta_item_list() {
1074 if items
.iter().filter_map(|i
| i
.meta_item()).any(|it
| it
.has_name(flag
)) {
1084 attrs
: &[ast
::Attribute
],
1085 additional_attrs
: Option
<(&[ast
::Attribute
], DefId
)>,
1087 let mut doc_strings
: Vec
<DocFragment
> = vec
![];
1088 let clean_attr
= |(attr
, parent_module
): (&ast
::Attribute
, Option
<DefId
>)| {
1089 if let Some((value
, kind
)) = attr
.doc_str_and_comment_kind() {
1090 trace
!("got doc_str={:?}", value
);
1091 let value
= beautify_doc_string(value
, kind
);
1092 let kind
= if attr
.is_doc_comment() {
1093 DocFragmentKind
::SugaredDoc
1095 DocFragmentKind
::RawDoc
1099 DocFragment { span: attr.span, doc: value, kind, parent_module, indent: 0 }
;
1101 doc_strings
.push(frag
);
1109 // Additional documentation should be shown before the original documentation
1110 let other_attrs
= additional_attrs
1112 .flat_map(|(attrs
, id
)| attrs
.iter().map(move |attr
| (attr
, Some(id
))))
1113 .chain(attrs
.iter().map(|attr
| (attr
, None
)))
1114 .filter_map(clean_attr
)
1117 Attributes { doc_strings, other_attrs }
1120 /// Finds the `doc` attribute as a NameValue and returns the corresponding
1122 crate fn doc_value(&self) -> Option
<String
> {
1123 let mut iter
= self.doc_strings
.iter();
1125 let ori
= iter
.next()?
;
1126 let mut out
= String
::new();
1127 add_doc_fragment(&mut out
, ori
);
1128 for new_frag
in iter
{
1129 add_doc_fragment(&mut out
, new_frag
);
1132 if out
.is_empty() { None }
else { Some(out) }
1135 /// Return the doc-comments on this item, grouped by the module they came from.
1137 /// The module can be different if this is a re-export with added documentation.
1138 crate fn collapsed_doc_value_by_module_level(&self) -> FxHashMap
<Option
<DefId
>, String
> {
1139 let mut ret
= FxHashMap
::default();
1140 if self.doc_strings
.len() == 0 {
1143 let last_index
= self.doc_strings
.len() - 1;
1145 for (i
, new_frag
) in self.doc_strings
.iter().enumerate() {
1146 let out
= ret
.entry(new_frag
.parent_module
).or_default();
1147 add_doc_fragment(out
, new_frag
);
1148 if i
== last_index
{
1155 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
1157 crate fn collapsed_doc_value(&self) -> Option
<String
> {
1158 if self.doc_strings
.is_empty() {
1161 Some(collapse_doc_fragments(&self.doc_strings
))
1165 crate fn get_doc_aliases(&self) -> Box
<[Symbol
]> {
1166 let mut aliases
= FxHashSet
::default();
1168 for attr
in self.other_attrs
.lists(sym
::doc
).filter(|a
| a
.has_name(sym
::alias
)) {
1169 if let Some(values
) = attr
.meta_item_list() {
1171 match l
.literal().unwrap().kind
{
1172 ast
::LitKind
::Str(s
, _
) => {
1175 _
=> unreachable
!(),
1179 aliases
.insert(attr
.value_str().unwrap());
1182 aliases
.into_iter().collect
::<Vec
<_
>>().into()
1186 impl PartialEq
for Attributes
{
1187 fn eq(&self, rhs
: &Self) -> bool
{
1188 self.doc_strings
== rhs
.doc_strings
1192 .map(|attr
| attr
.id
)
1193 .eq(rhs
.other_attrs
.iter().map(|attr
| attr
.id
))
1197 impl Eq
for Attributes {}
1199 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1200 crate enum GenericBound
{
1201 TraitBound(PolyTrait
, hir
::TraitBoundModifier
),
1206 crate fn maybe_sized(cx
: &mut DocContext
<'_
>) -> GenericBound
{
1207 let did
= cx
.tcx
.require_lang_item(LangItem
::Sized
, None
);
1208 let empty
= cx
.tcx
.intern_substs(&[]);
1209 let path
= external_path(cx
, did
, false, vec
![], empty
);
1210 inline
::record_extern_fqn(cx
, did
, ItemType
::Trait
);
1211 GenericBound
::TraitBound(
1212 PolyTrait { trait_: path, generic_params: Vec::new() }
,
1213 hir
::TraitBoundModifier
::Maybe
,
1217 crate fn is_sized_bound(&self, cx
: &DocContext
<'_
>) -> bool
{
1218 use rustc_hir
::TraitBoundModifier
as TBM
;
1219 if let GenericBound
::TraitBound(PolyTrait { ref trait_, .. }
, TBM
::None
) = *self {
1220 if Some(trait_
.def_id()) == cx
.tcx
.lang_items().sized_trait() {
1227 crate fn get_poly_trait(&self) -> Option
<PolyTrait
> {
1228 if let GenericBound
::TraitBound(ref p
, _
) = *self {
1229 return Some(p
.clone());
1234 crate fn get_trait_path(&self) -> Option
<Path
> {
1235 if let GenericBound
::TraitBound(PolyTrait { ref trait_, .. }
, _
) = *self {
1236 Some(trait_
.clone())
1243 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1244 crate struct Lifetime(pub Symbol
);
1247 crate fn statik() -> Lifetime
{
1248 Lifetime(kw
::StaticLifetime
)
1251 crate fn elided() -> Lifetime
{
1252 Lifetime(kw
::UnderscoreLifetime
)
1256 #[derive(Clone, Debug)]
1257 crate enum WherePredicate
{
1258 BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<Lifetime> }
,
1259 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> }
,
1260 EqPredicate { lhs: Type, rhs: Term }
,
1263 impl WherePredicate
{
1264 crate fn get_bounds(&self) -> Option
<&[GenericBound
]> {
1266 WherePredicate
::BoundPredicate { ref bounds, .. }
=> Some(bounds
),
1267 WherePredicate
::RegionPredicate { ref bounds, .. }
=> Some(bounds
),
1273 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1274 crate enum GenericParamDefKind
{
1275 Lifetime { outlives: Vec<Lifetime> }
,
1276 Type { did: DefId, bounds: Vec<GenericBound>, default: Option<Box<Type>>, synthetic: bool }
,
1277 Const { did: DefId, ty: Box<Type>, default: Option<Box<String>> }
,
1280 impl GenericParamDefKind
{
1281 crate fn is_type(&self) -> bool
{
1282 matches
!(self, GenericParamDefKind
::Type { .. }
)
1286 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1287 crate struct GenericParamDef
{
1289 crate kind
: GenericParamDefKind
,
1292 // `GenericParamDef` is used in many places. Make sure it doesn't unintentionally get bigger.
1293 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
1294 rustc_data_structures
::static_assert_size
!(GenericParamDef
, 56);
1296 impl GenericParamDef
{
1297 crate fn is_synthetic_type_param(&self) -> bool
{
1299 GenericParamDefKind
::Lifetime { .. }
| GenericParamDefKind
::Const { .. }
=> false,
1300 GenericParamDefKind
::Type { synthetic, .. }
=> synthetic
,
1304 crate fn is_type(&self) -> bool
{
1308 crate fn get_bounds(&self) -> Option
<&[GenericBound
]> {
1310 GenericParamDefKind
::Type { ref bounds, .. }
=> Some(bounds
),
1316 // maybe use a Generic enum and use Vec<Generic>?
1317 #[derive(Clone, Debug, Default)]
1318 crate struct Generics
{
1319 crate params
: Vec
<GenericParamDef
>,
1320 crate where_predicates
: Vec
<WherePredicate
>,
1323 #[derive(Clone, Debug)]
1324 crate struct Function
{
1326 crate generics
: Generics
,
1329 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1330 crate struct FnDecl
{
1331 crate inputs
: Arguments
,
1332 crate output
: FnRetTy
,
1333 crate c_variadic
: bool
,
1337 crate fn self_type(&self) -> Option
<SelfTy
> {
1338 self.inputs
.values
.get(0).and_then(|v
| v
.to_self())
1341 /// Returns the sugared return type for an async function.
1343 /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
1344 /// will return `i32`.
1348 /// This function will panic if the return type does not match the expected sugaring for async
1350 crate fn sugared_async_return_type(&self) -> FnRetTy
{
1351 match &self.output
{
1352 FnRetTy
::Return(Type
::ImplTrait(bounds
)) => match &bounds
[0] {
1353 GenericBound
::TraitBound(PolyTrait { trait_, .. }
, ..) => {
1354 let bindings
= trait_
.bindings().unwrap();
1355 let ret_ty
= bindings
[0].term();
1356 let ty
= ret_ty
.ty().expect("Unexpected constant return term");
1357 FnRetTy
::Return(ty
.clone())
1359 _
=> panic
!("unexpected desugaring of async function"),
1361 _
=> panic
!("unexpected desugaring of async function"),
1366 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1367 crate struct Arguments
{
1368 crate values
: Vec
<Argument
>,
1371 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1372 crate struct Argument
{
1375 /// This field is used to represent "const" arguments from the `rustc_legacy_const_generics`
1376 /// feature. More information in <https://github.com/rust-lang/rust/issues/83167>.
1377 crate is_const
: bool
,
1380 #[derive(Clone, PartialEq, Debug)]
1383 SelfBorrowed(Option
<Lifetime
>, Mutability
),
1388 crate fn to_self(&self) -> Option
<SelfTy
> {
1389 if self.name
!= kw
::SelfLower
{
1392 if self.type_
.is_self_type() {
1393 return Some(SelfValue
);
1396 BorrowedRef { ref lifetime, mutability, ref type_ }
if type_
.is_self_type() => {
1397 Some(SelfBorrowed(lifetime
.clone(), mutability
))
1399 _
=> Some(SelfExplicit(self.type_
.clone())),
1404 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1405 crate enum FnRetTy
{
1411 crate fn as_return(&self) -> Option
<&Type
> {
1413 Return(ret
) => Some(ret
),
1414 DefaultReturn
=> None
,
1419 #[derive(Clone, Debug)]
1420 crate struct Trait
{
1421 crate unsafety
: hir
::Unsafety
,
1422 crate items
: Vec
<Item
>,
1423 crate generics
: Generics
,
1424 crate bounds
: Vec
<GenericBound
>,
1425 crate is_auto
: bool
,
1428 #[derive(Clone, Debug)]
1429 crate struct TraitAlias
{
1430 crate generics
: Generics
,
1431 crate bounds
: Vec
<GenericBound
>,
1434 /// A trait reference, which may have higher ranked lifetimes.
1435 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1436 crate struct PolyTrait
{
1438 crate generic_params
: Vec
<GenericParamDef
>,
1441 /// Rustdoc's representation of types, mostly based on the [`hir::Ty`].
1442 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1444 /// A named type, which could be a trait.
1446 /// This is mostly Rustdoc's version of [`hir::Path`].
1447 /// It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics.
1448 Path { path: Path }
,
1449 /// A `dyn Trait` object: `dyn for<'a> Trait<'a> + Send + 'static`
1450 DynTrait(Vec
<PolyTrait
>, Option
<Lifetime
>),
1451 /// A type parameter.
1453 /// A primitive (aka, builtin) type.
1454 Primitive(PrimitiveType
),
1455 /// A function pointer: `extern "ABI" fn(...) -> ...`
1456 BareFunction(Box
<BareFunctionDecl
>),
1457 /// A tuple type: `(i32, &str)`.
1459 /// A slice type (does *not* include the `&`): `[i32]`
1463 /// The `String` field is a stringified version of the array's length parameter.
1464 Array(Box
<Type
>, String
),
1465 /// A raw pointer type: `*const i32`, `*mut i32`
1466 RawPointer(Mutability
, Box
<Type
>),
1467 /// A reference type: `&i32`, `&'a mut Foo`
1468 BorrowedRef { lifetime: Option<Lifetime>, mutability: Mutability, type_: Box<Type> }
,
1470 /// A qualified path to an associated item: `<Type as Trait>::Name`
1472 assoc
: Box
<PathSegment
>,
1473 self_type
: Box
<Type
>,
1474 /// FIXME: This is a hack that should be removed; see [this discussion][1].
1476 /// [1]: https://github.com/rust-lang/rust/pull/85479#discussion_r635729093
1477 self_def_id
: Option
<DefId
>,
1481 /// A type that is inferred: `_`
1484 /// An `impl Trait`: `impl TraitA + TraitB + ...`
1485 ImplTrait(Vec
<GenericBound
>),
1488 // `Type` is used a lot. Make sure it doesn't unintentionally get bigger.
1489 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
1490 rustc_data_structures
::static_assert_size
!(Type
, 80);
1493 /// When comparing types for equality, it can help to ignore `&` wrapping.
1494 crate fn without_borrowed_ref(&self) -> &Type
{
1495 let mut result
= self;
1496 while let Type
::BorrowedRef { type_, .. }
= result
{
1502 /// Check if two types are "potentially the same".
1503 /// This is different from `Eq`, because it knows that things like
1504 /// `Placeholder` are possible matches for everything.
1505 crate fn is_same(&self, other
: &Self, cache
: &Cache
) -> bool
{
1506 match (self, other
) {
1508 (Type
::Tuple(a
), Type
::Tuple(b
)) => {
1509 a
.len() == b
.len() && a
.iter().zip(b
).all(|(a
, b
)| a
.is_same(&b
, cache
))
1511 (Type
::Slice(a
), Type
::Slice(b
)) => a
.is_same(&b
, cache
),
1512 (Type
::Array(a
, al
), Type
::Array(b
, bl
)) => al
== bl
&& a
.is_same(&b
, cache
),
1513 (Type
::RawPointer(mutability
, type_
), Type
::RawPointer(b_mutability
, b_type_
)) => {
1514 mutability
== b_mutability
&& type_
.is_same(&b_type_
, cache
)
1517 Type
::BorrowedRef { mutability, type_, .. }
,
1518 Type
::BorrowedRef { mutability: b_mutability, type_: b_type_, .. }
,
1519 ) => mutability
== b_mutability
&& type_
.is_same(&b_type_
, cache
),
1520 // Placeholders and generics are equal to all other types.
1521 (Type
::Infer
, _
) | (_
, Type
::Infer
) => true,
1522 (Type
::Generic(_
), _
) | (_
, Type
::Generic(_
)) => true,
1523 // Other cases, such as primitives, just use recursion.
1526 .and_then(|a
| Some((a
, b
.def_id(cache
)?
)))
1527 .map(|(a
, b
)| a
== b
)
1532 crate fn primitive_type(&self) -> Option
<PrimitiveType
> {
1534 Primitive(p
) | BorrowedRef { type_: box Primitive(p), .. }
=> Some(p
),
1535 Slice(..) | BorrowedRef { type_: box Slice(..), .. }
=> Some(PrimitiveType
::Slice
),
1536 Array(..) | BorrowedRef { type_: box Array(..), .. }
=> Some(PrimitiveType
::Array
),
1539 Some(PrimitiveType
::Unit
)
1541 Some(PrimitiveType
::Tuple
)
1544 RawPointer(..) => Some(PrimitiveType
::RawPointer
),
1545 BareFunction(..) => Some(PrimitiveType
::Fn
),
1550 /// Checks if this is a `T::Name` path for an associated type.
1551 crate fn is_assoc_ty(&self) -> bool
{
1553 Type
::Path { path, .. }
=> path
.is_assoc_ty(),
1558 crate fn is_self_type(&self) -> bool
{
1560 Generic(name
) => name
== kw
::SelfUpper
,
1565 crate fn generics(&self) -> Option
<Vec
<&Type
>> {
1567 Type
::Path { path, .. }
=> path
.generics(),
1572 crate fn is_full_generic(&self) -> bool
{
1573 matches
!(self, Type
::Generic(_
))
1576 crate fn is_primitive(&self) -> bool
{
1577 self.primitive_type().is_some()
1580 crate fn projection(&self) -> Option
<(&Type
, DefId
, PathSegment
)> {
1581 if let QPath { self_type, trait_, assoc, .. }
= self {
1582 Some((&self_type
, trait_
.def_id(), *assoc
.clone()))
1588 fn inner_def_id(&self, cache
: Option
<&Cache
>) -> Option
<DefId
> {
1589 let t
: PrimitiveType
= match *self {
1590 Type
::Path { ref path }
=> return Some(path
.def_id()),
1591 DynTrait(ref bounds
, _
) => return Some(bounds
[0].trait_
.def_id()),
1592 Primitive(p
) => return cache
.and_then(|c
| c
.primitive_locations
.get(&p
).cloned()),
1593 BorrowedRef { type_: box Generic(..), .. }
=> PrimitiveType
::Reference
,
1594 BorrowedRef { ref type_, .. }
=> return type_
.inner_def_id(cache
),
1599 PrimitiveType
::Tuple
1602 BareFunction(..) => PrimitiveType
::Fn
,
1603 Slice(..) => PrimitiveType
::Slice
,
1604 Array(..) => PrimitiveType
::Array
,
1605 RawPointer(..) => PrimitiveType
::RawPointer
,
1606 QPath { ref self_type, .. }
=> return self_type
.inner_def_id(cache
),
1607 Generic(_
) | Infer
| ImplTrait(_
) => return None
,
1609 cache
.and_then(|c
| Primitive(t
).def_id(c
))
1612 /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s.
1614 /// [clean]: crate::clean
1615 crate fn def_id(&self, cache
: &Cache
) -> Option
<DefId
> {
1616 self.inner_def_id(Some(cache
))
1620 /// A primitive (aka, builtin) type.
1622 /// This represents things like `i32`, `str`, etc.
1624 /// N.B. This has to be different from [`hir::PrimTy`] because it also includes types that aren't
1625 /// paths, like [`Self::Unit`].
1626 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1627 crate enum PrimitiveType
{
1655 type SimplifiedTypes
= FxHashMap
<PrimitiveType
, ArrayVec
<SimplifiedType
, 2>>;
1656 impl PrimitiveType
{
1657 crate fn from_hir(prim
: hir
::PrimTy
) -> PrimitiveType
{
1658 use ast
::{FloatTy, IntTy, UintTy}
;
1660 hir
::PrimTy
::Int(IntTy
::Isize
) => PrimitiveType
::Isize
,
1661 hir
::PrimTy
::Int(IntTy
::I8
) => PrimitiveType
::I8
,
1662 hir
::PrimTy
::Int(IntTy
::I16
) => PrimitiveType
::I16
,
1663 hir
::PrimTy
::Int(IntTy
::I32
) => PrimitiveType
::I32
,
1664 hir
::PrimTy
::Int(IntTy
::I64
) => PrimitiveType
::I64
,
1665 hir
::PrimTy
::Int(IntTy
::I128
) => PrimitiveType
::I128
,
1666 hir
::PrimTy
::Uint(UintTy
::Usize
) => PrimitiveType
::Usize
,
1667 hir
::PrimTy
::Uint(UintTy
::U8
) => PrimitiveType
::U8
,
1668 hir
::PrimTy
::Uint(UintTy
::U16
) => PrimitiveType
::U16
,
1669 hir
::PrimTy
::Uint(UintTy
::U32
) => PrimitiveType
::U32
,
1670 hir
::PrimTy
::Uint(UintTy
::U64
) => PrimitiveType
::U64
,
1671 hir
::PrimTy
::Uint(UintTy
::U128
) => PrimitiveType
::U128
,
1672 hir
::PrimTy
::Float(FloatTy
::F32
) => PrimitiveType
::F32
,
1673 hir
::PrimTy
::Float(FloatTy
::F64
) => PrimitiveType
::F64
,
1674 hir
::PrimTy
::Str
=> PrimitiveType
::Str
,
1675 hir
::PrimTy
::Bool
=> PrimitiveType
::Bool
,
1676 hir
::PrimTy
::Char
=> PrimitiveType
::Char
,
1680 crate fn from_symbol(s
: Symbol
) -> Option
<PrimitiveType
> {
1682 sym
::isize => Some(PrimitiveType
::Isize
),
1683 sym
::i8 => Some(PrimitiveType
::I8
),
1684 sym
::i16 => Some(PrimitiveType
::I16
),
1685 sym
::i32 => Some(PrimitiveType
::I32
),
1686 sym
::i64 => Some(PrimitiveType
::I64
),
1687 sym
::i128
=> Some(PrimitiveType
::I128
),
1688 sym
::usize => Some(PrimitiveType
::Usize
),
1689 sym
::u8 => Some(PrimitiveType
::U8
),
1690 sym
::u16 => Some(PrimitiveType
::U16
),
1691 sym
::u32 => Some(PrimitiveType
::U32
),
1692 sym
::u64 => Some(PrimitiveType
::U64
),
1693 sym
::u128
=> Some(PrimitiveType
::U128
),
1694 sym
::bool
=> Some(PrimitiveType
::Bool
),
1695 sym
::char => Some(PrimitiveType
::Char
),
1696 sym
::str => Some(PrimitiveType
::Str
),
1697 sym
::f32 => Some(PrimitiveType
::F32
),
1698 sym
::f64 => Some(PrimitiveType
::F64
),
1699 sym
::array
=> Some(PrimitiveType
::Array
),
1700 sym
::slice
=> Some(PrimitiveType
::Slice
),
1701 sym
::tuple
=> Some(PrimitiveType
::Tuple
),
1702 sym
::unit
=> Some(PrimitiveType
::Unit
),
1703 sym
::pointer
=> Some(PrimitiveType
::RawPointer
),
1704 sym
::reference
=> Some(PrimitiveType
::Reference
),
1705 kw
::Fn
=> Some(PrimitiveType
::Fn
),
1706 sym
::never
=> Some(PrimitiveType
::Never
),
1711 crate fn simplified_types() -> &'
static SimplifiedTypes
{
1712 use ty
::fast_reject
::SimplifiedTypeGen
::*;
1713 use ty
::{FloatTy, IntTy, UintTy}
;
1714 use PrimitiveType
::*;
1715 static CELL
: OnceCell
<SimplifiedTypes
> = OnceCell
::new();
1717 let single
= |x
| iter
::once(x
).collect();
1718 CELL
.get_or_init(move || {
1720 Isize
=> single(IntSimplifiedType(IntTy
::Isize
)),
1721 I8
=> single(IntSimplifiedType(IntTy
::I8
)),
1722 I16
=> single(IntSimplifiedType(IntTy
::I16
)),
1723 I32
=> single(IntSimplifiedType(IntTy
::I32
)),
1724 I64
=> single(IntSimplifiedType(IntTy
::I64
)),
1725 I128
=> single(IntSimplifiedType(IntTy
::I128
)),
1726 Usize
=> single(UintSimplifiedType(UintTy
::Usize
)),
1727 U8
=> single(UintSimplifiedType(UintTy
::U8
)),
1728 U16
=> single(UintSimplifiedType(UintTy
::U16
)),
1729 U32
=> single(UintSimplifiedType(UintTy
::U32
)),
1730 U64
=> single(UintSimplifiedType(UintTy
::U64
)),
1731 U128
=> single(UintSimplifiedType(UintTy
::U128
)),
1732 F32
=> single(FloatSimplifiedType(FloatTy
::F32
)),
1733 F64
=> single(FloatSimplifiedType(FloatTy
::F64
)),
1734 Str
=> single(StrSimplifiedType
),
1735 Bool
=> single(BoolSimplifiedType
),
1736 Char
=> single(CharSimplifiedType
),
1737 Array
=> single(ArraySimplifiedType
),
1738 Slice
=> single(SliceSimplifiedType
),
1739 // FIXME: If we ever add an inherent impl for tuples
1740 // with different lengths, they won't show in rustdoc.
1742 // Either manually update this arrayvec at this point
1743 // or start with a more complex refactoring.
1744 Tuple
=> [TupleSimplifiedType(2), TupleSimplifiedType(3)].into(),
1745 Unit
=> single(TupleSimplifiedType(0)),
1746 RawPointer
=> [PtrSimplifiedType(Mutability
::Not
), PtrSimplifiedType(Mutability
::Mut
)].into(),
1747 Reference
=> [RefSimplifiedType(Mutability
::Not
), RefSimplifiedType(Mutability
::Mut
)].into(),
1748 // FIXME: This will be wrong if we ever add inherent impls
1749 // for function pointers.
1750 Fn
=> ArrayVec
::new(),
1751 Never
=> single(NeverSimplifiedType
),
1756 crate fn impls
<'tcx
>(&self, tcx
: TyCtxt
<'tcx
>) -> impl Iterator
<Item
= DefId
> + 'tcx
{
1757 Self::simplified_types()
1761 .flat_map(move |&simp
| tcx
.incoherent_impls(simp
))
1765 crate fn all_impls(tcx
: TyCtxt
<'_
>) -> impl Iterator
<Item
= DefId
> + '_
{
1766 Self::simplified_types()
1769 .flat_map(move |&simp
| tcx
.incoherent_impls(simp
))
1773 crate fn as_sym(&self) -> Symbol
{
1774 use PrimitiveType
::*;
1776 Isize
=> sym
::isize,
1782 Usize
=> sym
::usize,
1793 Array
=> sym
::array
,
1794 Slice
=> sym
::slice
,
1795 Tuple
=> sym
::tuple
,
1797 RawPointer
=> sym
::pointer
,
1798 Reference
=> sym
::reference
,
1800 Never
=> sym
::never
,
1804 /// Returns the DefId of the module with `doc(primitive)` for this primitive type.
1805 /// Panics if there is no such module.
1807 /// This gives precedence to primitives defined in the current crate, and deprioritizes primitives defined in `core`,
1808 /// but otherwise, if multiple crates define the same primitive, there is no guarantee of which will be picked.
1809 /// In particular, if a crate depends on both `std` and another crate that also defines `doc(primitive)`, then
1810 /// it's entirely random whether `std` or the other crate is picked. (no_std crates are usually fine unless multiple dependencies define a primitive.)
1811 crate fn primitive_locations(tcx
: TyCtxt
<'_
>) -> &FxHashMap
<PrimitiveType
, DefId
> {
1812 static PRIMITIVE_LOCATIONS
: OnceCell
<FxHashMap
<PrimitiveType
, DefId
>> = OnceCell
::new();
1813 PRIMITIVE_LOCATIONS
.get_or_init(|| {
1814 let mut primitive_locations
= FxHashMap
::default();
1815 // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate.
1816 // This is a degenerate case that I don't plan to support.
1817 for &crate_num
in tcx
.crates(()) {
1818 let e
= ExternalCrate { crate_num }
;
1819 let crate_name
= e
.name(tcx
);
1820 debug
!(?crate_num
, ?crate_name
);
1821 for &(def_id
, prim
) in &e
.primitives(tcx
) {
1822 // HACK: try to link to std instead where possible
1823 if crate_name
== sym
::core
&& primitive_locations
.contains_key(&prim
) {
1826 primitive_locations
.insert(prim
, def_id
);
1829 let local_primitives
= ExternalCrate { crate_num: LOCAL_CRATE }
.primitives(tcx
);
1830 for (def_id
, prim
) in local_primitives
{
1831 primitive_locations
.insert(prim
, def_id
);
1838 impl From
<ast
::IntTy
> for PrimitiveType
{
1839 fn from(int_ty
: ast
::IntTy
) -> PrimitiveType
{
1841 ast
::IntTy
::Isize
=> PrimitiveType
::Isize
,
1842 ast
::IntTy
::I8
=> PrimitiveType
::I8
,
1843 ast
::IntTy
::I16
=> PrimitiveType
::I16
,
1844 ast
::IntTy
::I32
=> PrimitiveType
::I32
,
1845 ast
::IntTy
::I64
=> PrimitiveType
::I64
,
1846 ast
::IntTy
::I128
=> PrimitiveType
::I128
,
1851 impl From
<ast
::UintTy
> for PrimitiveType
{
1852 fn from(uint_ty
: ast
::UintTy
) -> PrimitiveType
{
1854 ast
::UintTy
::Usize
=> PrimitiveType
::Usize
,
1855 ast
::UintTy
::U8
=> PrimitiveType
::U8
,
1856 ast
::UintTy
::U16
=> PrimitiveType
::U16
,
1857 ast
::UintTy
::U32
=> PrimitiveType
::U32
,
1858 ast
::UintTy
::U64
=> PrimitiveType
::U64
,
1859 ast
::UintTy
::U128
=> PrimitiveType
::U128
,
1864 impl From
<ast
::FloatTy
> for PrimitiveType
{
1865 fn from(float_ty
: ast
::FloatTy
) -> PrimitiveType
{
1867 ast
::FloatTy
::F32
=> PrimitiveType
::F32
,
1868 ast
::FloatTy
::F64
=> PrimitiveType
::F64
,
1873 impl From
<ty
::IntTy
> for PrimitiveType
{
1874 fn from(int_ty
: ty
::IntTy
) -> PrimitiveType
{
1876 ty
::IntTy
::Isize
=> PrimitiveType
::Isize
,
1877 ty
::IntTy
::I8
=> PrimitiveType
::I8
,
1878 ty
::IntTy
::I16
=> PrimitiveType
::I16
,
1879 ty
::IntTy
::I32
=> PrimitiveType
::I32
,
1880 ty
::IntTy
::I64
=> PrimitiveType
::I64
,
1881 ty
::IntTy
::I128
=> PrimitiveType
::I128
,
1886 impl From
<ty
::UintTy
> for PrimitiveType
{
1887 fn from(uint_ty
: ty
::UintTy
) -> PrimitiveType
{
1889 ty
::UintTy
::Usize
=> PrimitiveType
::Usize
,
1890 ty
::UintTy
::U8
=> PrimitiveType
::U8
,
1891 ty
::UintTy
::U16
=> PrimitiveType
::U16
,
1892 ty
::UintTy
::U32
=> PrimitiveType
::U32
,
1893 ty
::UintTy
::U64
=> PrimitiveType
::U64
,
1894 ty
::UintTy
::U128
=> PrimitiveType
::U128
,
1899 impl From
<ty
::FloatTy
> for PrimitiveType
{
1900 fn from(float_ty
: ty
::FloatTy
) -> PrimitiveType
{
1902 ty
::FloatTy
::F32
=> PrimitiveType
::F32
,
1903 ty
::FloatTy
::F64
=> PrimitiveType
::F64
,
1908 impl From
<hir
::PrimTy
> for PrimitiveType
{
1909 fn from(prim_ty
: hir
::PrimTy
) -> PrimitiveType
{
1911 hir
::PrimTy
::Int(int_ty
) => int_ty
.into(),
1912 hir
::PrimTy
::Uint(uint_ty
) => uint_ty
.into(),
1913 hir
::PrimTy
::Float(float_ty
) => float_ty
.into(),
1914 hir
::PrimTy
::Str
=> PrimitiveType
::Str
,
1915 hir
::PrimTy
::Bool
=> PrimitiveType
::Bool
,
1916 hir
::PrimTy
::Char
=> PrimitiveType
::Char
,
1921 #[derive(Copy, Clone, Debug)]
1922 crate enum Visibility
{
1925 /// Visibility inherited from parent.
1927 /// For example, this is the visibility of private items and of enum variants.
1929 /// `pub(crate)`, `pub(super)`, or `pub(in path::to::somewhere)`
1934 crate fn is_public(&self) -> bool
{
1935 matches
!(self, Visibility
::Public
)
1939 #[derive(Clone, Debug)]
1940 crate struct Struct
{
1941 crate struct_type
: CtorKind
,
1942 crate generics
: Generics
,
1943 crate fields
: Vec
<Item
>,
1944 crate fields_stripped
: bool
,
1947 #[derive(Clone, Debug)]
1948 crate struct Union
{
1949 crate generics
: Generics
,
1950 crate fields
: Vec
<Item
>,
1951 crate fields_stripped
: bool
,
1954 /// This is a more limited form of the standard Struct, different in that
1955 /// it lacks the things most items have (name, id, parameterization). Found
1956 /// only as a variant in an enum.
1957 #[derive(Clone, Debug)]
1958 crate struct VariantStruct
{
1959 crate struct_type
: CtorKind
,
1960 crate fields
: Vec
<Item
>,
1961 crate fields_stripped
: bool
,
1964 #[derive(Clone, Debug)]
1966 crate variants
: IndexVec
<VariantIdx
, Item
>,
1967 crate generics
: Generics
,
1968 crate variants_stripped
: bool
,
1971 #[derive(Clone, Debug)]
1972 crate enum Variant
{
1975 Struct(VariantStruct
),
1978 /// Small wrapper around [`rustc_span::Span`] that adds helper methods
1979 /// and enforces calling [`rustc_span::Span::source_callsite()`].
1980 #[derive(Copy, Clone, Debug)]
1981 crate struct Span(rustc_span
::Span
);
1984 /// Wraps a [`rustc_span::Span`]. In case this span is the result of a macro expansion, the
1985 /// span will be updated to point to the macro invocation instead of the macro definition.
1987 /// (See rust-lang/rust#39726)
1988 crate fn new(sp
: rustc_span
::Span
) -> Self {
1989 Self(sp
.source_callsite())
1992 crate fn inner(&self) -> rustc_span
::Span
{
1996 crate fn dummy() -> Self {
1997 Self(rustc_span
::DUMMY_SP
)
2000 crate fn is_dummy(&self) -> bool
{
2004 crate fn filename(&self, sess
: &Session
) -> FileName
{
2005 sess
.source_map().span_to_filename(self.0)
2008 crate fn lo(&self, sess
: &Session
) -> Loc
{
2009 sess
.source_map().lookup_char_pos(self.0.lo())
2012 crate fn hi(&self, sess
: &Session
) -> Loc
{
2013 sess
.source_map().lookup_char_pos(self.0.hi())
2016 crate fn cnum(&self, sess
: &Session
) -> CrateNum
{
2017 // FIXME: is there a time when the lo and hi crate would be different?
2018 self.lo(sess
).file
.cnum
2022 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2025 crate segments
: Vec
<PathSegment
>,
2029 crate fn def_id(&self) -> DefId
{
2033 crate fn last(&self) -> Symbol
{
2034 self.segments
.last().expect("segments were empty").name
2037 crate fn whole_name(&self) -> String
{
2040 .map(|s
| if s
.name
== kw
::PathRoot { String::new() }
else { s.name.to_string() }
)
2041 .intersperse("::".into())
2045 /// Checks if this is a `T::Name` path for an associated type.
2046 crate fn is_assoc_ty(&self) -> bool
{
2048 Res
::SelfTy { .. }
if self.segments
.len() != 1 => true,
2049 Res
::Def(DefKind
::TyParam
, _
) if self.segments
.len() != 1 => true,
2050 Res
::Def(DefKind
::AssocTy
, _
) => true,
2055 crate fn generics(&self) -> Option
<Vec
<&Type
>> {
2056 self.segments
.last().and_then(|seg
| {
2057 if let GenericArgs
::AngleBracketed { ref args, .. }
= seg
.args
{
2060 .filter_map(|arg
| match arg
{
2061 GenericArg
::Type(ty
) => Some(ty
),
2072 crate fn bindings(&self) -> Option
<&[TypeBinding
]> {
2073 self.segments
.last().and_then(|seg
| {
2074 if let GenericArgs
::AngleBracketed { ref bindings, .. }
= seg
.args
{
2083 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2084 crate enum GenericArg
{
2087 Const(Box
<Constant
>),
2091 // `GenericArg` can occur many times in a single `Path`, so make sure it
2092 // doesn't increase in size unexpectedly.
2093 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2094 rustc_data_structures
::static_assert_size
!(GenericArg
, 88);
2096 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2097 crate enum GenericArgs
{
2098 AngleBracketed { args: Vec<GenericArg>, bindings: ThinVec<TypeBinding> }
,
2099 Parenthesized { inputs: Vec<Type>, output: Option<Box<Type>> }
,
2102 // `GenericArgs` is in every `PathSegment`, so its size can significantly
2103 // affect rustdoc's memory usage.
2104 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2105 rustc_data_structures
::static_assert_size
!(GenericArgs
, 40);
2107 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2108 crate struct PathSegment
{
2110 crate args
: GenericArgs
,
2113 // `PathSegment` usually occurs multiple times in every `Path`, so its size can
2114 // significantly affect rustdoc's memory usage.
2115 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2116 rustc_data_structures
::static_assert_size
!(PathSegment
, 48);
2118 #[derive(Clone, Debug)]
2119 crate struct Typedef
{
2121 crate generics
: Generics
,
2122 /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
2123 /// alias instead of the final type. This will always have the final type, regardless of whether
2124 /// `type_` came from HIR or from metadata.
2126 /// If `item_type.is_none()`, `type_` is guaranteed to come from metadata (and therefore hold the
2128 crate item_type
: Option
<Type
>,
2131 #[derive(Clone, Debug)]
2132 crate struct OpaqueTy
{
2133 crate bounds
: Vec
<GenericBound
>,
2134 crate generics
: Generics
,
2137 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2138 crate struct BareFunctionDecl
{
2139 crate unsafety
: hir
::Unsafety
,
2140 crate generic_params
: Vec
<GenericParamDef
>,
2145 #[derive(Clone, Debug)]
2146 crate struct Static
{
2148 crate mutability
: Mutability
,
2149 crate expr
: Option
<BodyId
>,
2152 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2153 crate struct Constant
{
2155 crate kind
: ConstantKind
,
2158 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2165 crate fn ty(&self) -> Option
<&Type
> {
2166 if let Term
::Type(ty
) = self { Some(ty) }
else { None }
2170 impl From
<Type
> for Term
{
2171 fn from(ty
: Type
) -> Self {
2176 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2177 crate enum ConstantKind
{
2178 /// This is the wrapper around `ty::Const` for a non-local constant. Because it doesn't have a
2179 /// `BodyId`, we need to handle it on its own.
2181 /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified
2182 /// by a DefId. So this field must be different from `Extern`.
2183 TyConst { expr: String }
,
2184 /// A constant (expression) that's not an item or associated item. These are usually found
2185 /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
2186 /// used to define explicit discriminant values for enum variants.
2187 Anonymous { body: BodyId }
,
2188 /// A constant from a different crate.
2189 Extern { def_id: DefId }
,
2190 /// `const FOO: u32 = ...;`
2191 Local { def_id: DefId, body: BodyId }
,
2195 crate fn expr(&self, tcx
: TyCtxt
<'_
>) -> String
{
2199 crate fn value(&self, tcx
: TyCtxt
<'_
>) -> Option
<String
> {
2200 self.kind
.value(tcx
)
2203 crate fn is_literal(&self, tcx
: TyCtxt
<'_
>) -> bool
{
2204 self.kind
.is_literal(tcx
)
2209 crate fn expr(&self, tcx
: TyCtxt
<'_
>) -> String
{
2211 ConstantKind
::TyConst { ref expr }
=> expr
.clone(),
2212 ConstantKind
::Extern { def_id }
=> print_inlined_const(tcx
, def_id
),
2213 ConstantKind
::Local { body, .. }
| ConstantKind
::Anonymous { body }
=> {
2214 print_const_expr(tcx
, body
)
2219 crate fn value(&self, tcx
: TyCtxt
<'_
>) -> Option
<String
> {
2221 ConstantKind
::TyConst { .. }
| ConstantKind
::Anonymous { .. }
=> None
,
2222 ConstantKind
::Extern { def_id }
| ConstantKind
::Local { def_id, .. }
=> {
2223 print_evaluated_const(tcx
, def_id
)
2228 crate fn is_literal(&self, tcx
: TyCtxt
<'_
>) -> bool
{
2230 ConstantKind
::TyConst { .. }
=> false,
2231 ConstantKind
::Extern { def_id }
=> def_id
.as_local().map_or(false, |def_id
| {
2232 is_literal_expr(tcx
, tcx
.hir().local_def_id_to_hir_id(def_id
))
2234 ConstantKind
::Local { body, .. }
| ConstantKind
::Anonymous { body }
=> {
2235 is_literal_expr(tcx
, body
.hir_id
)
2241 #[derive(Clone, Debug)]
2243 crate unsafety
: hir
::Unsafety
,
2244 crate generics
: Generics
,
2245 crate trait_
: Option
<Path
>,
2247 crate items
: Vec
<Item
>,
2248 crate polarity
: ty
::ImplPolarity
,
2249 crate kind
: ImplKind
,
2253 crate fn provided_trait_methods(&self, tcx
: TyCtxt
<'_
>) -> FxHashSet
<Symbol
> {
2256 .map(|t
| t
.def_id())
2257 .map(|did
| tcx
.provided_trait_methods(did
).map(|meth
| meth
.name
).collect())
2258 .unwrap_or_default()
2262 #[derive(Clone, Debug)]
2263 crate enum ImplKind
{
2270 crate fn is_auto(&self) -> bool
{
2271 matches
!(self, ImplKind
::Auto
)
2274 crate fn is_blanket(&self) -> bool
{
2275 matches
!(self, ImplKind
::Blanket(_
))
2278 crate fn as_blanket_ty(&self) -> Option
<&Type
> {
2280 ImplKind
::Blanket(ty
) => Some(ty
),
2286 #[derive(Clone, Debug)]
2287 crate struct Import
{
2288 crate kind
: ImportKind
,
2289 crate source
: ImportSource
,
2290 crate should_be_displayed
: bool
,
2294 crate fn new_simple(name
: Symbol
, source
: ImportSource
, should_be_displayed
: bool
) -> Self {
2295 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2298 crate fn new_glob(source
: ImportSource
, should_be_displayed
: bool
) -> Self {
2299 Self { kind: ImportKind::Glob, source, should_be_displayed }
2303 #[derive(Clone, Debug)]
2304 crate enum ImportKind
{
2305 // use source as str;
2311 #[derive(Clone, Debug)]
2312 crate struct ImportSource
{
2314 crate did
: Option
<DefId
>,
2317 #[derive(Clone, Debug)]
2318 crate struct Macro
{
2319 crate source
: String
,
2322 #[derive(Clone, Debug)]
2323 crate struct ProcMacro
{
2324 crate kind
: MacroKind
,
2325 crate helpers
: Vec
<Symbol
>,
2328 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
2329 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
2330 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2331 crate struct TypeBinding
{
2332 crate assoc
: PathSegment
,
2333 crate kind
: TypeBindingKind
,
2336 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2337 crate enum TypeBindingKind
{
2338 Equality { term: Term }
,
2339 Constraint { bounds: Vec<GenericBound> }
,
2343 crate fn term(&self) -> &Term
{
2345 TypeBindingKind
::Equality { ref term }
=> term
,
2346 _
=> panic
!("expected equality type binding for parenthesized generic args"),
2351 /// The type, lifetime, or constant that a private type alias's parameter should be
2352 /// replaced with when expanding a use of that type alias.
2357 /// type PrivAlias<T> = Vec<T>;
2359 /// pub fn public_fn() -> PrivAlias<i32> { vec![] }
2362 /// `public_fn`'s docs will show it as returning `Vec<i32>`, since `PrivAlias` is private.
2363 /// [`SubstParam`] is used to record that `T` should be mapped to `i32`.
2364 crate enum SubstParam
{
2371 crate fn as_ty(&self) -> Option
<&Type
> {
2372 if let Self::Type(ty
) = self { Some(ty) }
else { None }
2375 crate fn as_lt(&self) -> Option
<&Lifetime
> {
2376 if let Self::Lifetime(lt
) = self { Some(lt) }
else { None }