1use std::fmt::Write;
2use std::hash::Hash;
3use std::path::PathBuf;
4use std::sync::{Arc, OnceLock as OnceCell};
5use std::{fmt, iter};
6
7use arrayvec::ArrayVec;
8use itertools::Either;
9use rustc_abi::{ExternAbi, VariantIdx};
10use rustc_ast as ast;
11use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
12use rustc_data_structures::thin_vec::ThinVec;
13use rustc_hir as hir;
14use rustc_hir::attrs::lang_items::LangItem;
15use rustc_hir::attrs::{AttributeKind, DeprecatedSince, Deprecation, DocAttribute};
16use rustc_hir::def::{CtorKind, DefKind, MacroKinds, Res};
17use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
18use rustc_hir::{Attribute, BodyId, ConstStability, Mutability, Stability, StableSince, find_attr};
19use rustc_index::IndexVec;
20use rustc_metadata::rendered_const;
21use rustc_middle::ty::fast_reject::SimplifiedType;
22use rustc_middle::ty::{self, Ty, TyCtxt, Visibility};
23use rustc_resolve::rustdoc::{
24 DocFragment, add_doc_fragment, attrs_to_doc_fragments, inner_docs, span_of_fragments,
25};
26use rustc_session::Session;
27use rustc_span::def_id::{CRATE_DEF_ID, ModId};
28use rustc_span::hygiene::MacroKind;
29use rustc_span::symbol::{Symbol, kw, sym};
30use rustc_span::{DUMMY_SP, FileName, Ident, Loc, RemapPathScopeComponents, span_bug};
31use tracing::{debug, trace};
32
33pub(crate) use self::ItemKind::*;
34pub(crate) use self::Type::{
35 Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath,
36 RawPointer, SelfTy, Slice, Tuple, UnsafeBinder,
37};
38use crate::clean::cfg::Cfg;
39use crate::clean::clean_middle_path;
40use crate::clean::inline::{self, print_inlined_const};
41use crate::clean::utils::{is_literal_expr, print_evaluated_const};
42use crate::core::DocContext;
43use crate::formats::cache::Cache;
44use crate::formats::item_type::ItemType;
45use crate::html::format::HrefInfo;
46use crate::html::render::Context;
47use crate::passes::collect_intra_doc_links::UrlFragment;
48
49#[cfg(test)]
50mod tests;
51
52pub(crate) type ItemIdSet = FxHashSet<ItemId>;
53
54#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
55pub(crate) enum ItemId {
56 DefId(DefId),
58 Auto { trait_: DefId, for_: DefId },
60 Blanket { impl_id: DefId, for_: DefId },
62}
63
64#[derive(Debug, Copy, Clone, PartialEq, Eq)]
65pub(crate) enum Defaultness {
66 Implicit,
67 Default,
68 Final,
69}
70
71impl Defaultness {
72 pub(crate) fn from_trait_item(defaultness: hir::Defaultness) -> Self {
73 match defaultness {
74 hir::Defaultness::Default { .. } => Self::Implicit,
75 hir::Defaultness::Final => Self::Final,
76 }
77 }
78
79 pub(crate) fn from_impl_item(defaultness: hir::Defaultness) -> Self {
80 match defaultness {
81 hir::Defaultness::Default { .. } => Self::Default,
82 hir::Defaultness::Final => Self::Implicit,
83 }
84 }
85}
86
87impl ItemId {
88 #[inline]
89 pub(crate) fn is_local(self) -> bool {
90 match self {
91 ItemId::Auto { for_: id, .. }
92 | ItemId::Blanket { for_: id, .. }
93 | ItemId::DefId(id) => id.is_local(),
94 }
95 }
96
97 #[inline]
98 #[track_caller]
99 pub(crate) fn expect_def_id(self) -> DefId {
100 self.as_def_id()
101 .unwrap_or_else(|| panic!("ItemId::expect_def_id: `{self:?}` isn't a DefId"))
102 }
103
104 #[inline]
105 pub(crate) fn as_def_id(self) -> Option<DefId> {
106 match self {
107 ItemId::DefId(id) => Some(id),
108 _ => None,
109 }
110 }
111
112 #[inline]
113 pub(crate) fn as_local_def_id(self) -> Option<LocalDefId> {
114 self.as_def_id().and_then(|id| id.as_local())
115 }
116
117 #[inline]
118 pub(crate) fn krate(self) -> CrateNum {
119 match self {
120 ItemId::Auto { for_: id, .. }
121 | ItemId::Blanket { for_: id, .. }
122 | ItemId::DefId(id) => id.krate,
123 }
124 }
125}
126
127impl From<DefId> for ItemId {
128 fn from(id: DefId) -> Self {
129 Self::DefId(id)
130 }
131}
132
133#[derive(Debug)]
135pub(crate) struct Crate {
136 pub(crate) module: Item,
137 pub(crate) external_traits: Box<FxIndexMap<DefId, Trait>>,
139}
140
141impl Crate {
142 pub(crate) fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
143 ExternalCrate::LOCAL.name(tcx)
144 }
145
146 pub(crate) fn src(&self, tcx: TyCtxt<'_>) -> FileName {
147 ExternalCrate::LOCAL.src(tcx)
148 }
149}
150
151#[derive(Copy, Clone, Debug)]
152pub(crate) struct ExternalCrate {
153 pub(crate) crate_num: CrateNum,
154}
155
156impl ExternalCrate {
157 const LOCAL: Self = Self { crate_num: LOCAL_CRATE };
158
159 #[inline]
160 pub(crate) fn def_id(&self) -> DefId {
161 self.crate_num.as_def_id()
162 }
163
164 pub(crate) fn src(&self, tcx: TyCtxt<'_>) -> FileName {
165 let krate_span = tcx.def_span(self.def_id());
166 tcx.sess.source_map().span_to_filename(krate_span)
167 }
168
169 pub(crate) fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
170 tcx.crate_name(self.crate_num)
171 }
172
173 pub(crate) fn src_root(&self, tcx: TyCtxt<'_>) -> PathBuf {
174 match self.src(tcx) {
175 FileName::Real(ref p) => {
176 match p
177 .local_path()
178 .or(Some(p.path(RemapPathScopeComponents::DOCUMENTATION)))
179 .unwrap()
180 .parent()
181 {
182 Some(p) => p.to_path_buf(),
183 None => PathBuf::new(),
184 }
185 }
186 _ => PathBuf::new(),
187 }
188 }
189
190 pub(crate) fn location(
193 &self,
194 extern_url: Option<&str>,
195 extern_url_takes_precedence: bool,
196 dst: &std::path::Path,
197 tcx: TyCtxt<'_>,
198 ) -> ExternalLocation {
199 use ExternalLocation::*;
200
201 fn to_remote(url: impl ToString) -> ExternalLocation {
202 let mut url = url.to_string();
203 if !url.ends_with('/') {
204 url.push('/');
205 }
206 let is_absolute = url.starts_with('/')
207 || url.split_once(':').is_some_and(|(scheme, _)| {
208 scheme.bytes().next().is_some_and(|b| b.is_ascii_alphabetic())
209 && scheme
210 .bytes()
211 .all(|b| b.is_ascii_alphanumeric() || matches!(b, b'+' | b'-' | b'.'))
212 });
213 Remote { url, is_absolute }
214 }
215
216 let local_location = dst.join(self.name(tcx).as_str());
220 if local_location.is_dir() {
221 return Local;
222 }
223
224 if extern_url_takes_precedence && let Some(url) = extern_url {
225 return to_remote(url);
226 }
227
228 let did = self.crate_num.as_def_id();
231 find_attr!(tcx, did, Doc(d) =>d.html_root_url.map(|(url, _)| url))
232 .flatten()
233 .map(to_remote)
234 .or_else(|| extern_url.map(to_remote)) .unwrap_or(Unknown) }
237
238 fn fake_doc_items<T>(
239 &self,
240 tcx: TyCtxt<'_>,
241 f: impl Fn(DefId, TyCtxt<'_>) -> Option<(DefId, T)>,
242 ) -> impl Iterator<Item = (DefId, T)> {
243 tcx.fake_doc_items(self.crate_num).into_iter().filter_map(move |did| f(*did, tcx))
244 }
245
246 pub(crate) fn keywords(&self, tcx: TyCtxt<'_>) -> impl Iterator<Item = (DefId, Symbol)> {
247 self.retrieve_keywords_or_documented_attributes(tcx, |d| d.keyword.map(|(v, _)| v))
248 }
249 pub(crate) fn documented_attributes(
250 &self,
251 tcx: TyCtxt<'_>,
252 ) -> impl Iterator<Item = (DefId, Symbol)> {
253 self.retrieve_keywords_or_documented_attributes(tcx, |d| d.attribute.map(|(v, _)| v))
254 }
255
256 fn retrieve_keywords_or_documented_attributes<F: Fn(&DocAttribute) -> Option<Symbol>>(
257 &self,
258 tcx: TyCtxt<'_>,
259 callback: F,
260 ) -> impl Iterator<Item = (DefId, Symbol)> {
261 let as_target = move |did: DefId, tcx: TyCtxt<'_>| -> Option<(DefId, Symbol)> {
262 find_attr!(tcx, did, Doc(d) => callback(d)).flatten().map(|value| (did, value))
263 };
264 self.fake_doc_items(tcx, as_target)
265 }
266
267 pub(crate) fn primitives(
268 &self,
269 tcx: TyCtxt<'_>,
270 ) -> impl Iterator<Item = (DefId, PrimitiveType)> {
271 fn as_primitive(def_id: DefId, tcx: TyCtxt<'_>) -> Option<(DefId, PrimitiveType)> {
289 let (attr_span, prim_sym) = find_attr!(
290 tcx, def_id,
291 RustcDocPrimitive(span, prim) => (*span, *prim)
292 )?;
293 let Some(prim) = PrimitiveType::from_symbol(prim_sym) else {
294 span_bug!(attr_span, "primitive `{prim_sym}` is not a member of `PrimitiveType`");
295 };
296 Some((def_id, prim))
297 }
298
299 self.fake_doc_items(tcx, as_primitive)
300 }
301}
302
303#[derive(Debug)]
305pub(crate) enum ExternalLocation {
306 Remote { url: String, is_absolute: bool },
308 Local,
310 Unknown,
312}
313
314#[derive(Clone)]
318pub(crate) struct Item {
319 pub(crate) inner: Box<ItemInner>,
320}
321
322#[derive(Clone)]
328pub(crate) struct ItemInner {
329 pub(crate) name: Option<Symbol>,
332 pub(crate) kind: ItemKind,
335 pub(crate) attrs: Attributes,
336 pub(crate) stability: Option<Stability>,
338 pub(crate) item_id: ItemId,
339 pub(crate) inline_stmt_id: Option<LocalDefId>,
343 pub(crate) cfg: Option<Arc<Cfg>>,
344}
345
346impl std::ops::Deref for Item {
347 type Target = ItemInner;
348 fn deref(&self) -> &ItemInner {
349 &self.inner
350 }
351}
352
353impl fmt::Debug for Item {
356 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
357 let alternate = f.alternate();
358 let mut fmt = f.debug_struct("Item");
360 fmt.field("name", &self.name).field("item_id", &self.item_id);
361 if alternate {
363 fmt.field("attrs", &self.attrs).field("kind", &self.kind).field("cfg", &self.cfg);
364 } else {
365 fmt.field("kind", &self.type_());
366 fmt.field("docs", &self.doc_value());
367 }
368 fmt.finish()
369 }
370}
371
372pub(crate) fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
373 Span::new(def_id.as_local().map_or_else(
374 || tcx.def_span(def_id),
375 |local| tcx.hir_span_with_body(tcx.local_def_id_to_hir_id(local)),
376 ))
377}
378
379fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
380 let parent = tcx.parent(def_id);
381 match tcx.def_kind(parent) {
382 DefKind::Struct | DefKind::Union => false,
383 DefKind::Variant => true,
384 parent_kind => panic!("unexpected parent kind: {parent_kind:?}"),
385 }
386}
387
388impl Item {
389 pub(crate) fn cfg_parent_ids_for_detached_item(&self, tcx: TyCtxt<'_>) -> Vec<LocalDefId> {
390 let Some(def_id) = self.inline_stmt_id.or(self.item_id.as_local_def_id()) else {
391 return Vec::new();
392 };
393 let mut ids = Vec::new();
394 let mut next = def_id;
395 while let Some(parent) = tcx.opt_local_parent(next) {
396 if parent == CRATE_DEF_ID {
397 break;
398 }
399 ids.push(parent);
400 next = parent;
401 }
402 ids.reverse();
403 ids
404 }
405
406 pub(crate) fn stability(&self, tcx: TyCtxt<'_>) -> Option<Stability> {
410 let stability = self.inner.stability;
411 debug_assert!(
412 stability.is_some()
413 || self.def_id().is_none_or(|did| tcx.lookup_stability(did).is_none()),
414 "missing stability for cleaned item: {self:?}",
415 );
416 stability
417 }
418
419 pub(crate) fn const_stability(&self, tcx: TyCtxt<'_>) -> Option<ConstStability> {
420 self.def_id().and_then(|did| tcx.lookup_const_stability(did))
421 }
422
423 pub(crate) fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
424 self.def_id().and_then(|did| tcx.lookup_deprecation(did)).or_else(|| {
425 let stab = self.stability(tcx)?;
429 if let rustc_hir::StabilityLevel::Stable {
430 allowed_through_unstable_modules: Some((note, _)),
431 ..
432 } = stab.level
433 {
434 Some(Deprecation {
435 since: DeprecatedSince::Unspecified,
436 note: Some(Ident { name: note, span: DUMMY_SP }),
437 suggestion: None,
438 })
439 } else {
440 None
441 }
442 })
443 }
444
445 pub(crate) fn is_deprecated(&self, tcx: TyCtxt<'_>) -> bool {
446 self.deprecation(tcx).is_some_and(|deprecation| deprecation.is_in_effect())
447 }
448
449 pub(crate) fn is_unstable(&self) -> bool {
450 self.stability.is_some_and(|x| x.is_unstable())
451 }
452
453 pub(crate) fn is_exported_macro(&self) -> bool {
454 match self.kind {
455 ItemKind::MacroItem(..) => find_attr!(&self.attrs.other_attrs, MacroExport { .. }),
456 _ => false,
457 }
458 }
459
460 pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
461 self.item_id
462 .as_def_id()
463 .map(|did| {
464 inner_docs(
465 #[allow(deprecated)]
466 tcx.get_all_attrs(did),
467 )
468 })
469 .unwrap_or(false)
470 }
471
472 pub(crate) fn has_self_param(&self) -> bool {
474 if let ItemKind::MethodItem(Function { decl, .. }, _) = &self.inner.kind {
475 decl.receiver_type().is_some()
476 } else {
477 false
478 }
479 }
480
481 pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option<Span> {
482 let kind = match &self.kind {
483 ItemKind::StrippedItem(k) => k,
484 _ => &self.kind,
485 };
486 match kind {
487 ItemKind::ModuleItem(Module { span, .. }) => Some(*span),
488 ItemKind::ImplItem(Impl { kind: ImplKind::Auto, .. }) => None,
489 ItemKind::ImplItem(Impl { kind: ImplKind::Blanket(_), .. }) => {
490 if let ItemId::Blanket { impl_id, .. } = self.item_id {
491 Some(rustc_span(impl_id, tcx))
492 } else {
493 panic!("blanket impl item has non-blanket ID")
494 }
495 }
496 _ => self.def_id().map(|did| rustc_span(did, tcx)),
497 }
498 }
499
500 pub(crate) fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
501 let deprecation_notes = find_attr!(&self.attrs.other_attrs, Deprecated { deprecation, .. } => deprecation.note.map(|note| note.span)).flatten();
502
503 span_of_fragments(&self.attrs.doc_strings)
504 .into_iter()
505 .chain(deprecation_notes)
506 .reduce(|a, b| a.to(b))
507 .unwrap_or_else(|| self.span(tcx).map_or(DUMMY_SP, |span| span.inner()))
508 }
509
510 pub(crate) fn doc_value(&self) -> String {
512 self.attrs.doc_value()
513 }
514
515 pub(crate) fn opt_doc_value(&self) -> Option<String> {
519 self.attrs.opt_doc_value()
520 }
521
522 pub(crate) fn from_def_id_and_parts(
523 def_id: DefId,
524 name: Option<Symbol>,
525 kind: ItemKind,
526 tcx: TyCtxt<'_>,
527 ) -> Item {
528 #[allow(deprecated)]
529 let hir_attrs = tcx.get_all_attrs(def_id);
530
531 Self::from_def_id_and_attrs_and_parts(
532 def_id,
533 name,
534 kind,
535 Attributes::from_hir(hir_attrs),
536 None,
537 )
538 }
539
540 pub(crate) fn from_def_id_and_attrs_and_parts(
541 def_id: DefId,
542 name: Option<Symbol>,
543 kind: ItemKind,
544 attrs: Attributes,
545 cfg: Option<Arc<Cfg>>,
546 ) -> Item {
547 trace!("name={name:?}, def_id={def_id:?} cfg={cfg:?}");
548
549 Item {
550 inner: Box::new(ItemInner {
551 item_id: def_id.into(),
552 kind,
553 attrs,
554 stability: None,
555 name,
556 cfg,
557 inline_stmt_id: None,
558 }),
559 }
560 }
561
562 pub(crate) fn item_or_reexport_id(&self) -> ItemId {
568 self.attrs
570 .doc_strings
571 .first()
572 .map(|x| x.item_id)
573 .flatten()
574 .map(ItemId::from)
575 .unwrap_or(self.item_id)
576 }
577
578 pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
579 use crate::html::format::{href_with_path_check, link_tooltip};
580
581 let Some(links) = cx.cache().intra_doc_links.get(&self.item_or_reexport_id()) else {
582 return vec![];
583 };
584 links
585 .iter()
586 .filter_map(|ItemLink { link: s, link_text, page_id: id, fragment }| {
587 debug!(?id);
588 if let Ok(HrefInfo { mut url, .. }) = href_with_path_check(*id, cx, link_text) {
589 debug!(?url);
590 match fragment {
591 Some(UrlFragment::Item(def_id)) => {
592 write!(url, "{}", crate::html::format::fragment(*def_id, cx.tcx()))
593 .unwrap();
594 }
595 Some(UrlFragment::UserWritten(raw)) => {
596 url.push('#');
597 url.push_str(raw);
598 }
599 None => {}
600 }
601 Some(RenderedLink {
602 original_text: s.clone(),
603 new_text: link_text.clone(),
604 tooltip: link_tooltip(*id, fragment, cx, Some(link_text)).to_string(),
605 href: url,
606 })
607 } else {
608 None
609 }
610 })
611 .collect()
612 }
613
614 pub(crate) fn link_names(&self, cache: &Cache) -> Vec<RenderedLink> {
620 let Some(links) = cache.intra_doc_links.get(&self.item_id) else {
621 return vec![];
622 };
623 links
624 .iter()
625 .map(|ItemLink { link: s, link_text, .. }| RenderedLink {
626 original_text: s.clone(),
627 new_text: link_text.clone(),
628 href: String::new(),
629 tooltip: String::new(),
630 })
631 .collect()
632 }
633
634 pub(crate) fn is_crate(&self) -> bool {
635 self.is_mod() && self.def_id().is_some_and(|did| did.is_crate_root())
636 }
637 pub(crate) fn is_mod(&self) -> bool {
638 self.type_() == ItemType::Module
639 }
640 pub(crate) fn is_struct(&self) -> bool {
641 self.type_() == ItemType::Struct
642 }
643 pub(crate) fn is_enum(&self) -> bool {
644 self.type_() == ItemType::Enum
645 }
646 pub(crate) fn is_variant(&self) -> bool {
647 self.type_() == ItemType::Variant
648 }
649 pub(crate) fn is_associated_type(&self) -> bool {
650 matches!(self.kind, AssocTypeItem(..) | StrippedItem(AssocTypeItem(..)))
651 }
652 pub(crate) fn is_required_associated_type(&self) -> bool {
653 matches!(self.kind, RequiredAssocTypeItem(..) | StrippedItem(RequiredAssocTypeItem(..)))
654 }
655 pub(crate) fn is_associated_const(&self) -> bool {
656 matches!(
657 self.kind,
658 ProvidedAssocConstItem(..)
659 | ImplAssocConstItem(..)
660 | StrippedItem(ProvidedAssocConstItem(..) | ImplAssocConstItem(..))
661 )
662 }
663 pub(crate) fn is_required_associated_const(&self) -> bool {
664 matches!(self.kind, RequiredAssocConstItem(..) | StrippedItem(RequiredAssocConstItem(..)))
665 }
666 pub(crate) fn is_method(&self) -> bool {
667 self.type_() == ItemType::Method
668 }
669 pub(crate) fn is_ty_method(&self) -> bool {
670 self.type_() == ItemType::TyMethod
671 }
672 pub(crate) fn is_primitive(&self) -> bool {
673 self.type_() == ItemType::Primitive
674 }
675 pub(crate) fn is_union(&self) -> bool {
676 self.type_() == ItemType::Union
677 }
678 pub(crate) fn is_import(&self) -> bool {
679 self.type_() == ItemType::Import
680 }
681 pub(crate) fn is_extern_crate(&self) -> bool {
682 self.type_() == ItemType::ExternCrate
683 }
684 pub(crate) fn is_keyword(&self) -> bool {
685 self.type_() == ItemType::Keyword
686 }
687 pub(crate) fn is_attribute(&self) -> bool {
688 self.type_() == ItemType::Attribute
689 }
690 pub(crate) fn is_fake_item(&self) -> bool {
699 matches!(self.type_(), ItemType::Primitive | ItemType::Keyword | ItemType::Attribute)
700 }
701 pub(crate) fn is_stripped(&self) -> bool {
702 match self.kind {
703 StrippedItem(..) => true,
704 ImportItem(ref i) => !i.should_be_displayed,
705 _ => false,
706 }
707 }
708 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
709 match self.kind {
710 StructItem(ref struct_) => Some(struct_.has_stripped_entries()),
711 UnionItem(ref union_) => Some(union_.has_stripped_entries()),
712 EnumItem(ref enum_) => Some(enum_.has_stripped_entries()),
713 VariantItem(ref v) => v.has_stripped_entries(),
714 TypeAliasItem(ref type_alias) => {
715 type_alias.inner_type.as_ref().and_then(|t| t.has_stripped_entries())
716 }
717 _ => None,
718 }
719 }
720
721 pub(crate) fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
722 self.stability(tcx).as_ref().and_then(|s| {
723 let mut classes = Vec::with_capacity(2);
724
725 if s.is_unstable() {
726 classes.push("unstable");
727 }
728
729 if self.deprecation(tcx).is_some() {
731 classes.push("deprecated");
732 }
733
734 if !classes.is_empty() { Some(classes.join(" ")) } else { None }
735 })
736 }
737
738 pub(crate) fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<StableSince> {
739 self.stability(tcx).and_then(|stability| stability.stable_since())
740 }
741
742 pub(crate) fn is_non_exhaustive(&self) -> bool {
743 find_attr!(&self.attrs.other_attrs, NonExhaustive(..))
744 }
745
746 pub(crate) fn type_(&self) -> ItemType {
750 ItemType::from(self)
751 }
752
753 pub(crate) fn types(&self) -> impl Iterator<Item = ItemType> {
756 if let ItemKind::MacroItem(_, macro_kinds) = self.kind {
757 Either::Right(macro_kinds.iter().map(|kind| match kind {
758 MacroKinds::ATTR => ItemType::DeclMacroAttribute,
759 MacroKinds::DERIVE => ItemType::DeclMacroDerive,
760 MacroKinds::BANG => ItemType::Macro,
761 _ => panic!("unsupported macro kind {kind:?}"),
762 }))
763 } else {
764 Either::Left(std::iter::once(self.type_()))
765 }
766 }
767
768 pub(crate) fn is_decl_macro(&self) -> bool {
770 matches!(self.kind, ItemKind::MacroItem(..))
771 }
772
773 pub(crate) fn defaultness(&self) -> Option<Defaultness> {
774 match self.kind {
775 ItemKind::MethodItem(_, defaultness) | ItemKind::RequiredMethodItem(_, defaultness) => {
776 Some(defaultness)
777 }
778 _ => None,
779 }
780 }
781
782 pub(crate) fn html_filename(&self) -> String {
784 format!("{type_}.{name}.html", type_ = self.type_(), name = self.name.unwrap())
785 }
786
787 pub(crate) fn fn_header(&self, tcx: TyCtxt<'_>) -> Option<hir::FnHeader> {
789 fn build_fn_header(
790 def_id: DefId,
791 tcx: TyCtxt<'_>,
792 asyncness: ty::Asyncness,
793 ) -> hir::FnHeader {
794 let sig = tcx.fn_sig(def_id).skip_binder();
795 let constness = if tcx.is_const_fn(def_id) {
796 if let Some(assoc) = tcx.opt_associated_item(def_id)
800 && let ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) =
801 assoc.container
802 {
803 hir::Constness::NotConst
804 } else {
805 hir::Constness::Const { always: false }
806 }
807 } else {
808 hir::Constness::NotConst
809 };
810 let asyncness = match asyncness {
811 ty::Asyncness::Yes => hir::IsAsync::Async(DUMMY_SP),
812 ty::Asyncness::No => hir::IsAsync::NotAsync,
813 };
814 hir::FnHeader {
815 safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
816 hir::HeaderSafety::SafeTargetFeatures
817 } else {
818 sig.safety().into()
819 },
820 abi: sig.abi(),
821 constness,
822 asyncness,
823 }
824 }
825 let header = match self.kind {
826 ItemKind::ForeignFunctionItem(_, safety) => {
827 let def_id = self.def_id().unwrap();
828 let abi = tcx.fn_sig(def_id).skip_binder().abi();
829 hir::FnHeader {
830 safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
831 hir::HeaderSafety::SafeTargetFeatures
832 } else {
833 safety.into()
834 },
835 abi,
836 constness: hir::Constness::NotConst,
838 asyncness: hir::IsAsync::NotAsync,
839 }
840 }
841 ItemKind::FunctionItem(_)
842 | ItemKind::MethodItem(..)
843 | ItemKind::RequiredMethodItem(..) => {
844 let def_id = self.def_id().unwrap();
845 build_fn_header(def_id, tcx, tcx.asyncness(def_id))
846 }
847 _ => return None,
848 };
849 Some(header)
850 }
851
852 pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option<Visibility<ModId>> {
855 let def_id = match self.item_id {
856 ItemId::Auto { .. } | ItemId::Blanket { .. } => return None,
858 ItemId::DefId(def_id) => def_id,
859 };
860
861 match self.kind {
862 ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) | ItemKind::AttributeItem => {
866 return Some(Visibility::Public);
867 }
868 StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => {
870 return None;
871 }
872 VariantItem(..) | ImplItem(..) => return None,
874 RequiredAssocConstItem(..)
876 | ProvidedAssocConstItem(..)
877 | ImplAssocConstItem(..)
878 | AssocTypeItem(..)
879 | RequiredAssocTypeItem(..)
880 | RequiredMethodItem(..)
881 | MethodItem(..) => {
882 match tcx.associated_item(def_id).container {
883 ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) => {
886 return None;
887 }
888 ty::AssocContainer::InherentImpl => {}
889 }
890 }
891 _ => {}
892 }
893 let def_id = match self.inline_stmt_id {
894 Some(inlined) => inlined.to_def_id(),
895 None => def_id,
896 };
897 Some(tcx.visibility(def_id))
898 }
899
900 pub fn is_doc_hidden(&self) -> bool {
901 self.attrs.is_doc_hidden()
902 }
903
904 pub fn def_id(&self) -> Option<DefId> {
905 self.item_id.as_def_id()
906 }
907}
908
909#[derive(Clone, Debug)]
910pub(crate) enum ItemKind {
911 ExternCrateItem {
912 src: Option<Symbol>,
914 },
915 ImportItem(Import),
916 StructItem(Struct),
917 UnionItem(Union),
918 EnumItem(Enum),
919 FunctionItem(Box<Function>),
920 ModuleItem(Module),
921 TypeAliasItem(Box<TypeAlias>),
922 StaticItem(Static),
923 TraitItem(Box<Trait>),
924 TraitAliasItem(TraitAlias),
925 ImplItem(Box<Impl>),
926 PlaceholderImplItem,
929 RequiredMethodItem(Box<Function>, Defaultness),
931 MethodItem(Box<Function>, Defaultness),
935 StructFieldItem(Type),
936 VariantItem(Variant),
937 ForeignFunctionItem(Box<Function>, hir::Safety),
939 ForeignStaticItem(Static, hir::Safety),
941 ForeignTypeItem,
943 MacroItem(Macro, MacroKinds),
950 ProcMacroItem(ProcMacro),
951 PrimitiveItem(PrimitiveType),
952 RequiredAssocConstItem(Generics, Box<Type>),
954 ConstantItem(Box<Constant>),
955 ProvidedAssocConstItem(Box<Constant>),
957 ImplAssocConstItem(Box<Constant>),
959 RequiredAssocTypeItem(Generics, Vec<GenericBound>),
963 AssocTypeItem(Box<TypeAlias>, Vec<GenericBound>),
965 StrippedItem(Box<ItemKind>),
967 KeywordItem,
970 AttributeItem,
973}
974
975impl ItemKind {
976 pub(crate) fn inner_items(&self) -> impl Iterator<Item = &Item> {
979 match self {
980 StructItem(s) => s.fields.iter(),
981 UnionItem(u) => u.fields.iter(),
982 VariantItem(v) => match &v.kind {
983 VariantKind::CLike => [].iter(),
984 VariantKind::Tuple(t) => t.iter(),
985 VariantKind::Struct(s) => s.fields.iter(),
986 },
987 EnumItem(e) => e.variants.iter(),
988 TraitItem(t) => t.items.iter(),
989 ImplItem(i) => i.items.iter(),
990 ModuleItem(m) => m.items.iter(),
991 ExternCrateItem { .. }
992 | ImportItem(_)
993 | FunctionItem(_)
994 | TypeAliasItem(_)
995 | StaticItem(_)
996 | ConstantItem(_)
997 | TraitAliasItem(_)
998 | RequiredMethodItem(..)
999 | MethodItem(..)
1000 | StructFieldItem(_)
1001 | ForeignFunctionItem(_, _)
1002 | ForeignStaticItem(_, _)
1003 | ForeignTypeItem
1004 | MacroItem(..)
1005 | ProcMacroItem(_)
1006 | PrimitiveItem(_)
1007 | RequiredAssocConstItem(..)
1008 | ProvidedAssocConstItem(..)
1009 | ImplAssocConstItem(..)
1010 | RequiredAssocTypeItem(..)
1011 | AssocTypeItem(..)
1012 | StrippedItem(_)
1013 | KeywordItem
1014 | AttributeItem
1015 | PlaceholderImplItem => [].iter(),
1016 }
1017 }
1018}
1019
1020#[derive(Clone, Debug)]
1021pub(crate) struct Module {
1022 pub(crate) items: Vec<Item>,
1023 pub(crate) span: Span,
1024}
1025
1026#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1030pub(crate) struct ItemLink {
1031 pub(crate) link: Box<str>,
1033 pub(crate) link_text: Box<str>,
1038 pub(crate) page_id: DefId,
1042 pub(crate) fragment: Option<UrlFragment>,
1044}
1045
1046pub struct RenderedLink {
1047 pub(crate) original_text: Box<str>,
1051 pub(crate) new_text: Box<str>,
1053 pub(crate) href: String,
1055 pub(crate) tooltip: String,
1057}
1058
1059#[derive(Clone, Debug, Default)]
1062pub(crate) struct Attributes {
1063 pub(crate) doc_strings: Vec<DocFragment>,
1064 pub(crate) other_attrs: ThinVec<hir::Attribute>,
1065}
1066
1067impl Attributes {
1068 pub(crate) fn has_doc_flag<F: Fn(&DocAttribute) -> bool>(&self, callback: F) -> bool {
1069 find_attr!(&self.other_attrs, Doc(d) if callback(d))
1070 }
1071
1072 pub(crate) fn is_doc_hidden(&self) -> bool {
1073 find_attr!(&self.other_attrs, Doc(d) if d.hidden.is_some())
1074 }
1075
1076 pub(crate) fn from_hir(attrs: &[hir::Attribute]) -> Attributes {
1077 Attributes::from_hir_iter(attrs.iter().map(|attr| (attr, None)), false)
1078 }
1079
1080 pub(crate) fn from_hir_with_additional(
1081 attrs: &[hir::Attribute],
1082 (additional_attrs, def_id): (&[hir::Attribute], DefId),
1083 ) -> Attributes {
1084 let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id)));
1086 let attrs2 = attrs.iter().map(|attr| (attr, None));
1087 Attributes::from_hir_iter(attrs1.chain(attrs2), false)
1088 }
1089
1090 pub(crate) fn from_hir_iter<'a>(
1091 attrs: impl Iterator<Item = (&'a hir::Attribute, Option<DefId>)>,
1092 doc_only: bool,
1093 ) -> Attributes {
1094 let (doc_strings, other_attrs) = attrs_to_doc_fragments(attrs, doc_only);
1095 Attributes { doc_strings, other_attrs }
1096 }
1097
1098 pub(crate) fn doc_value(&self) -> String {
1100 self.opt_doc_value().unwrap_or_default()
1101 }
1102
1103 pub(crate) fn opt_doc_value(&self) -> Option<String> {
1107 (!self.doc_strings.is_empty()).then(|| {
1108 let mut res = String::new();
1109 for frag in &self.doc_strings {
1110 add_doc_fragment(&mut res, frag);
1111 }
1112 res.pop();
1113 res
1114 })
1115 }
1116
1117 pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> {
1118 let mut aliases = FxIndexSet::default();
1119
1120 for attr in &self.other_attrs {
1121 if let Attribute::Parsed(AttributeKind::Doc(d)) = attr {
1122 for (alias, _) in &d.aliases {
1123 aliases.insert(*alias);
1124 }
1125 }
1126 }
1127 aliases.into_iter().collect::<Vec<_>>().into()
1128 }
1129
1130 pub(crate) fn merge_with(&mut self, other: Self) {
1131 let Self { doc_strings, other_attrs } = other;
1132 self.doc_strings.extend(doc_strings);
1133 self.other_attrs.extend(other_attrs);
1134 }
1135}
1136
1137#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1138pub(crate) enum GenericBound {
1139 TraitBound(PolyTrait, hir::TraitBoundModifiers),
1140 Outlives(Lifetime),
1141 Use(Vec<PreciseCapturingArg>),
1143}
1144
1145impl GenericBound {
1146 pub(crate) fn sized(cx: &mut DocContext<'_>) -> GenericBound {
1147 Self::sized_with(cx, hir::TraitBoundModifiers::NONE)
1148 }
1149
1150 pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1151 Self::sized_with(
1152 cx,
1153 hir::TraitBoundModifiers {
1154 polarity: hir::BoundPolarity::Maybe(DUMMY_SP),
1155 constness: hir::BoundConstness::Never,
1156 },
1157 )
1158 }
1159
1160 fn sized_with(cx: &mut DocContext<'_>, modifiers: hir::TraitBoundModifiers) -> GenericBound {
1161 let did = cx.tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
1162 let empty = ty::Binder::dummy(ty::GenericArgs::empty());
1163 let path = clean_middle_path(cx, did, false, ThinVec::new(), empty);
1164 inline::record_extern_fqn(cx, did, ItemType::Trait);
1165 GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifiers)
1166 }
1167
1168 pub(crate) fn is_trait_bound(&self) -> bool {
1169 matches!(self, Self::TraitBound(..))
1170 }
1171
1172 pub(crate) fn is_sized_bound(&self, tcx: TyCtxt<'_>) -> bool {
1173 self.is_bounded_by_lang_item(tcx, LangItem::Sized)
1174 }
1175
1176 pub(crate) fn is_meta_sized_bound(&self, tcx: TyCtxt<'_>) -> bool {
1177 self.is_bounded_by_lang_item(tcx, LangItem::MetaSized)
1178 }
1179
1180 fn is_bounded_by_lang_item(&self, tcx: TyCtxt<'_>, lang_item: LangItem) -> bool {
1181 if let GenericBound::TraitBound(poly_trait_ref, rustc_hir::TraitBoundModifiers::NONE) = self
1182 && tcx.is_lang_item(poly_trait_ref.trait_.def_id(), lang_item)
1183 {
1184 return true;
1185 }
1186 false
1187 }
1188
1189 pub(crate) fn get_trait_path(&self) -> Option<Path> {
1190 if let GenericBound::TraitBound(poly_trait_ref, _) = self {
1191 Some(poly_trait_ref.trait_.clone())
1192 } else {
1193 None
1194 }
1195 }
1196}
1197
1198#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1199pub(crate) struct Lifetime(pub Symbol);
1200
1201impl Lifetime {
1202 pub(crate) fn statik() -> Lifetime {
1203 Lifetime(kw::StaticLifetime)
1204 }
1205
1206 pub(crate) fn elided() -> Lifetime {
1207 Lifetime(kw::UnderscoreLifetime)
1208 }
1209}
1210
1211#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1212pub(crate) enum PreciseCapturingArg {
1213 Lifetime(Lifetime),
1214 Param(Symbol),
1215}
1216
1217impl PreciseCapturingArg {
1218 pub(crate) fn name(self) -> Symbol {
1219 match self {
1220 PreciseCapturingArg::Lifetime(lt) => lt.0,
1221 PreciseCapturingArg::Param(param) => param,
1222 }
1223 }
1224}
1225
1226#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1227pub(crate) enum WherePredicate {
1228 BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
1229 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1230 ProjectionPredicate { lhs: QPathData, rhs: Term },
1231}
1232
1233impl WherePredicate {
1234 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1235 match self {
1236 WherePredicate::BoundPredicate { bounds, .. } => Some(bounds),
1237 WherePredicate::RegionPredicate { bounds, .. } => Some(bounds),
1238 _ => None,
1239 }
1240 }
1241}
1242
1243#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1244pub(crate) enum GenericParamDefKind {
1245 Lifetime { outlives: ThinVec<Lifetime> },
1246 Type { bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
1247 Const { ty: Box<Type>, default: Option<Box<String>> },
1249}
1250
1251impl GenericParamDefKind {
1252 pub(crate) fn is_type(&self) -> bool {
1253 matches!(self, GenericParamDefKind::Type { .. })
1254 }
1255}
1256
1257#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1258pub(crate) struct GenericParamDef {
1259 pub(crate) name: Symbol,
1260 pub(crate) def_id: DefId,
1261 pub(crate) kind: GenericParamDefKind,
1262}
1263
1264impl GenericParamDef {
1265 pub(crate) fn lifetime(def_id: DefId, name: Symbol) -> Self {
1266 Self { name, def_id, kind: GenericParamDefKind::Lifetime { outlives: ThinVec::new() } }
1267 }
1268
1269 pub(crate) fn is_synthetic_param(&self) -> bool {
1270 match self.kind {
1271 GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
1272 GenericParamDefKind::Type { synthetic, .. } => synthetic,
1273 }
1274 }
1275
1276 pub(crate) fn is_type(&self) -> bool {
1277 self.kind.is_type()
1278 }
1279
1280 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1281 match self.kind {
1282 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1283 _ => None,
1284 }
1285 }
1286}
1287
1288#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
1290pub(crate) struct Generics {
1291 pub(crate) params: ThinVec<GenericParamDef>,
1292 pub(crate) where_predicates: ThinVec<WherePredicate>,
1293}
1294
1295impl Generics {
1296 pub(crate) fn is_empty(&self) -> bool {
1297 self.params.is_empty() && self.where_predicates.is_empty()
1298 }
1299}
1300
1301#[derive(Clone, Debug)]
1302pub(crate) struct Function {
1303 pub(crate) decl: FnDecl,
1304 pub(crate) generics: Generics,
1305}
1306
1307#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1308pub(crate) struct FnDecl {
1309 pub(crate) inputs: Vec<Parameter>,
1310 pub(crate) output: Type,
1311 pub(crate) c_variadic: bool,
1312}
1313
1314impl FnDecl {
1315 pub(crate) fn receiver_type(&self) -> Option<&Type> {
1316 self.inputs.first().and_then(|v| v.to_receiver())
1317 }
1318}
1319
1320#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1322pub(crate) struct Parameter {
1323 pub(crate) name: Option<Symbol>,
1324 pub(crate) type_: Type,
1325 pub(crate) is_const: bool,
1328 pub(crate) is_splat: bool,
1331}
1332
1333impl Parameter {
1334 pub(crate) fn to_receiver(&self) -> Option<&Type> {
1335 if self.name == Some(kw::SelfLower) { Some(&self.type_) } else { None }
1336 }
1337}
1338
1339#[derive(Clone, Debug)]
1340pub(crate) struct Trait {
1341 pub(crate) def_id: DefId,
1342 pub(crate) items: Vec<Item>,
1343 pub(crate) generics: Generics,
1344 pub(crate) bounds: Vec<GenericBound>,
1345}
1346
1347impl Trait {
1348 pub(crate) fn is_auto(&self, tcx: TyCtxt<'_>) -> bool {
1349 tcx.trait_is_auto(self.def_id)
1350 }
1351 pub(crate) fn is_notable_trait(&self, tcx: TyCtxt<'_>) -> bool {
1352 tcx.is_doc_notable_trait(self.def_id)
1353 }
1354 pub(crate) fn safety(&self, tcx: TyCtxt<'_>) -> hir::Safety {
1355 tcx.trait_def(self.def_id).safety
1356 }
1357 pub(crate) fn is_dyn_compatible(&self, tcx: TyCtxt<'_>) -> bool {
1358 tcx.is_dyn_compatible(self.def_id)
1359 }
1360 pub(crate) fn is_deprecated(&self, tcx: TyCtxt<'_>) -> bool {
1361 tcx.lookup_deprecation(self.def_id).is_some_and(|deprecation| deprecation.is_in_effect())
1362 }
1363}
1364
1365#[derive(Clone, Debug)]
1366pub(crate) struct TraitAlias {
1367 pub(crate) generics: Generics,
1368 pub(crate) bounds: Vec<GenericBound>,
1369}
1370
1371#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1373pub(crate) struct PolyTrait {
1374 pub(crate) trait_: Path,
1375 pub(crate) generic_params: Vec<GenericParamDef>,
1376}
1377
1378#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1380pub(crate) enum Type {
1381 Path {
1386 path: Path,
1387 },
1388 DynTrait(Vec<PolyTrait>, Option<Lifetime>),
1390 Generic(Symbol),
1392 SelfTy,
1394 Primitive(PrimitiveType),
1396 BareFunction(Box<BareFunctionDecl>),
1398 Tuple(Vec<Type>),
1400 Slice(Box<Type>),
1402 Array(Box<Type>, Box<str>),
1406 Pat(Box<Type>, Box<str>),
1407 FieldOf(Box<Type>, Box<str>),
1408 RawPointer(Mutability, Box<Type>),
1410 BorrowedRef {
1412 lifetime: Option<Lifetime>,
1413 mutability: Mutability,
1414 type_: Box<Type>,
1415 },
1416
1417 QPath(Box<QPathData>),
1419
1420 Infer,
1422
1423 ImplTrait(Vec<GenericBound>),
1425
1426 UnsafeBinder(Box<UnsafeBinderTy>),
1427}
1428
1429impl Type {
1430 pub(crate) fn without_borrowed_ref(&self) -> &Type {
1432 let mut result = self;
1433 while let Type::BorrowedRef { type_, .. } = result {
1434 result = type_;
1435 }
1436 result
1437 }
1438
1439 pub(crate) fn is_borrowed_ref(&self) -> bool {
1440 matches!(self, Type::BorrowedRef { .. })
1441 }
1442
1443 fn is_type_alias(&self) -> bool {
1444 matches!(self, Type::Path { path: Path { res: Res::Def(DefKind::TyAlias, _), .. } })
1445 }
1446
1447 pub(crate) fn is_doc_subtype_of(&self, other: &Self, cache: &Cache) -> bool {
1468 let (self_cleared, other_cleared) = if !self.is_borrowed_ref() || !other.is_borrowed_ref() {
1471 (self.without_borrowed_ref(), other.without_borrowed_ref())
1472 } else {
1473 (self, other)
1474 };
1475
1476 if self_cleared.is_type_alias() || other_cleared.is_type_alias() {
1482 return true;
1483 }
1484
1485 match (self_cleared, other_cleared) {
1486 (Type::Tuple(a), Type::Tuple(b)) => {
1488 a.iter().eq_by(b, |a, b| a.is_doc_subtype_of(b, cache))
1489 }
1490 (Type::Slice(a), Type::Slice(b)) => a.is_doc_subtype_of(b, cache),
1491 (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_doc_subtype_of(b, cache),
1492 (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
1493 mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache)
1494 }
1495 (
1496 Type::BorrowedRef { mutability, type_, .. },
1497 Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
1498 ) => mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache),
1499 (Type::Infer, _) | (_, Type::Infer) => true,
1501 (_, Type::Generic(_)) => true,
1504 (Type::Generic(_), _) => false,
1505 (Type::SelfTy, Type::SelfTy) => true,
1507 (Type::Path { path: a }, Type::Path { path: b }) => {
1509 a.def_id() == b.def_id()
1510 && a.generics()
1511 .zip(b.generics())
1512 .map(|(ag, bg)| ag.zip(bg).all(|(at, bt)| at.is_doc_subtype_of(bt, cache)))
1513 .unwrap_or(true)
1514 }
1515 (a, b) => a
1517 .def_id(cache)
1518 .and_then(|a| Some((a, b.def_id(cache)?)))
1519 .map(|(a, b)| a == b)
1520 .unwrap_or(false),
1521 }
1522 }
1523
1524 pub(crate) fn primitive_type(&self) -> Option<PrimitiveType> {
1525 match *self {
1526 Primitive(p) | BorrowedRef { type_: Primitive(p), .. } => Some(p),
1527 Slice(..) | BorrowedRef { type_: Slice(..), .. } => Some(PrimitiveType::Slice),
1528 Array(..) | BorrowedRef { type_: Array(..), .. } => Some(PrimitiveType::Array),
1529 Tuple(ref tys) => {
1530 if tys.is_empty() {
1531 Some(PrimitiveType::Unit)
1532 } else {
1533 Some(PrimitiveType::Tuple)
1534 }
1535 }
1536 RawPointer(..) => Some(PrimitiveType::RawPointer),
1537 BareFunction(..) => Some(PrimitiveType::Fn),
1538 _ => None,
1539 }
1540 }
1541
1542 pub(crate) fn sugared_async_return_type(self) -> Type {
1552 if let Type::ImplTrait(mut v) = self
1553 && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = v.pop()
1554 && let Some(segment) = trait_.segments.pop()
1555 && let GenericArgs::AngleBracketed { mut constraints, .. } = segment.args
1556 && let Some(constraint) = constraints.pop()
1557 && let AssocItemConstraintKind::Equality { term } = constraint.kind
1558 && let Term::Type(ty) = term
1559 {
1560 ty
1561 } else {
1562 panic!("unexpected async fn return type")
1563 }
1564 }
1565
1566 pub(crate) fn is_assoc_ty(&self) -> bool {
1568 match self {
1569 Type::Path { path, .. } => path.is_assoc_ty(),
1570 _ => false,
1571 }
1572 }
1573
1574 pub(crate) fn is_self_type(&self) -> bool {
1575 matches!(*self, Type::SelfTy)
1576 }
1577
1578 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
1579 match self {
1580 Type::Path { path, .. } => path.generic_args(),
1581 _ => None,
1582 }
1583 }
1584
1585 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
1586 match self {
1587 Type::Path { path, .. } => path.generics(),
1588 _ => None,
1589 }
1590 }
1591
1592 pub(crate) fn is_full_generic(&self) -> bool {
1593 matches!(self, Type::Generic(_))
1594 }
1595
1596 pub(crate) fn is_unit(&self) -> bool {
1597 matches!(self, Type::Tuple(v) if v.is_empty())
1598 }
1599
1600 pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
1604 let t: PrimitiveType = match self {
1605 Type::Path { path } => return Some(path.def_id()),
1606 DynTrait(bounds, _) => return bounds.first().map(|b| b.trait_.def_id()),
1607 Primitive(p) => return cache.primitive_locations.get(p).cloned(),
1608 BorrowedRef { type_: Generic(..), .. } => PrimitiveType::Reference,
1609 BorrowedRef { type_, .. } => return type_.def_id(cache),
1610 Tuple(tys) => {
1611 if tys.is_empty() {
1612 PrimitiveType::Unit
1613 } else {
1614 PrimitiveType::Tuple
1615 }
1616 }
1617 BareFunction(..) => PrimitiveType::Fn,
1618 Slice(..) => PrimitiveType::Slice,
1619 Array(..) => PrimitiveType::Array,
1620 Type::Pat(..) => PrimitiveType::Pat,
1621 Type::FieldOf(..) => PrimitiveType::FieldOf,
1622 RawPointer(..) => PrimitiveType::RawPointer,
1623 QPath(QPathData { self_type, .. }) => return self_type.def_id(cache),
1624 Generic(_) | SelfTy | Infer | ImplTrait(_) | UnsafeBinder(_) => return None,
1625 };
1626 Primitive(t).def_id(cache)
1627 }
1628}
1629
1630#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1631pub(crate) struct QPathData {
1632 pub assoc: PathSegment,
1633 pub self_type: Type,
1634 pub should_fully_qualify: bool,
1636 pub trait_: Option<Path>,
1637}
1638
1639#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1646pub(crate) enum PrimitiveType {
1647 Isize,
1648 I8,
1649 I16,
1650 I32,
1651 I64,
1652 I128,
1653 Usize,
1654 U8,
1655 U16,
1656 U32,
1657 U64,
1658 U128,
1659 F16,
1660 F32,
1661 F64,
1662 F128,
1663 Char,
1664 Bool,
1665 Str,
1666 Slice,
1667 Array,
1668 Pat,
1669 FieldOf,
1670 Tuple,
1671 Unit,
1672 RawPointer,
1673 Reference,
1674 Fn,
1675 Never,
1676}
1677
1678type SimplifiedTypes = FxIndexMap<PrimitiveType, ArrayVec<SimplifiedType, 3>>;
1679impl PrimitiveType {
1680 pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1681 use ast::{FloatTy, IntTy, UintTy};
1682 match prim {
1683 hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1684 hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1685 hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1686 hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1687 hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1688 hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1689 hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1690 hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1691 hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1692 hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1693 hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1694 hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1695 hir::PrimTy::Float(FloatTy::F16) => PrimitiveType::F16,
1696 hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1697 hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1698 hir::PrimTy::Float(FloatTy::F128) => PrimitiveType::F128,
1699 hir::PrimTy::Str => PrimitiveType::Str,
1700 hir::PrimTy::Bool => PrimitiveType::Bool,
1701 hir::PrimTy::Char => PrimitiveType::Char,
1702 }
1703 }
1704
1705 pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1706 match s {
1707 sym::isize => Some(PrimitiveType::Isize),
1708 sym::i8 => Some(PrimitiveType::I8),
1709 sym::i16 => Some(PrimitiveType::I16),
1710 sym::i32 => Some(PrimitiveType::I32),
1711 sym::i64 => Some(PrimitiveType::I64),
1712 sym::i128 => Some(PrimitiveType::I128),
1713 sym::usize => Some(PrimitiveType::Usize),
1714 sym::u8 => Some(PrimitiveType::U8),
1715 sym::u16 => Some(PrimitiveType::U16),
1716 sym::u32 => Some(PrimitiveType::U32),
1717 sym::u64 => Some(PrimitiveType::U64),
1718 sym::u128 => Some(PrimitiveType::U128),
1719 sym::bool => Some(PrimitiveType::Bool),
1720 sym::char => Some(PrimitiveType::Char),
1721 sym::str => Some(PrimitiveType::Str),
1722 sym::f16 => Some(PrimitiveType::F16),
1723 sym::f32 => Some(PrimitiveType::F32),
1724 sym::f64 => Some(PrimitiveType::F64),
1725 sym::f128 => Some(PrimitiveType::F128),
1726 sym::array => Some(PrimitiveType::Array),
1727 sym::slice => Some(PrimitiveType::Slice),
1728 sym::tuple => Some(PrimitiveType::Tuple),
1729 sym::unit => Some(PrimitiveType::Unit),
1730 sym::pointer => Some(PrimitiveType::RawPointer),
1731 sym::reference => Some(PrimitiveType::Reference),
1732 kw::Fn => Some(PrimitiveType::Fn),
1733 sym::never => Some(PrimitiveType::Never),
1734 _ => None,
1735 }
1736 }
1737
1738 pub(crate) fn from_ty(ty: Ty<'_>) -> Option<Self> {
1739 match ty.kind() {
1740 ty::Array(..) => Some(Self::Array),
1741 ty::Bool => Some(Self::Bool),
1742 ty::Char => Some(Self::Char),
1743 ty::FnDef(..) | ty::FnPtr(..) => Some(Self::Fn),
1744 ty::Int(int) => Some(Self::from(*int)),
1745 ty::Uint(uint) => Some(Self::from(*uint)),
1746 ty::Float(float) => Some(Self::from(*float)),
1747 ty::Never => Some(Self::Never),
1748 ty::Pat(..) => Some(Self::Pat),
1749 ty::RawPtr(..) => Some(Self::RawPointer),
1750 ty::Ref(..) => Some(Self::Reference),
1751 ty::Slice(..) => Some(Self::Slice),
1752 ty::Str => Some(Self::Str),
1753 ty::Tuple(elems) if elems.is_empty() => Some(Self::Unit),
1754 ty::Tuple(_) => Some(Self::Tuple),
1755 ty::Adt(..)
1756 | ty::Alias(_, ..)
1757 | ty::Bound(..)
1758 | ty::Closure(..)
1759 | ty::Coroutine(..)
1760 | ty::CoroutineClosure(..)
1761 | ty::CoroutineWitness(..)
1762 | ty::Dynamic(..)
1763 | ty::Error(..)
1764 | ty::Foreign(..)
1765 | ty::Infer(..)
1766 | ty::Param(..)
1767 | ty::Placeholder(..)
1768 | ty::UnsafeBinder(..) => None,
1769 }
1770 }
1771
1772 pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
1773 use PrimitiveType::*;
1774 use ty::{FloatTy, IntTy, UintTy};
1775 static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
1776
1777 let single = |x| iter::once(x).collect();
1778 CELL.get_or_init(move || {
1779 map! {
1780 Isize => single(SimplifiedType::Int(IntTy::Isize)),
1781 I8 => single(SimplifiedType::Int(IntTy::I8)),
1782 I16 => single(SimplifiedType::Int(IntTy::I16)),
1783 I32 => single(SimplifiedType::Int(IntTy::I32)),
1784 I64 => single(SimplifiedType::Int(IntTy::I64)),
1785 I128 => single(SimplifiedType::Int(IntTy::I128)),
1786 Usize => single(SimplifiedType::Uint(UintTy::Usize)),
1787 U8 => single(SimplifiedType::Uint(UintTy::U8)),
1788 U16 => single(SimplifiedType::Uint(UintTy::U16)),
1789 U32 => single(SimplifiedType::Uint(UintTy::U32)),
1790 U64 => single(SimplifiedType::Uint(UintTy::U64)),
1791 U128 => single(SimplifiedType::Uint(UintTy::U128)),
1792 F16 => single(SimplifiedType::Float(FloatTy::F16)),
1793 F32 => single(SimplifiedType::Float(FloatTy::F32)),
1794 F64 => single(SimplifiedType::Float(FloatTy::F64)),
1795 F128 => single(SimplifiedType::Float(FloatTy::F128)),
1796 Str => single(SimplifiedType::Str),
1797 Bool => single(SimplifiedType::Bool),
1798 Char => single(SimplifiedType::Char),
1799 Array => single(SimplifiedType::Array),
1800 Slice => single(SimplifiedType::Slice),
1801 Tuple => [SimplifiedType::Tuple(1), SimplifiedType::Tuple(2), SimplifiedType::Tuple(3)].into(),
1807 Unit => single(SimplifiedType::Tuple(0)),
1808 RawPointer => [SimplifiedType::Ptr(Mutability::Not), SimplifiedType::Ptr(Mutability::Mut)].into_iter().collect(),
1809 Reference => [SimplifiedType::Ref(Mutability::Not), SimplifiedType::Ref(Mutability::Mut)].into_iter().collect(),
1810 Fn => single(SimplifiedType::Function(1)),
1813 Never => single(SimplifiedType::Never),
1814 }
1815 })
1816 }
1817
1818 pub(crate) fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = DefId> + 'tcx {
1819 Self::simplified_types()
1820 .get(self)
1821 .into_iter()
1822 .flatten()
1823 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1824 .copied()
1825 }
1826
1827 pub(crate) fn as_sym(&self) -> Symbol {
1828 use PrimitiveType::*;
1829 match self {
1830 Isize => sym::isize,
1831 I8 => sym::i8,
1832 I16 => sym::i16,
1833 I32 => sym::i32,
1834 I64 => sym::i64,
1835 I128 => sym::i128,
1836 Usize => sym::usize,
1837 U8 => sym::u8,
1838 U16 => sym::u16,
1839 U32 => sym::u32,
1840 U64 => sym::u64,
1841 U128 => sym::u128,
1842 F16 => sym::f16,
1843 F32 => sym::f32,
1844 F64 => sym::f64,
1845 F128 => sym::f128,
1846 Str => sym::str,
1847 Bool => sym::bool,
1848 Char => sym::char,
1849 Array => sym::array,
1850 Pat => sym::pat,
1851 FieldOf => sym::field_of,
1852 Slice => sym::slice,
1853 Tuple => sym::tuple,
1854 Unit => sym::unit,
1855 RawPointer => sym::pointer,
1856 Reference => sym::reference,
1857 Fn => kw::Fn,
1858 Never => sym::never,
1859 }
1860 }
1861
1862 pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxIndexMap<PrimitiveType, DefId> {
1874 fn as_primitive(def_id: DefId, tcx: TyCtxt<'_>) -> Option<PrimitiveType> {
1875 let (attr_span, prim_sym) = find_attr!(
1876 tcx, def_id,
1877 RustcDocPrimitive(span, prim) => (*span, *prim)
1878 )?;
1879 let Some(prim) = PrimitiveType::from_symbol(prim_sym) else {
1880 span_bug!(attr_span, "primitive `{prim_sym}` is not a member of `PrimitiveType`");
1881 };
1882 Some(prim)
1883 }
1884
1885 static PRIMITIVE_LOCATIONS: OnceCell<FxIndexMap<PrimitiveType, DefId>> = OnceCell::new();
1886 PRIMITIVE_LOCATIONS.get_or_init(|| {
1887 let mut primitive_locations = FxIndexMap::default();
1888 let mut ids = tcx.all_fake_doc_items(()).clone();
1892
1893 ids.iter_mut().partition_in_place(|id| tcx.crate_name(id.krate) == sym::core);
1897 for def_id in ids {
1898 if let Some(prim) = as_primitive(def_id, tcx) {
1899 primitive_locations.insert(prim, def_id);
1900 }
1901 }
1902
1903 primitive_locations
1904 })
1905 }
1906}
1907
1908impl From<ty::IntTy> for PrimitiveType {
1909 fn from(int_ty: ty::IntTy) -> PrimitiveType {
1910 match int_ty {
1911 ty::IntTy::Isize => PrimitiveType::Isize,
1912 ty::IntTy::I8 => PrimitiveType::I8,
1913 ty::IntTy::I16 => PrimitiveType::I16,
1914 ty::IntTy::I32 => PrimitiveType::I32,
1915 ty::IntTy::I64 => PrimitiveType::I64,
1916 ty::IntTy::I128 => PrimitiveType::I128,
1917 }
1918 }
1919}
1920
1921impl From<ty::UintTy> for PrimitiveType {
1922 fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1923 match uint_ty {
1924 ty::UintTy::Usize => PrimitiveType::Usize,
1925 ty::UintTy::U8 => PrimitiveType::U8,
1926 ty::UintTy::U16 => PrimitiveType::U16,
1927 ty::UintTy::U32 => PrimitiveType::U32,
1928 ty::UintTy::U64 => PrimitiveType::U64,
1929 ty::UintTy::U128 => PrimitiveType::U128,
1930 }
1931 }
1932}
1933
1934impl From<ty::FloatTy> for PrimitiveType {
1935 fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1936 match float_ty {
1937 ty::FloatTy::F16 => PrimitiveType::F16,
1938 ty::FloatTy::F32 => PrimitiveType::F32,
1939 ty::FloatTy::F64 => PrimitiveType::F64,
1940 ty::FloatTy::F128 => PrimitiveType::F128,
1941 }
1942 }
1943}
1944
1945impl From<hir::PrimTy> for PrimitiveType {
1946 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1947 match prim_ty {
1948 hir::PrimTy::Int(int_ty) => int_ty.into(),
1949 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1950 hir::PrimTy::Float(float_ty) => float_ty.into(),
1951 hir::PrimTy::Str => PrimitiveType::Str,
1952 hir::PrimTy::Bool => PrimitiveType::Bool,
1953 hir::PrimTy::Char => PrimitiveType::Char,
1954 }
1955 }
1956}
1957
1958#[derive(Clone, Debug)]
1959pub(crate) struct Struct {
1960 pub(crate) ctor_kind: Option<CtorKind>,
1961 pub(crate) generics: Generics,
1962 pub(crate) fields: ThinVec<Item>,
1963}
1964
1965impl Struct {
1966 pub(crate) fn has_stripped_entries(&self) -> bool {
1967 self.fields.iter().any(|f| f.is_stripped())
1968 }
1969}
1970
1971#[derive(Clone, Debug)]
1972pub(crate) struct Union {
1973 pub(crate) generics: Generics,
1974 pub(crate) fields: Vec<Item>,
1975}
1976
1977impl Union {
1978 pub(crate) fn has_stripped_entries(&self) -> bool {
1979 self.fields.iter().any(|f| f.is_stripped())
1980 }
1981}
1982
1983#[derive(Clone, Debug)]
1987pub(crate) struct VariantStruct {
1988 pub(crate) fields: ThinVec<Item>,
1989}
1990
1991impl VariantStruct {
1992 pub(crate) fn has_stripped_entries(&self) -> bool {
1993 self.fields.iter().any(|f| f.is_stripped())
1994 }
1995}
1996
1997#[derive(Clone, Debug)]
1998pub(crate) struct Enum {
1999 pub(crate) variants: IndexVec<VariantIdx, Item>,
2000 pub(crate) generics: Generics,
2001}
2002
2003impl Enum {
2004 pub(crate) fn has_stripped_entries(&self) -> bool {
2005 self.variants.iter().any(|f| f.is_stripped())
2006 }
2007
2008 pub(crate) fn non_stripped_variants(&self) -> impl Iterator<Item = &Item> {
2009 self.variants.iter().filter(|v| !v.is_stripped())
2010 }
2011}
2012
2013#[derive(Clone, Debug)]
2014pub(crate) struct Variant {
2015 pub kind: VariantKind,
2016 pub discriminant: Option<Discriminant>,
2017}
2018
2019#[derive(Clone, Debug)]
2020pub(crate) enum VariantKind {
2021 CLike,
2022 Tuple(ThinVec<Item>),
2023 Struct(VariantStruct),
2024}
2025
2026impl Variant {
2027 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
2028 match &self.kind {
2029 VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()),
2030 VariantKind::CLike | VariantKind::Tuple(_) => None,
2031 }
2032 }
2033}
2034
2035#[derive(Clone, Debug)]
2036pub(crate) struct Discriminant {
2037 pub(super) expr: Option<BodyId>,
2040 pub(super) value: DefId,
2041}
2042
2043impl Discriminant {
2044 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
2047 self.expr
2048 .map(|body| rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body)))
2049 }
2050 pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String {
2051 print_evaluated_const(tcx, self.value, with_underscores, false).unwrap()
2052 }
2053}
2054
2055#[derive(Copy, Clone, Debug)]
2058pub(crate) struct Span(rustc_span::Span);
2059
2060impl Span {
2061 pub(crate) fn new(sp: rustc_span::Span) -> Self {
2066 Self(sp.source_callsite())
2067 }
2068
2069 pub(crate) fn inner(&self) -> rustc_span::Span {
2070 self.0
2071 }
2072
2073 pub(crate) fn filename(&self, sess: &Session) -> FileName {
2074 sess.source_map().span_to_filename(self.0)
2075 }
2076
2077 pub(crate) fn lo(&self, sess: &Session) -> Loc {
2078 sess.source_map().lookup_char_pos(self.0.lo())
2079 }
2080
2081 pub(crate) fn hi(&self, sess: &Session) -> Loc {
2082 sess.source_map().lookup_char_pos(self.0.hi())
2083 }
2084
2085 pub(crate) fn cnum(&self, sess: &Session) -> CrateNum {
2086 self.lo(sess).file.cnum
2088 }
2089}
2090
2091#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2092pub(crate) struct Path {
2093 pub(crate) res: Res,
2094 pub(crate) segments: ThinVec<PathSegment>,
2095}
2096
2097impl Path {
2098 pub(crate) fn def_id(&self) -> DefId {
2099 self.res.def_id()
2100 }
2101
2102 pub(crate) fn last_opt(&self) -> Option<Symbol> {
2103 self.segments.last().map(|s| s.name)
2104 }
2105
2106 pub(crate) fn last(&self) -> Symbol {
2107 self.last_opt().expect("segments were empty")
2108 }
2109
2110 pub(crate) fn whole_name(&self) -> String {
2111 self.segments
2112 .iter()
2113 .map(|s| if s.name == kw::PathRoot { "" } else { s.name.as_str() })
2114 .intersperse("::")
2115 .collect()
2116 }
2117
2118 pub(crate) fn is_assoc_ty(&self) -> bool {
2120 match self.res {
2121 Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _)
2122 if self.segments.len() != 1 =>
2123 {
2124 true
2125 }
2126 Res::Def(DefKind::AssocTy, _) => true,
2127 _ => false,
2128 }
2129 }
2130
2131 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
2132 self.segments.last().map(|seg| &seg.args)
2133 }
2134
2135 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
2136 self.segments.last().and_then(|seg| {
2137 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2138 Some(args.iter().filter_map(|arg| match arg {
2139 GenericArg::Type(ty) => Some(ty),
2140 _ => None,
2141 }))
2142 } else {
2143 None
2144 }
2145 })
2146 }
2147}
2148
2149#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2150pub(crate) enum GenericArg {
2151 Lifetime(Lifetime),
2152 Type(Type),
2153 Const(Box<ConstantKind>),
2154 Infer,
2155}
2156
2157impl GenericArg {
2158 pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
2159 if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2160 }
2161
2162 pub(crate) fn as_ty(&self) -> Option<&Type> {
2163 if let Self::Type(ty) = self { Some(ty) } else { None }
2164 }
2165}
2166
2167#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2168pub(crate) enum GenericArgs {
2169 AngleBracketed { args: ThinVec<GenericArg>, constraints: ThinVec<AssocItemConstraint> },
2171 Parenthesized { inputs: ThinVec<Type>, output: Option<Box<Type>> },
2173 ReturnTypeNotation,
2175}
2176
2177impl GenericArgs {
2178 pub(crate) fn is_empty(&self) -> bool {
2179 match self {
2180 GenericArgs::AngleBracketed { args, constraints } => {
2181 args.is_empty() && constraints.is_empty()
2182 }
2183 GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
2184 GenericArgs::ReturnTypeNotation => false,
2185 }
2186 }
2187 pub(crate) fn constraints(&self) -> Box<dyn Iterator<Item = AssocItemConstraint> + '_> {
2188 match self {
2189 GenericArgs::AngleBracketed { constraints, .. } => {
2190 Box::new(constraints.iter().cloned())
2191 }
2192 GenericArgs::Parenthesized { output, .. } => Box::new(
2193 output
2194 .as_ref()
2195 .map(|ty| AssocItemConstraint {
2196 assoc: PathSegment {
2197 name: sym::Output,
2198 args: GenericArgs::AngleBracketed {
2199 args: ThinVec::new(),
2200 constraints: ThinVec::new(),
2201 },
2202 },
2203 kind: AssocItemConstraintKind::Equality {
2204 term: Term::Type((**ty).clone()),
2205 },
2206 })
2207 .into_iter(),
2208 ),
2209 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2210 }
2211 }
2212}
2213
2214impl<'a> IntoIterator for &'a GenericArgs {
2215 type IntoIter = Box<dyn Iterator<Item = GenericArg> + 'a>;
2216 type Item = GenericArg;
2217 fn into_iter(self) -> Self::IntoIter {
2218 match self {
2219 GenericArgs::AngleBracketed { args, .. } => Box::new(args.iter().cloned()),
2220 GenericArgs::Parenthesized { inputs, .. } => {
2221 Box::new(inputs.iter().cloned().map(GenericArg::Type))
2223 }
2224 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2225 }
2226 }
2227}
2228
2229#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2230pub(crate) struct PathSegment {
2231 pub(crate) name: Symbol,
2232 pub(crate) args: GenericArgs,
2233}
2234
2235#[derive(Clone, Debug)]
2236pub(crate) enum TypeAliasInnerType {
2237 Enum { variants: IndexVec<VariantIdx, Item>, is_non_exhaustive: bool },
2238 Union { fields: Vec<Item> },
2239 Struct { ctor_kind: Option<CtorKind>, fields: Vec<Item> },
2240}
2241
2242impl TypeAliasInnerType {
2243 fn has_stripped_entries(&self) -> Option<bool> {
2244 Some(match self {
2245 Self::Enum { variants, .. } => variants.iter().any(|v| v.is_stripped()),
2246 Self::Union { fields } | Self::Struct { fields, .. } => {
2247 fields.iter().any(|f| f.is_stripped())
2248 }
2249 })
2250 }
2251}
2252
2253#[derive(Clone, Debug)]
2254pub(crate) struct TypeAlias {
2255 pub(crate) type_: Type,
2256 pub(crate) generics: Generics,
2257 pub(crate) inner_type: Option<TypeAliasInnerType>,
2260 pub(crate) item_type: Option<Type>,
2267}
2268
2269#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2270pub(crate) struct BareFunctionDecl {
2271 pub(crate) safety: hir::Safety,
2272 pub(crate) generic_params: Vec<GenericParamDef>,
2273 pub(crate) decl: FnDecl,
2274 pub(crate) abi: ExternAbi,
2275}
2276
2277#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2278pub(crate) struct UnsafeBinderTy {
2279 pub(crate) generic_params: Vec<GenericParamDef>,
2280 pub(crate) ty: Type,
2281}
2282
2283#[derive(Clone, Debug)]
2284pub(crate) struct Static {
2285 pub(crate) type_: Box<Type>,
2286 pub(crate) mutability: Mutability,
2287 pub(crate) expr: Option<BodyId>,
2288}
2289
2290#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2291pub(crate) struct Constant {
2292 pub(crate) generics: Generics,
2293 pub(crate) kind: ConstantKind,
2294 pub(crate) type_: Type,
2295}
2296
2297#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2298pub(crate) enum Term {
2299 Type(Type),
2300 Constant(ConstantKind),
2301}
2302
2303impl Term {
2304 pub(crate) fn ty(&self) -> Option<&Type> {
2305 if let Term::Type(ty) = self { Some(ty) } else { None }
2306 }
2307}
2308
2309impl From<Type> for Term {
2310 fn from(ty: Type) -> Self {
2311 Term::Type(ty)
2312 }
2313}
2314
2315#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2316pub(crate) enum ConstantKind {
2317 TyConst { expr: Box<str> },
2323 Path { path: Box<str> },
2326 Anonymous { body: BodyId },
2330 Extern { def_id: DefId },
2332 Local { def_id: DefId, body: BodyId },
2334 Infer,
2336}
2337
2338impl ConstantKind {
2339 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2340 match *self {
2341 ConstantKind::TyConst { ref expr } => expr.to_string(),
2342 ConstantKind::Path { ref path } => path.to_string(),
2343 ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2344 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2345 rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body))
2346 }
2347 ConstantKind::Infer => "_".to_string(),
2348 }
2349 }
2350
2351 pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2352 match *self {
2353 ConstantKind::TyConst { .. }
2354 | ConstantKind::Path { .. }
2355 | ConstantKind::Anonymous { .. }
2356 | ConstantKind::Infer => None,
2357 ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2358 print_evaluated_const(tcx, def_id, true, true)
2359 }
2360 }
2361 }
2362
2363 pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2364 match *self {
2365 ConstantKind::TyConst { .. }
2366 | ConstantKind::Extern { .. }
2367 | ConstantKind::Path { .. }
2368 | ConstantKind::Infer => false,
2369 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2370 is_literal_expr(tcx, body.hir_id)
2371 }
2372 }
2373 }
2374}
2375
2376#[derive(Clone, Debug)]
2377pub(crate) struct Impl {
2378 pub(crate) safety: hir::Safety,
2379 pub(crate) generics: Generics,
2380 pub(crate) trait_: Option<Path>,
2381 pub(crate) for_: Type,
2382 pub(crate) items: Vec<Item>,
2383 pub(crate) polarity: ty::ImplPolarity,
2384 pub(crate) kind: ImplKind,
2385 pub(crate) is_deprecated: bool,
2386}
2387
2388impl Impl {
2389 pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxIndexSet<Symbol> {
2390 self.trait_
2391 .as_ref()
2392 .map(|t| t.def_id())
2393 .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name()).collect())
2394 .unwrap_or_default()
2395 }
2396
2397 pub(crate) fn is_negative_trait_impl(&self) -> bool {
2398 matches!(self.polarity, ty::ImplPolarity::Negative)
2399 }
2400}
2401
2402#[derive(Clone, Debug)]
2403pub(crate) enum ImplKind {
2404 Normal,
2405 Auto,
2406 FakeVariadic,
2407 Blanket(Box<Type>),
2408}
2409
2410impl ImplKind {
2411 pub(crate) fn is_auto(&self) -> bool {
2412 matches!(self, ImplKind::Auto)
2413 }
2414
2415 pub(crate) fn is_blanket(&self) -> bool {
2416 matches!(self, ImplKind::Blanket(_))
2417 }
2418
2419 pub(crate) fn is_fake_variadic(&self) -> bool {
2420 matches!(self, ImplKind::FakeVariadic)
2421 }
2422
2423 pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
2424 match self {
2425 ImplKind::Blanket(ty) => Some(ty),
2426 _ => None,
2427 }
2428 }
2429}
2430
2431#[derive(Clone, Debug)]
2432pub(crate) struct Import {
2433 pub(crate) kind: ImportKind,
2434 pub(crate) source: ImportSource,
2436 pub(crate) should_be_displayed: bool,
2437}
2438
2439impl Import {
2440 pub(crate) fn new_simple(
2441 name: Symbol,
2442 source: ImportSource,
2443 should_be_displayed: bool,
2444 ) -> Self {
2445 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2446 }
2447
2448 pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2449 Self { kind: ImportKind::Glob, source, should_be_displayed }
2450 }
2451
2452 pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool {
2453 self.source.did.is_some_and(|did| tcx.is_doc_hidden(did))
2454 }
2455}
2456
2457#[derive(Clone, Debug)]
2458pub(crate) enum ImportKind {
2459 Simple(Symbol),
2461 Glob,
2463}
2464
2465#[derive(Clone, Debug)]
2466pub(crate) struct ImportSource {
2467 pub(crate) path: Path,
2468 pub(crate) did: Option<DefId>,
2469}
2470
2471#[derive(Clone, Debug)]
2472pub(crate) struct Macro {
2473 pub(crate) source: String,
2474 pub(crate) macro_rules: bool,
2476}
2477
2478#[derive(Clone, Debug)]
2479pub(crate) struct ProcMacro {
2480 pub(crate) kind: MacroKind,
2481 pub(crate) helpers: Vec<Symbol>,
2482}
2483
2484#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2495pub(crate) struct AssocItemConstraint {
2496 pub(crate) assoc: PathSegment,
2497 pub(crate) kind: AssocItemConstraintKind,
2498}
2499
2500#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2502pub(crate) enum AssocItemConstraintKind {
2503 Equality { term: Term },
2504 Bound { bounds: Vec<GenericBound> },
2505}
2506
2507#[cfg(target_pointer_width = "64")]
2509mod size_asserts {
2510 use rustc_data_structures::static_assert_size;
2511
2512 use super::*;
2513 static_assert_size!(Crate, 16); static_assert_size!(DocFragment, 48);
2516 static_assert_size!(GenericArg, 32);
2517 static_assert_size!(GenericArgs, 24);
2518 static_assert_size!(GenericParamDef, 40);
2519 static_assert_size!(Generics, 16);
2520 static_assert_size!(Item, 8);
2521 static_assert_size!(ItemInner, 144);
2522 static_assert_size!(ItemKind, 48);
2523 static_assert_size!(PathSegment, 32);
2524 static_assert_size!(Type, 32);
2525 }