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