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