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 { always: false }
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: hir::Constness::NotConst,
858 asyncness: hir::IsAsync::NotAsync,
859 }
860 }
861 ItemKind::FunctionItem(_)
862 | ItemKind::MethodItem(..)
863 | ItemKind::RequiredMethodItem(..) => {
864 let def_id = self.def_id().unwrap();
865 build_fn_header(def_id, tcx, tcx.asyncness(def_id))
866 }
867 _ => return None,
868 };
869 Some(header)
870 }
871
872 pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option<Visibility<DefId>> {
875 let def_id = match self.item_id {
876 ItemId::Auto { .. } | ItemId::Blanket { .. } => return None,
878 ItemId::DefId(def_id) => def_id,
879 };
880
881 match self.kind {
882 ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) | ItemKind::AttributeItem => {
886 return Some(Visibility::Public);
887 }
888 StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => {
890 return None;
891 }
892 VariantItem(..) | ImplItem(..) => return None,
894 RequiredAssocConstItem(..)
896 | ProvidedAssocConstItem(..)
897 | ImplAssocConstItem(..)
898 | AssocTypeItem(..)
899 | RequiredAssocTypeItem(..)
900 | RequiredMethodItem(..)
901 | MethodItem(..) => {
902 match tcx.associated_item(def_id).container {
903 ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) => {
906 return None;
907 }
908 ty::AssocContainer::InherentImpl => {}
909 }
910 }
911 _ => {}
912 }
913 let def_id = match self.inline_stmt_id {
914 Some(inlined) => inlined.to_def_id(),
915 None => def_id,
916 };
917 Some(tcx.visibility(def_id))
918 }
919
920 pub fn is_doc_hidden(&self) -> bool {
921 self.attrs.is_doc_hidden()
922 }
923
924 pub fn def_id(&self) -> Option<DefId> {
925 self.item_id.as_def_id()
926 }
927}
928
929#[derive(Clone, Debug)]
930pub(crate) enum ItemKind {
931 ExternCrateItem {
932 src: Option<Symbol>,
934 },
935 ImportItem(Import),
936 StructItem(Struct),
937 UnionItem(Union),
938 EnumItem(Enum),
939 FunctionItem(Box<Function>),
940 ModuleItem(Module),
941 TypeAliasItem(Box<TypeAlias>),
942 StaticItem(Static),
943 TraitItem(Box<Trait>),
944 TraitAliasItem(TraitAlias),
945 ImplItem(Box<Impl>),
946 PlaceholderImplItem,
949 RequiredMethodItem(Box<Function>, Defaultness),
951 MethodItem(Box<Function>, Defaultness),
955 StructFieldItem(Type),
956 VariantItem(Variant),
957 ForeignFunctionItem(Box<Function>, hir::Safety),
959 ForeignStaticItem(Static, hir::Safety),
961 ForeignTypeItem,
963 MacroItem(Macro, MacroKinds),
970 ProcMacroItem(ProcMacro),
971 PrimitiveItem(PrimitiveType),
972 RequiredAssocConstItem(Generics, Box<Type>),
974 ConstantItem(Box<Constant>),
975 ProvidedAssocConstItem(Box<Constant>),
977 ImplAssocConstItem(Box<Constant>),
979 RequiredAssocTypeItem(Generics, Vec<GenericBound>),
983 AssocTypeItem(Box<TypeAlias>, Vec<GenericBound>),
985 StrippedItem(Box<ItemKind>),
987 KeywordItem,
990 AttributeItem,
993}
994
995impl ItemKind {
996 pub(crate) fn inner_items(&self) -> impl Iterator<Item = &Item> {
999 match self {
1000 StructItem(s) => s.fields.iter(),
1001 UnionItem(u) => u.fields.iter(),
1002 VariantItem(v) => match &v.kind {
1003 VariantKind::CLike => [].iter(),
1004 VariantKind::Tuple(t) => t.iter(),
1005 VariantKind::Struct(s) => s.fields.iter(),
1006 },
1007 EnumItem(e) => e.variants.iter(),
1008 TraitItem(t) => t.items.iter(),
1009 ImplItem(i) => i.items.iter(),
1010 ModuleItem(m) => m.items.iter(),
1011 ExternCrateItem { .. }
1012 | ImportItem(_)
1013 | FunctionItem(_)
1014 | TypeAliasItem(_)
1015 | StaticItem(_)
1016 | ConstantItem(_)
1017 | TraitAliasItem(_)
1018 | RequiredMethodItem(..)
1019 | MethodItem(..)
1020 | StructFieldItem(_)
1021 | ForeignFunctionItem(_, _)
1022 | ForeignStaticItem(_, _)
1023 | ForeignTypeItem
1024 | MacroItem(..)
1025 | ProcMacroItem(_)
1026 | PrimitiveItem(_)
1027 | RequiredAssocConstItem(..)
1028 | ProvidedAssocConstItem(..)
1029 | ImplAssocConstItem(..)
1030 | RequiredAssocTypeItem(..)
1031 | AssocTypeItem(..)
1032 | StrippedItem(_)
1033 | KeywordItem
1034 | AttributeItem
1035 | PlaceholderImplItem => [].iter(),
1036 }
1037 }
1038}
1039
1040#[derive(Clone, Debug)]
1041pub(crate) struct Module {
1042 pub(crate) items: Vec<Item>,
1043 pub(crate) span: Span,
1044}
1045
1046#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1050pub(crate) struct ItemLink {
1051 pub(crate) link: Box<str>,
1053 pub(crate) link_text: Box<str>,
1058 pub(crate) page_id: DefId,
1062 pub(crate) fragment: Option<UrlFragment>,
1064}
1065
1066pub struct RenderedLink {
1067 pub(crate) original_text: Box<str>,
1071 pub(crate) new_text: Box<str>,
1073 pub(crate) href: String,
1075 pub(crate) tooltip: String,
1077}
1078
1079#[derive(Clone, Debug, Default)]
1082pub(crate) struct Attributes {
1083 pub(crate) doc_strings: Vec<DocFragment>,
1084 pub(crate) other_attrs: ThinVec<hir::Attribute>,
1085}
1086
1087impl Attributes {
1088 pub(crate) fn has_doc_flag<F: Fn(&DocAttribute) -> bool>(&self, callback: F) -> bool {
1089 find_attr!(&self.other_attrs, Doc(d) if callback(d))
1090 }
1091
1092 pub(crate) fn is_doc_hidden(&self) -> bool {
1093 find_attr!(&self.other_attrs, Doc(d) if d.hidden.is_some())
1094 }
1095
1096 pub(crate) fn from_hir(attrs: &[hir::Attribute]) -> Attributes {
1097 Attributes::from_hir_iter(attrs.iter().map(|attr| (attr, None)), false)
1098 }
1099
1100 pub(crate) fn from_hir_with_additional(
1101 attrs: &[hir::Attribute],
1102 (additional_attrs, def_id): (&[hir::Attribute], DefId),
1103 ) -> Attributes {
1104 let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id)));
1106 let attrs2 = attrs.iter().map(|attr| (attr, None));
1107 Attributes::from_hir_iter(attrs1.chain(attrs2), false)
1108 }
1109
1110 pub(crate) fn from_hir_iter<'a>(
1111 attrs: impl Iterator<Item = (&'a hir::Attribute, Option<DefId>)>,
1112 doc_only: bool,
1113 ) -> Attributes {
1114 let (doc_strings, other_attrs) = attrs_to_doc_fragments(attrs, doc_only);
1115 Attributes { doc_strings, other_attrs }
1116 }
1117
1118 pub(crate) fn doc_value(&self) -> String {
1120 self.opt_doc_value().unwrap_or_default()
1121 }
1122
1123 pub(crate) fn opt_doc_value(&self) -> Option<String> {
1127 (!self.doc_strings.is_empty()).then(|| {
1128 let mut res = String::new();
1129 for frag in &self.doc_strings {
1130 add_doc_fragment(&mut res, frag);
1131 }
1132 res.pop();
1133 res
1134 })
1135 }
1136
1137 pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> {
1138 let mut aliases = FxIndexSet::default();
1139
1140 for attr in &self.other_attrs {
1141 if let Attribute::Parsed(AttributeKind::Doc(d)) = attr {
1142 for (alias, _) in &d.aliases {
1143 aliases.insert(*alias);
1144 }
1145 }
1146 }
1147 aliases.into_iter().collect::<Vec<_>>().into()
1148 }
1149
1150 pub(crate) fn merge_with(&mut self, other: Self) {
1151 let Self { doc_strings, other_attrs } = other;
1152 self.doc_strings.extend(doc_strings);
1153 self.other_attrs.extend(other_attrs);
1154 }
1155}
1156
1157#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1158pub(crate) enum GenericBound {
1159 TraitBound(PolyTrait, hir::TraitBoundModifiers),
1160 Outlives(Lifetime),
1161 Use(Vec<PreciseCapturingArg>),
1163}
1164
1165impl GenericBound {
1166 pub(crate) fn sized(cx: &mut DocContext<'_>) -> GenericBound {
1167 Self::sized_with(cx, hir::TraitBoundModifiers::NONE)
1168 }
1169
1170 pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1171 Self::sized_with(
1172 cx,
1173 hir::TraitBoundModifiers {
1174 polarity: hir::BoundPolarity::Maybe(DUMMY_SP),
1175 constness: hir::BoundConstness::Never,
1176 },
1177 )
1178 }
1179
1180 fn sized_with(cx: &mut DocContext<'_>, modifiers: hir::TraitBoundModifiers) -> GenericBound {
1181 let did = cx.tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
1182 let empty = ty::Binder::dummy(ty::GenericArgs::empty());
1183 let path = clean_middle_path(cx, did, false, ThinVec::new(), empty);
1184 inline::record_extern_fqn(cx, did, ItemType::Trait);
1185 GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifiers)
1186 }
1187
1188 pub(crate) fn is_trait_bound(&self) -> bool {
1189 matches!(self, Self::TraitBound(..))
1190 }
1191
1192 pub(crate) fn is_sized_bound(&self, tcx: TyCtxt<'_>) -> bool {
1193 self.is_bounded_by_lang_item(tcx, LangItem::Sized)
1194 }
1195
1196 pub(crate) fn is_meta_sized_bound(&self, tcx: TyCtxt<'_>) -> bool {
1197 self.is_bounded_by_lang_item(tcx, LangItem::MetaSized)
1198 }
1199
1200 fn is_bounded_by_lang_item(&self, tcx: TyCtxt<'_>, lang_item: LangItem) -> bool {
1201 if let GenericBound::TraitBound(poly_trait_ref, rustc_hir::TraitBoundModifiers::NONE) = self
1202 && tcx.is_lang_item(poly_trait_ref.trait_.def_id(), lang_item)
1203 {
1204 return true;
1205 }
1206 false
1207 }
1208
1209 pub(crate) fn get_trait_path(&self) -> Option<Path> {
1210 if let GenericBound::TraitBound(poly_trait_ref, _) = self {
1211 Some(poly_trait_ref.trait_.clone())
1212 } else {
1213 None
1214 }
1215 }
1216}
1217
1218#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1219pub(crate) struct Lifetime(pub Symbol);
1220
1221impl Lifetime {
1222 pub(crate) fn statik() -> Lifetime {
1223 Lifetime(kw::StaticLifetime)
1224 }
1225
1226 pub(crate) fn elided() -> Lifetime {
1227 Lifetime(kw::UnderscoreLifetime)
1228 }
1229}
1230
1231#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1232pub(crate) enum PreciseCapturingArg {
1233 Lifetime(Lifetime),
1234 Param(Symbol),
1235}
1236
1237impl PreciseCapturingArg {
1238 pub(crate) fn name(self) -> Symbol {
1239 match self {
1240 PreciseCapturingArg::Lifetime(lt) => lt.0,
1241 PreciseCapturingArg::Param(param) => param,
1242 }
1243 }
1244}
1245
1246#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1247pub(crate) enum WherePredicate {
1248 BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
1249 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1250 ProjectionPredicate { lhs: QPathData, rhs: Term },
1251}
1252
1253impl WherePredicate {
1254 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1255 match self {
1256 WherePredicate::BoundPredicate { bounds, .. } => Some(bounds),
1257 WherePredicate::RegionPredicate { bounds, .. } => Some(bounds),
1258 _ => None,
1259 }
1260 }
1261}
1262
1263#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1264pub(crate) enum GenericParamDefKind {
1265 Lifetime { outlives: ThinVec<Lifetime> },
1266 Type { bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
1267 Const { ty: Box<Type>, default: Option<Box<String>> },
1269}
1270
1271impl GenericParamDefKind {
1272 pub(crate) fn is_type(&self) -> bool {
1273 matches!(self, GenericParamDefKind::Type { .. })
1274 }
1275}
1276
1277#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1278pub(crate) struct GenericParamDef {
1279 pub(crate) name: Symbol,
1280 pub(crate) def_id: DefId,
1281 pub(crate) kind: GenericParamDefKind,
1282}
1283
1284impl GenericParamDef {
1285 pub(crate) fn lifetime(def_id: DefId, name: Symbol) -> Self {
1286 Self { name, def_id, kind: GenericParamDefKind::Lifetime { outlives: ThinVec::new() } }
1287 }
1288
1289 pub(crate) fn is_synthetic_param(&self) -> bool {
1290 match self.kind {
1291 GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
1292 GenericParamDefKind::Type { synthetic, .. } => synthetic,
1293 }
1294 }
1295
1296 pub(crate) fn is_type(&self) -> bool {
1297 self.kind.is_type()
1298 }
1299
1300 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1301 match self.kind {
1302 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1303 _ => None,
1304 }
1305 }
1306}
1307
1308#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
1310pub(crate) struct Generics {
1311 pub(crate) params: ThinVec<GenericParamDef>,
1312 pub(crate) where_predicates: ThinVec<WherePredicate>,
1313}
1314
1315impl Generics {
1316 pub(crate) fn is_empty(&self) -> bool {
1317 self.params.is_empty() && self.where_predicates.is_empty()
1318 }
1319}
1320
1321#[derive(Clone, Debug)]
1322pub(crate) struct Function {
1323 pub(crate) decl: FnDecl,
1324 pub(crate) generics: Generics,
1325}
1326
1327#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1328pub(crate) struct FnDecl {
1329 pub(crate) inputs: Vec<Parameter>,
1330 pub(crate) output: Type,
1331 pub(crate) c_variadic: bool,
1332}
1333
1334impl FnDecl {
1335 pub(crate) fn receiver_type(&self) -> Option<&Type> {
1336 self.inputs.first().and_then(|v| v.to_receiver())
1337 }
1338}
1339
1340#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1342pub(crate) struct Parameter {
1343 pub(crate) name: Option<Symbol>,
1344 pub(crate) type_: Type,
1345 pub(crate) is_const: bool,
1348}
1349
1350impl Parameter {
1351 pub(crate) fn to_receiver(&self) -> Option<&Type> {
1352 if self.name == Some(kw::SelfLower) { Some(&self.type_) } else { None }
1353 }
1354}
1355
1356#[derive(Clone, Debug)]
1357pub(crate) struct Trait {
1358 pub(crate) def_id: DefId,
1359 pub(crate) items: Vec<Item>,
1360 pub(crate) generics: Generics,
1361 pub(crate) bounds: Vec<GenericBound>,
1362}
1363
1364impl Trait {
1365 pub(crate) fn is_auto(&self, tcx: TyCtxt<'_>) -> bool {
1366 tcx.trait_is_auto(self.def_id)
1367 }
1368 pub(crate) fn is_notable_trait(&self, tcx: TyCtxt<'_>) -> bool {
1369 tcx.is_doc_notable_trait(self.def_id)
1370 }
1371 pub(crate) fn safety(&self, tcx: TyCtxt<'_>) -> hir::Safety {
1372 tcx.trait_def(self.def_id).safety
1373 }
1374 pub(crate) fn is_dyn_compatible(&self, tcx: TyCtxt<'_>) -> bool {
1375 tcx.is_dyn_compatible(self.def_id)
1376 }
1377 pub(crate) fn is_deprecated(&self, tcx: TyCtxt<'_>) -> bool {
1378 tcx.lookup_deprecation(self.def_id).is_some_and(|deprecation| deprecation.is_in_effect())
1379 }
1380}
1381
1382#[derive(Clone, Debug)]
1383pub(crate) struct TraitAlias {
1384 pub(crate) generics: Generics,
1385 pub(crate) bounds: Vec<GenericBound>,
1386}
1387
1388#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1390pub(crate) struct PolyTrait {
1391 pub(crate) trait_: Path,
1392 pub(crate) generic_params: Vec<GenericParamDef>,
1393}
1394
1395#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1397pub(crate) enum Type {
1398 Path {
1403 path: Path,
1404 },
1405 DynTrait(Vec<PolyTrait>, Option<Lifetime>),
1407 Generic(Symbol),
1409 SelfTy,
1411 Primitive(PrimitiveType),
1413 BareFunction(Box<BareFunctionDecl>),
1415 Tuple(Vec<Type>),
1417 Slice(Box<Type>),
1419 Array(Box<Type>, Box<str>),
1423 Pat(Box<Type>, Box<str>),
1424 FieldOf(Box<Type>, Box<str>),
1425 RawPointer(Mutability, Box<Type>),
1427 BorrowedRef {
1429 lifetime: Option<Lifetime>,
1430 mutability: Mutability,
1431 type_: Box<Type>,
1432 },
1433
1434 QPath(Box<QPathData>),
1436
1437 Infer,
1439
1440 ImplTrait(Vec<GenericBound>),
1442
1443 UnsafeBinder(Box<UnsafeBinderTy>),
1444}
1445
1446impl Type {
1447 pub(crate) fn without_borrowed_ref(&self) -> &Type {
1449 let mut result = self;
1450 while let Type::BorrowedRef { type_, .. } = result {
1451 result = type_;
1452 }
1453 result
1454 }
1455
1456 pub(crate) fn is_borrowed_ref(&self) -> bool {
1457 matches!(self, Type::BorrowedRef { .. })
1458 }
1459
1460 fn is_type_alias(&self) -> bool {
1461 matches!(self, Type::Path { path: Path { res: Res::Def(DefKind::TyAlias, _), .. } })
1462 }
1463
1464 pub(crate) fn is_doc_subtype_of(&self, other: &Self, cache: &Cache) -> bool {
1485 let (self_cleared, other_cleared) = if !self.is_borrowed_ref() || !other.is_borrowed_ref() {
1488 (self.without_borrowed_ref(), other.without_borrowed_ref())
1489 } else {
1490 (self, other)
1491 };
1492
1493 if self_cleared.is_type_alias() || other_cleared.is_type_alias() {
1499 return true;
1500 }
1501
1502 match (self_cleared, other_cleared) {
1503 (Type::Tuple(a), Type::Tuple(b)) => {
1505 a.iter().eq_by(b, |a, b| a.is_doc_subtype_of(b, cache))
1506 }
1507 (Type::Slice(a), Type::Slice(b)) => a.is_doc_subtype_of(b, cache),
1508 (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_doc_subtype_of(b, cache),
1509 (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
1510 mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache)
1511 }
1512 (
1513 Type::BorrowedRef { mutability, type_, .. },
1514 Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
1515 ) => mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache),
1516 (Type::Infer, _) | (_, Type::Infer) => true,
1518 (_, Type::Generic(_)) => true,
1521 (Type::Generic(_), _) => false,
1522 (Type::SelfTy, Type::SelfTy) => true,
1524 (Type::Path { path: a }, Type::Path { path: b }) => {
1526 a.def_id() == b.def_id()
1527 && a.generics()
1528 .zip(b.generics())
1529 .map(|(ag, bg)| ag.zip(bg).all(|(at, bt)| at.is_doc_subtype_of(bt, cache)))
1530 .unwrap_or(true)
1531 }
1532 (a, b) => a
1534 .def_id(cache)
1535 .and_then(|a| Some((a, b.def_id(cache)?)))
1536 .map(|(a, b)| a == b)
1537 .unwrap_or(false),
1538 }
1539 }
1540
1541 pub(crate) fn primitive_type(&self) -> Option<PrimitiveType> {
1542 match *self {
1543 Primitive(p) | BorrowedRef { type_: Primitive(p), .. } => Some(p),
1544 Slice(..) | BorrowedRef { type_: Slice(..), .. } => Some(PrimitiveType::Slice),
1545 Array(..) | BorrowedRef { type_: Array(..), .. } => Some(PrimitiveType::Array),
1546 Tuple(ref tys) => {
1547 if tys.is_empty() {
1548 Some(PrimitiveType::Unit)
1549 } else {
1550 Some(PrimitiveType::Tuple)
1551 }
1552 }
1553 RawPointer(..) => Some(PrimitiveType::RawPointer),
1554 BareFunction(..) => Some(PrimitiveType::Fn),
1555 _ => None,
1556 }
1557 }
1558
1559 pub(crate) fn sugared_async_return_type(self) -> Type {
1569 if let Type::ImplTrait(mut v) = self
1570 && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = v.pop()
1571 && let Some(segment) = trait_.segments.pop()
1572 && let GenericArgs::AngleBracketed { mut constraints, .. } = segment.args
1573 && let Some(constraint) = constraints.pop()
1574 && let AssocItemConstraintKind::Equality { term } = constraint.kind
1575 && let Term::Type(ty) = term
1576 {
1577 ty
1578 } else {
1579 panic!("unexpected async fn return type")
1580 }
1581 }
1582
1583 pub(crate) fn is_assoc_ty(&self) -> bool {
1585 match self {
1586 Type::Path { path, .. } => path.is_assoc_ty(),
1587 _ => false,
1588 }
1589 }
1590
1591 pub(crate) fn is_self_type(&self) -> bool {
1592 matches!(*self, Type::SelfTy)
1593 }
1594
1595 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
1596 match self {
1597 Type::Path { path, .. } => path.generic_args(),
1598 _ => None,
1599 }
1600 }
1601
1602 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
1603 match self {
1604 Type::Path { path, .. } => path.generics(),
1605 _ => None,
1606 }
1607 }
1608
1609 pub(crate) fn is_full_generic(&self) -> bool {
1610 matches!(self, Type::Generic(_))
1611 }
1612
1613 pub(crate) fn is_unit(&self) -> bool {
1614 matches!(self, Type::Tuple(v) if v.is_empty())
1615 }
1616
1617 pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
1621 let t: PrimitiveType = match self {
1622 Type::Path { path } => return Some(path.def_id()),
1623 DynTrait(bounds, _) => return bounds.first().map(|b| b.trait_.def_id()),
1624 Primitive(p) => return cache.primitive_locations.get(p).cloned(),
1625 BorrowedRef { type_: Generic(..), .. } => PrimitiveType::Reference,
1626 BorrowedRef { type_, .. } => return type_.def_id(cache),
1627 Tuple(tys) => {
1628 if tys.is_empty() {
1629 PrimitiveType::Unit
1630 } else {
1631 PrimitiveType::Tuple
1632 }
1633 }
1634 BareFunction(..) => PrimitiveType::Fn,
1635 Slice(..) => PrimitiveType::Slice,
1636 Array(..) => PrimitiveType::Array,
1637 Type::Pat(..) => PrimitiveType::Pat,
1638 Type::FieldOf(..) => PrimitiveType::FieldOf,
1639 RawPointer(..) => PrimitiveType::RawPointer,
1640 QPath(QPathData { self_type, .. }) => return self_type.def_id(cache),
1641 Generic(_) | SelfTy | Infer | ImplTrait(_) | UnsafeBinder(_) => return None,
1642 };
1643 Primitive(t).def_id(cache)
1644 }
1645}
1646
1647#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1648pub(crate) struct QPathData {
1649 pub assoc: PathSegment,
1650 pub self_type: Type,
1651 pub should_fully_qualify: bool,
1653 pub trait_: Option<Path>,
1654}
1655
1656#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1663pub(crate) enum PrimitiveType {
1664 Isize,
1665 I8,
1666 I16,
1667 I32,
1668 I64,
1669 I128,
1670 Usize,
1671 U8,
1672 U16,
1673 U32,
1674 U64,
1675 U128,
1676 F16,
1677 F32,
1678 F64,
1679 F128,
1680 Char,
1681 Bool,
1682 Str,
1683 Slice,
1684 Array,
1685 Pat,
1686 FieldOf,
1687 Tuple,
1688 Unit,
1689 RawPointer,
1690 Reference,
1691 Fn,
1692 Never,
1693}
1694
1695type SimplifiedTypes = FxIndexMap<PrimitiveType, ArrayVec<SimplifiedType, 3>>;
1696impl PrimitiveType {
1697 pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1698 use ast::{FloatTy, IntTy, UintTy};
1699 match prim {
1700 hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1701 hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1702 hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1703 hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1704 hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1705 hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1706 hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1707 hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1708 hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1709 hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1710 hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1711 hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1712 hir::PrimTy::Float(FloatTy::F16) => PrimitiveType::F16,
1713 hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1714 hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1715 hir::PrimTy::Float(FloatTy::F128) => PrimitiveType::F128,
1716 hir::PrimTy::Str => PrimitiveType::Str,
1717 hir::PrimTy::Bool => PrimitiveType::Bool,
1718 hir::PrimTy::Char => PrimitiveType::Char,
1719 }
1720 }
1721
1722 pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1723 match s {
1724 sym::isize => Some(PrimitiveType::Isize),
1725 sym::i8 => Some(PrimitiveType::I8),
1726 sym::i16 => Some(PrimitiveType::I16),
1727 sym::i32 => Some(PrimitiveType::I32),
1728 sym::i64 => Some(PrimitiveType::I64),
1729 sym::i128 => Some(PrimitiveType::I128),
1730 sym::usize => Some(PrimitiveType::Usize),
1731 sym::u8 => Some(PrimitiveType::U8),
1732 sym::u16 => Some(PrimitiveType::U16),
1733 sym::u32 => Some(PrimitiveType::U32),
1734 sym::u64 => Some(PrimitiveType::U64),
1735 sym::u128 => Some(PrimitiveType::U128),
1736 sym::bool => Some(PrimitiveType::Bool),
1737 sym::char => Some(PrimitiveType::Char),
1738 sym::str => Some(PrimitiveType::Str),
1739 sym::f16 => Some(PrimitiveType::F16),
1740 sym::f32 => Some(PrimitiveType::F32),
1741 sym::f64 => Some(PrimitiveType::F64),
1742 sym::f128 => Some(PrimitiveType::F128),
1743 sym::array => Some(PrimitiveType::Array),
1744 sym::slice => Some(PrimitiveType::Slice),
1745 sym::tuple => Some(PrimitiveType::Tuple),
1746 sym::unit => Some(PrimitiveType::Unit),
1747 sym::pointer => Some(PrimitiveType::RawPointer),
1748 sym::reference => Some(PrimitiveType::Reference),
1749 kw::Fn => Some(PrimitiveType::Fn),
1750 sym::never => Some(PrimitiveType::Never),
1751 _ => None,
1752 }
1753 }
1754
1755 pub(crate) fn from_ty(ty: Ty<'_>) -> Option<Self> {
1756 match ty.kind() {
1757 ty::Array(..) => Some(Self::Array),
1758 ty::Bool => Some(Self::Bool),
1759 ty::Char => Some(Self::Char),
1760 ty::FnDef(..) | ty::FnPtr(..) => Some(Self::Fn),
1761 ty::Int(int) => Some(Self::from(*int)),
1762 ty::Uint(uint) => Some(Self::from(*uint)),
1763 ty::Float(float) => Some(Self::from(*float)),
1764 ty::Never => Some(Self::Never),
1765 ty::Pat(..) => Some(Self::Pat),
1766 ty::RawPtr(..) => Some(Self::RawPointer),
1767 ty::Ref(..) => Some(Self::Reference),
1768 ty::Slice(..) => Some(Self::Slice),
1769 ty::Str => Some(Self::Str),
1770 ty::Tuple(elems) if elems.is_empty() => Some(Self::Unit),
1771 ty::Tuple(_) => Some(Self::Tuple),
1772 ty::Adt(..)
1773 | ty::Alias(..)
1774 | ty::Bound(..)
1775 | ty::Closure(..)
1776 | ty::Coroutine(..)
1777 | ty::CoroutineClosure(..)
1778 | ty::CoroutineWitness(..)
1779 | ty::Dynamic(..)
1780 | ty::Error(..)
1781 | ty::Foreign(..)
1782 | ty::Infer(..)
1783 | ty::Param(..)
1784 | ty::Placeholder(..)
1785 | ty::UnsafeBinder(..) => None,
1786 }
1787 }
1788
1789 pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
1790 use PrimitiveType::*;
1791 use ty::{FloatTy, IntTy, UintTy};
1792 static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
1793
1794 let single = |x| iter::once(x).collect();
1795 CELL.get_or_init(move || {
1796 map! {
1797 Isize => single(SimplifiedType::Int(IntTy::Isize)),
1798 I8 => single(SimplifiedType::Int(IntTy::I8)),
1799 I16 => single(SimplifiedType::Int(IntTy::I16)),
1800 I32 => single(SimplifiedType::Int(IntTy::I32)),
1801 I64 => single(SimplifiedType::Int(IntTy::I64)),
1802 I128 => single(SimplifiedType::Int(IntTy::I128)),
1803 Usize => single(SimplifiedType::Uint(UintTy::Usize)),
1804 U8 => single(SimplifiedType::Uint(UintTy::U8)),
1805 U16 => single(SimplifiedType::Uint(UintTy::U16)),
1806 U32 => single(SimplifiedType::Uint(UintTy::U32)),
1807 U64 => single(SimplifiedType::Uint(UintTy::U64)),
1808 U128 => single(SimplifiedType::Uint(UintTy::U128)),
1809 F16 => single(SimplifiedType::Float(FloatTy::F16)),
1810 F32 => single(SimplifiedType::Float(FloatTy::F32)),
1811 F64 => single(SimplifiedType::Float(FloatTy::F64)),
1812 F128 => single(SimplifiedType::Float(FloatTy::F128)),
1813 Str => single(SimplifiedType::Str),
1814 Bool => single(SimplifiedType::Bool),
1815 Char => single(SimplifiedType::Char),
1816 Array => single(SimplifiedType::Array),
1817 Slice => single(SimplifiedType::Slice),
1818 Tuple => [SimplifiedType::Tuple(1), SimplifiedType::Tuple(2), SimplifiedType::Tuple(3)].into(),
1824 Unit => single(SimplifiedType::Tuple(0)),
1825 RawPointer => [SimplifiedType::Ptr(Mutability::Not), SimplifiedType::Ptr(Mutability::Mut)].into_iter().collect(),
1826 Reference => [SimplifiedType::Ref(Mutability::Not), SimplifiedType::Ref(Mutability::Mut)].into_iter().collect(),
1827 Fn => single(SimplifiedType::Function(1)),
1830 Never => single(SimplifiedType::Never),
1831 }
1832 })
1833 }
1834
1835 pub(crate) fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = DefId> + 'tcx {
1836 Self::simplified_types()
1837 .get(self)
1838 .into_iter()
1839 .flatten()
1840 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1841 .copied()
1842 }
1843
1844 pub(crate) fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> {
1845 Self::simplified_types()
1846 .values()
1847 .flatten()
1848 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1849 .copied()
1850 }
1851
1852 pub(crate) fn as_sym(&self) -> Symbol {
1853 use PrimitiveType::*;
1854 match self {
1855 Isize => sym::isize,
1856 I8 => sym::i8,
1857 I16 => sym::i16,
1858 I32 => sym::i32,
1859 I64 => sym::i64,
1860 I128 => sym::i128,
1861 Usize => sym::usize,
1862 U8 => sym::u8,
1863 U16 => sym::u16,
1864 U32 => sym::u32,
1865 U64 => sym::u64,
1866 U128 => sym::u128,
1867 F16 => sym::f16,
1868 F32 => sym::f32,
1869 F64 => sym::f64,
1870 F128 => sym::f128,
1871 Str => sym::str,
1872 Bool => sym::bool,
1873 Char => sym::char,
1874 Array => sym::array,
1875 Pat => sym::pat,
1876 FieldOf => sym::field_of,
1877 Slice => sym::slice,
1878 Tuple => sym::tuple,
1879 Unit => sym::unit,
1880 RawPointer => sym::pointer,
1881 Reference => sym::reference,
1882 Fn => kw::Fn,
1883 Never => sym::never,
1884 }
1885 }
1886
1887 pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxIndexMap<PrimitiveType, DefId> {
1899 static PRIMITIVE_LOCATIONS: OnceCell<FxIndexMap<PrimitiveType, DefId>> = OnceCell::new();
1900 PRIMITIVE_LOCATIONS.get_or_init(|| {
1901 let mut primitive_locations = FxIndexMap::default();
1902 for &crate_num in tcx.crates(()) {
1905 let e = ExternalCrate { crate_num };
1906 let crate_name = e.name(tcx);
1907 debug!(?crate_num, ?crate_name);
1908 for (def_id, prim) in e.primitives(tcx) {
1909 if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1911 continue;
1912 }
1913 primitive_locations.insert(prim, def_id);
1914 }
1915 }
1916 let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1917 for (def_id, prim) in local_primitives {
1918 primitive_locations.insert(prim, def_id);
1919 }
1920 primitive_locations
1921 })
1922 }
1923}
1924
1925impl From<ty::IntTy> for PrimitiveType {
1926 fn from(int_ty: ty::IntTy) -> PrimitiveType {
1927 match int_ty {
1928 ty::IntTy::Isize => PrimitiveType::Isize,
1929 ty::IntTy::I8 => PrimitiveType::I8,
1930 ty::IntTy::I16 => PrimitiveType::I16,
1931 ty::IntTy::I32 => PrimitiveType::I32,
1932 ty::IntTy::I64 => PrimitiveType::I64,
1933 ty::IntTy::I128 => PrimitiveType::I128,
1934 }
1935 }
1936}
1937
1938impl From<ty::UintTy> for PrimitiveType {
1939 fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1940 match uint_ty {
1941 ty::UintTy::Usize => PrimitiveType::Usize,
1942 ty::UintTy::U8 => PrimitiveType::U8,
1943 ty::UintTy::U16 => PrimitiveType::U16,
1944 ty::UintTy::U32 => PrimitiveType::U32,
1945 ty::UintTy::U64 => PrimitiveType::U64,
1946 ty::UintTy::U128 => PrimitiveType::U128,
1947 }
1948 }
1949}
1950
1951impl From<ty::FloatTy> for PrimitiveType {
1952 fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1953 match float_ty {
1954 ty::FloatTy::F16 => PrimitiveType::F16,
1955 ty::FloatTy::F32 => PrimitiveType::F32,
1956 ty::FloatTy::F64 => PrimitiveType::F64,
1957 ty::FloatTy::F128 => PrimitiveType::F128,
1958 }
1959 }
1960}
1961
1962impl From<hir::PrimTy> for PrimitiveType {
1963 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1964 match prim_ty {
1965 hir::PrimTy::Int(int_ty) => int_ty.into(),
1966 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1967 hir::PrimTy::Float(float_ty) => float_ty.into(),
1968 hir::PrimTy::Str => PrimitiveType::Str,
1969 hir::PrimTy::Bool => PrimitiveType::Bool,
1970 hir::PrimTy::Char => PrimitiveType::Char,
1971 }
1972 }
1973}
1974
1975#[derive(Clone, Debug)]
1976pub(crate) struct Struct {
1977 pub(crate) ctor_kind: Option<CtorKind>,
1978 pub(crate) generics: Generics,
1979 pub(crate) fields: ThinVec<Item>,
1980}
1981
1982impl Struct {
1983 pub(crate) fn has_stripped_entries(&self) -> bool {
1984 self.fields.iter().any(|f| f.is_stripped())
1985 }
1986}
1987
1988#[derive(Clone, Debug)]
1989pub(crate) struct Union {
1990 pub(crate) generics: Generics,
1991 pub(crate) fields: Vec<Item>,
1992}
1993
1994impl Union {
1995 pub(crate) fn has_stripped_entries(&self) -> bool {
1996 self.fields.iter().any(|f| f.is_stripped())
1997 }
1998}
1999
2000#[derive(Clone, Debug)]
2004pub(crate) struct VariantStruct {
2005 pub(crate) fields: ThinVec<Item>,
2006}
2007
2008impl VariantStruct {
2009 pub(crate) fn has_stripped_entries(&self) -> bool {
2010 self.fields.iter().any(|f| f.is_stripped())
2011 }
2012}
2013
2014#[derive(Clone, Debug)]
2015pub(crate) struct Enum {
2016 pub(crate) variants: IndexVec<VariantIdx, Item>,
2017 pub(crate) generics: Generics,
2018}
2019
2020impl Enum {
2021 pub(crate) fn has_stripped_entries(&self) -> bool {
2022 self.variants.iter().any(|f| f.is_stripped())
2023 }
2024
2025 pub(crate) fn non_stripped_variants(&self) -> impl Iterator<Item = &Item> {
2026 self.variants.iter().filter(|v| !v.is_stripped())
2027 }
2028}
2029
2030#[derive(Clone, Debug)]
2031pub(crate) struct Variant {
2032 pub kind: VariantKind,
2033 pub discriminant: Option<Discriminant>,
2034}
2035
2036#[derive(Clone, Debug)]
2037pub(crate) enum VariantKind {
2038 CLike,
2039 Tuple(ThinVec<Item>),
2040 Struct(VariantStruct),
2041}
2042
2043impl Variant {
2044 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
2045 match &self.kind {
2046 VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()),
2047 VariantKind::CLike | VariantKind::Tuple(_) => None,
2048 }
2049 }
2050}
2051
2052#[derive(Clone, Debug)]
2053pub(crate) struct Discriminant {
2054 pub(super) expr: Option<BodyId>,
2057 pub(super) value: DefId,
2058}
2059
2060impl Discriminant {
2061 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
2064 self.expr
2065 .map(|body| rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body)))
2066 }
2067 pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String {
2068 print_evaluated_const(tcx, self.value, with_underscores, false).unwrap()
2069 }
2070}
2071
2072#[derive(Copy, Clone, Debug)]
2075pub(crate) struct Span(rustc_span::Span);
2076
2077impl Span {
2078 pub(crate) fn new(sp: rustc_span::Span) -> Self {
2083 Self(sp.source_callsite())
2084 }
2085
2086 pub(crate) fn inner(&self) -> rustc_span::Span {
2087 self.0
2088 }
2089
2090 pub(crate) fn filename(&self, sess: &Session) -> FileName {
2091 sess.source_map().span_to_filename(self.0)
2092 }
2093
2094 pub(crate) fn lo(&self, sess: &Session) -> Loc {
2095 sess.source_map().lookup_char_pos(self.0.lo())
2096 }
2097
2098 pub(crate) fn hi(&self, sess: &Session) -> Loc {
2099 sess.source_map().lookup_char_pos(self.0.hi())
2100 }
2101
2102 pub(crate) fn cnum(&self, sess: &Session) -> CrateNum {
2103 self.lo(sess).file.cnum
2105 }
2106}
2107
2108#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2109pub(crate) struct Path {
2110 pub(crate) res: Res,
2111 pub(crate) segments: ThinVec<PathSegment>,
2112}
2113
2114impl Path {
2115 pub(crate) fn def_id(&self) -> DefId {
2116 self.res.def_id()
2117 }
2118
2119 pub(crate) fn last_opt(&self) -> Option<Symbol> {
2120 self.segments.last().map(|s| s.name)
2121 }
2122
2123 pub(crate) fn last(&self) -> Symbol {
2124 self.last_opt().expect("segments were empty")
2125 }
2126
2127 pub(crate) fn whole_name(&self) -> String {
2128 self.segments
2129 .iter()
2130 .map(|s| if s.name == kw::PathRoot { "" } else { s.name.as_str() })
2131 .intersperse("::")
2132 .collect()
2133 }
2134
2135 pub(crate) fn is_assoc_ty(&self) -> bool {
2137 match self.res {
2138 Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _)
2139 if self.segments.len() != 1 =>
2140 {
2141 true
2142 }
2143 Res::Def(DefKind::AssocTy, _) => true,
2144 _ => false,
2145 }
2146 }
2147
2148 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
2149 self.segments.last().map(|seg| &seg.args)
2150 }
2151
2152 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
2153 self.segments.last().and_then(|seg| {
2154 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2155 Some(args.iter().filter_map(|arg| match arg {
2156 GenericArg::Type(ty) => Some(ty),
2157 _ => None,
2158 }))
2159 } else {
2160 None
2161 }
2162 })
2163 }
2164}
2165
2166#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2167pub(crate) enum GenericArg {
2168 Lifetime(Lifetime),
2169 Type(Type),
2170 Const(Box<ConstantKind>),
2171 Infer,
2172}
2173
2174impl GenericArg {
2175 pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
2176 if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2177 }
2178
2179 pub(crate) fn as_ty(&self) -> Option<&Type> {
2180 if let Self::Type(ty) = self { Some(ty) } else { None }
2181 }
2182}
2183
2184#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2185pub(crate) enum GenericArgs {
2186 AngleBracketed { args: ThinVec<GenericArg>, constraints: ThinVec<AssocItemConstraint> },
2188 Parenthesized { inputs: ThinVec<Type>, output: Option<Box<Type>> },
2190 ReturnTypeNotation,
2192}
2193
2194impl GenericArgs {
2195 pub(crate) fn is_empty(&self) -> bool {
2196 match self {
2197 GenericArgs::AngleBracketed { args, constraints } => {
2198 args.is_empty() && constraints.is_empty()
2199 }
2200 GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
2201 GenericArgs::ReturnTypeNotation => false,
2202 }
2203 }
2204 pub(crate) fn constraints(&self) -> Box<dyn Iterator<Item = AssocItemConstraint> + '_> {
2205 match self {
2206 GenericArgs::AngleBracketed { constraints, .. } => {
2207 Box::new(constraints.iter().cloned())
2208 }
2209 GenericArgs::Parenthesized { output, .. } => Box::new(
2210 output
2211 .as_ref()
2212 .map(|ty| AssocItemConstraint {
2213 assoc: PathSegment {
2214 name: sym::Output,
2215 args: GenericArgs::AngleBracketed {
2216 args: ThinVec::new(),
2217 constraints: ThinVec::new(),
2218 },
2219 },
2220 kind: AssocItemConstraintKind::Equality {
2221 term: Term::Type((**ty).clone()),
2222 },
2223 })
2224 .into_iter(),
2225 ),
2226 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2227 }
2228 }
2229}
2230
2231impl<'a> IntoIterator for &'a GenericArgs {
2232 type IntoIter = Box<dyn Iterator<Item = GenericArg> + 'a>;
2233 type Item = GenericArg;
2234 fn into_iter(self) -> Self::IntoIter {
2235 match self {
2236 GenericArgs::AngleBracketed { args, .. } => Box::new(args.iter().cloned()),
2237 GenericArgs::Parenthesized { inputs, .. } => {
2238 Box::new(inputs.iter().cloned().map(GenericArg::Type))
2240 }
2241 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2242 }
2243 }
2244}
2245
2246#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2247pub(crate) struct PathSegment {
2248 pub(crate) name: Symbol,
2249 pub(crate) args: GenericArgs,
2250}
2251
2252#[derive(Clone, Debug)]
2253pub(crate) enum TypeAliasInnerType {
2254 Enum { variants: IndexVec<VariantIdx, Item>, is_non_exhaustive: bool },
2255 Union { fields: Vec<Item> },
2256 Struct { ctor_kind: Option<CtorKind>, fields: Vec<Item> },
2257}
2258
2259impl TypeAliasInnerType {
2260 fn has_stripped_entries(&self) -> Option<bool> {
2261 Some(match self {
2262 Self::Enum { variants, .. } => variants.iter().any(|v| v.is_stripped()),
2263 Self::Union { fields } | Self::Struct { fields, .. } => {
2264 fields.iter().any(|f| f.is_stripped())
2265 }
2266 })
2267 }
2268}
2269
2270#[derive(Clone, Debug)]
2271pub(crate) struct TypeAlias {
2272 pub(crate) type_: Type,
2273 pub(crate) generics: Generics,
2274 pub(crate) inner_type: Option<TypeAliasInnerType>,
2277 pub(crate) item_type: Option<Type>,
2284}
2285
2286#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2287pub(crate) struct BareFunctionDecl {
2288 pub(crate) safety: hir::Safety,
2289 pub(crate) generic_params: Vec<GenericParamDef>,
2290 pub(crate) decl: FnDecl,
2291 pub(crate) abi: ExternAbi,
2292}
2293
2294#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2295pub(crate) struct UnsafeBinderTy {
2296 pub(crate) generic_params: Vec<GenericParamDef>,
2297 pub(crate) ty: Type,
2298}
2299
2300#[derive(Clone, Debug)]
2301pub(crate) struct Static {
2302 pub(crate) type_: Box<Type>,
2303 pub(crate) mutability: Mutability,
2304 pub(crate) expr: Option<BodyId>,
2305}
2306
2307#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2308pub(crate) struct Constant {
2309 pub(crate) generics: Generics,
2310 pub(crate) kind: ConstantKind,
2311 pub(crate) type_: Type,
2312}
2313
2314#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2315pub(crate) enum Term {
2316 Type(Type),
2317 Constant(ConstantKind),
2318}
2319
2320impl Term {
2321 pub(crate) fn ty(&self) -> Option<&Type> {
2322 if let Term::Type(ty) = self { Some(ty) } else { None }
2323 }
2324}
2325
2326impl From<Type> for Term {
2327 fn from(ty: Type) -> Self {
2328 Term::Type(ty)
2329 }
2330}
2331
2332#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2333pub(crate) enum ConstantKind {
2334 TyConst { expr: Box<str> },
2340 Path { path: Box<str> },
2343 Anonymous { body: BodyId },
2347 Extern { def_id: DefId },
2349 Local { def_id: DefId, body: BodyId },
2351 Infer,
2353}
2354
2355impl ConstantKind {
2356 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2357 match *self {
2358 ConstantKind::TyConst { ref expr } => expr.to_string(),
2359 ConstantKind::Path { ref path } => path.to_string(),
2360 ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2361 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2362 rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body))
2363 }
2364 ConstantKind::Infer => "_".to_string(),
2365 }
2366 }
2367
2368 pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2369 match *self {
2370 ConstantKind::TyConst { .. }
2371 | ConstantKind::Path { .. }
2372 | ConstantKind::Anonymous { .. }
2373 | ConstantKind::Infer => None,
2374 ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2375 print_evaluated_const(tcx, def_id, true, true)
2376 }
2377 }
2378 }
2379
2380 pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2381 match *self {
2382 ConstantKind::TyConst { .. }
2383 | ConstantKind::Extern { .. }
2384 | ConstantKind::Path { .. }
2385 | ConstantKind::Infer => false,
2386 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2387 is_literal_expr(tcx, body.hir_id)
2388 }
2389 }
2390 }
2391}
2392
2393#[derive(Clone, Debug)]
2394pub(crate) struct Impl {
2395 pub(crate) safety: hir::Safety,
2396 pub(crate) generics: Generics,
2397 pub(crate) trait_: Option<Path>,
2398 pub(crate) for_: Type,
2399 pub(crate) items: Vec<Item>,
2400 pub(crate) polarity: ty::ImplPolarity,
2401 pub(crate) kind: ImplKind,
2402 pub(crate) is_deprecated: bool,
2403}
2404
2405impl Impl {
2406 pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxIndexSet<Symbol> {
2407 self.trait_
2408 .as_ref()
2409 .map(|t| t.def_id())
2410 .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name()).collect())
2411 .unwrap_or_default()
2412 }
2413
2414 pub(crate) fn is_negative_trait_impl(&self) -> bool {
2415 matches!(self.polarity, ty::ImplPolarity::Negative)
2416 }
2417}
2418
2419#[derive(Clone, Debug)]
2420pub(crate) enum ImplKind {
2421 Normal,
2422 Auto,
2423 FakeVariadic,
2424 Blanket(Box<Type>),
2425}
2426
2427impl ImplKind {
2428 pub(crate) fn is_auto(&self) -> bool {
2429 matches!(self, ImplKind::Auto)
2430 }
2431
2432 pub(crate) fn is_blanket(&self) -> bool {
2433 matches!(self, ImplKind::Blanket(_))
2434 }
2435
2436 pub(crate) fn is_fake_variadic(&self) -> bool {
2437 matches!(self, ImplKind::FakeVariadic)
2438 }
2439
2440 pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
2441 match self {
2442 ImplKind::Blanket(ty) => Some(ty),
2443 _ => None,
2444 }
2445 }
2446}
2447
2448#[derive(Clone, Debug)]
2449pub(crate) struct Import {
2450 pub(crate) kind: ImportKind,
2451 pub(crate) source: ImportSource,
2453 pub(crate) should_be_displayed: bool,
2454}
2455
2456impl Import {
2457 pub(crate) fn new_simple(
2458 name: Symbol,
2459 source: ImportSource,
2460 should_be_displayed: bool,
2461 ) -> Self {
2462 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2463 }
2464
2465 pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2466 Self { kind: ImportKind::Glob, source, should_be_displayed }
2467 }
2468
2469 pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool {
2470 self.source.did.is_some_and(|did| tcx.is_doc_hidden(did))
2471 }
2472}
2473
2474#[derive(Clone, Debug)]
2475pub(crate) enum ImportKind {
2476 Simple(Symbol),
2478 Glob,
2480}
2481
2482#[derive(Clone, Debug)]
2483pub(crate) struct ImportSource {
2484 pub(crate) path: Path,
2485 pub(crate) did: Option<DefId>,
2486}
2487
2488#[derive(Clone, Debug)]
2489pub(crate) struct Macro {
2490 pub(crate) source: String,
2491 pub(crate) macro_rules: bool,
2493}
2494
2495#[derive(Clone, Debug)]
2496pub(crate) struct ProcMacro {
2497 pub(crate) kind: MacroKind,
2498 pub(crate) helpers: Vec<Symbol>,
2499}
2500
2501#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2512pub(crate) struct AssocItemConstraint {
2513 pub(crate) assoc: PathSegment,
2514 pub(crate) kind: AssocItemConstraintKind,
2515}
2516
2517#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2519pub(crate) enum AssocItemConstraintKind {
2520 Equality { term: Term },
2521 Bound { bounds: Vec<GenericBound> },
2522}
2523
2524#[cfg(target_pointer_width = "64")]
2526mod size_asserts {
2527 use rustc_data_structures::static_assert_size;
2528
2529 use super::*;
2530 static_assert_size!(Crate, 16); static_assert_size!(DocFragment, 48);
2533 static_assert_size!(GenericArg, 32);
2534 static_assert_size!(GenericArgs, 24);
2535 static_assert_size!(GenericParamDef, 40);
2536 static_assert_size!(Generics, 16);
2537 static_assert_size!(Item, 8);
2538 static_assert_size!(ItemInner, 136);
2539 static_assert_size!(ItemKind, 48);
2540 static_assert_size!(PathSegment, 32);
2541 static_assert_size!(Type, 32);
2542 }