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(poly_trait_ref, rustc_hir::TraitBoundModifiers::NONE) = self
1205 && tcx.is_lang_item(poly_trait_ref.trait_.def_id(), lang_item)
1206 {
1207 return true;
1208 }
1209 false
1210 }
1211
1212 pub(crate) fn get_trait_path(&self) -> Option<Path> {
1213 if let GenericBound::TraitBound(poly_trait_ref, _) = self {
1214 Some(poly_trait_ref.trait_.clone())
1215 } else {
1216 None
1217 }
1218 }
1219}
1220
1221#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1222pub(crate) struct Lifetime(pub Symbol);
1223
1224impl Lifetime {
1225 pub(crate) fn statik() -> Lifetime {
1226 Lifetime(kw::StaticLifetime)
1227 }
1228
1229 pub(crate) fn elided() -> Lifetime {
1230 Lifetime(kw::UnderscoreLifetime)
1231 }
1232}
1233
1234#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1235pub(crate) enum PreciseCapturingArg {
1236 Lifetime(Lifetime),
1237 Param(Symbol),
1238}
1239
1240impl PreciseCapturingArg {
1241 pub(crate) fn name(self) -> Symbol {
1242 match self {
1243 PreciseCapturingArg::Lifetime(lt) => lt.0,
1244 PreciseCapturingArg::Param(param) => param,
1245 }
1246 }
1247}
1248
1249#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1250pub(crate) enum WherePredicate {
1251 BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
1252 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1253 EqPredicate { lhs: QPathData, rhs: Term },
1254}
1255
1256impl WherePredicate {
1257 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1258 match self {
1259 WherePredicate::BoundPredicate { bounds, .. } => Some(bounds),
1260 WherePredicate::RegionPredicate { bounds, .. } => Some(bounds),
1261 _ => None,
1262 }
1263 }
1264}
1265
1266#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1267pub(crate) enum GenericParamDefKind {
1268 Lifetime { outlives: ThinVec<Lifetime> },
1269 Type { bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
1270 Const { ty: Box<Type>, default: Option<Box<String>> },
1272}
1273
1274impl GenericParamDefKind {
1275 pub(crate) fn is_type(&self) -> bool {
1276 matches!(self, GenericParamDefKind::Type { .. })
1277 }
1278}
1279
1280#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1281pub(crate) struct GenericParamDef {
1282 pub(crate) name: Symbol,
1283 pub(crate) def_id: DefId,
1284 pub(crate) kind: GenericParamDefKind,
1285}
1286
1287impl GenericParamDef {
1288 pub(crate) fn lifetime(def_id: DefId, name: Symbol) -> Self {
1289 Self { name, def_id, kind: GenericParamDefKind::Lifetime { outlives: ThinVec::new() } }
1290 }
1291
1292 pub(crate) fn is_synthetic_param(&self) -> bool {
1293 match self.kind {
1294 GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
1295 GenericParamDefKind::Type { synthetic, .. } => synthetic,
1296 }
1297 }
1298
1299 pub(crate) fn is_type(&self) -> bool {
1300 self.kind.is_type()
1301 }
1302
1303 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1304 match self.kind {
1305 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1306 _ => None,
1307 }
1308 }
1309}
1310
1311#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
1313pub(crate) struct Generics {
1314 pub(crate) params: ThinVec<GenericParamDef>,
1315 pub(crate) where_predicates: ThinVec<WherePredicate>,
1316}
1317
1318impl Generics {
1319 pub(crate) fn is_empty(&self) -> bool {
1320 self.params.is_empty() && self.where_predicates.is_empty()
1321 }
1322}
1323
1324#[derive(Clone, Debug)]
1325pub(crate) struct Function {
1326 pub(crate) decl: FnDecl,
1327 pub(crate) generics: Generics,
1328}
1329
1330#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1331pub(crate) struct FnDecl {
1332 pub(crate) inputs: Vec<Parameter>,
1333 pub(crate) output: Type,
1334 pub(crate) c_variadic: bool,
1335}
1336
1337impl FnDecl {
1338 pub(crate) fn receiver_type(&self) -> Option<&Type> {
1339 self.inputs.first().and_then(|v| v.to_receiver())
1340 }
1341}
1342
1343#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1345pub(crate) struct Parameter {
1346 pub(crate) name: Option<Symbol>,
1347 pub(crate) type_: Type,
1348 pub(crate) is_const: bool,
1351}
1352
1353impl Parameter {
1354 pub(crate) fn to_receiver(&self) -> Option<&Type> {
1355 if self.name == Some(kw::SelfLower) { Some(&self.type_) } else { None }
1356 }
1357}
1358
1359#[derive(Clone, Debug)]
1360pub(crate) struct Trait {
1361 pub(crate) def_id: DefId,
1362 pub(crate) items: Vec<Item>,
1363 pub(crate) generics: Generics,
1364 pub(crate) bounds: Vec<GenericBound>,
1365}
1366
1367impl Trait {
1368 pub(crate) fn is_auto(&self, tcx: TyCtxt<'_>) -> bool {
1369 tcx.trait_is_auto(self.def_id)
1370 }
1371 pub(crate) fn is_notable_trait(&self, tcx: TyCtxt<'_>) -> bool {
1372 tcx.is_doc_notable_trait(self.def_id)
1373 }
1374 pub(crate) fn safety(&self, tcx: TyCtxt<'_>) -> hir::Safety {
1375 tcx.trait_def(self.def_id).safety
1376 }
1377 pub(crate) fn is_dyn_compatible(&self, tcx: TyCtxt<'_>) -> bool {
1378 tcx.is_dyn_compatible(self.def_id)
1379 }
1380 pub(crate) fn is_deprecated(&self, tcx: TyCtxt<'_>) -> bool {
1381 tcx.lookup_deprecation(self.def_id).is_some_and(|deprecation| deprecation.is_in_effect())
1382 }
1383}
1384
1385#[derive(Clone, Debug)]
1386pub(crate) struct TraitAlias {
1387 pub(crate) generics: Generics,
1388 pub(crate) bounds: Vec<GenericBound>,
1389}
1390
1391#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1393pub(crate) struct PolyTrait {
1394 pub(crate) trait_: Path,
1395 pub(crate) generic_params: Vec<GenericParamDef>,
1396}
1397
1398#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1400pub(crate) enum Type {
1401 Path {
1406 path: Path,
1407 },
1408 DynTrait(Vec<PolyTrait>, Option<Lifetime>),
1410 Generic(Symbol),
1412 SelfTy,
1414 Primitive(PrimitiveType),
1416 BareFunction(Box<BareFunctionDecl>),
1418 Tuple(Vec<Type>),
1420 Slice(Box<Type>),
1422 Array(Box<Type>, Box<str>),
1426 Pat(Box<Type>, Box<str>),
1427 FieldOf(Box<Type>, Box<str>),
1428 RawPointer(Mutability, Box<Type>),
1430 BorrowedRef {
1432 lifetime: Option<Lifetime>,
1433 mutability: Mutability,
1434 type_: Box<Type>,
1435 },
1436
1437 QPath(Box<QPathData>),
1439
1440 Infer,
1442
1443 ImplTrait(Vec<GenericBound>),
1445
1446 UnsafeBinder(Box<UnsafeBinderTy>),
1447}
1448
1449impl Type {
1450 pub(crate) fn without_borrowed_ref(&self) -> &Type {
1452 let mut result = self;
1453 while let Type::BorrowedRef { type_, .. } = result {
1454 result = type_;
1455 }
1456 result
1457 }
1458
1459 pub(crate) fn is_borrowed_ref(&self) -> bool {
1460 matches!(self, Type::BorrowedRef { .. })
1461 }
1462
1463 fn is_type_alias(&self) -> bool {
1464 matches!(self, Type::Path { path: Path { res: Res::Def(DefKind::TyAlias, _), .. } })
1465 }
1466
1467 pub(crate) fn is_doc_subtype_of(&self, other: &Self, cache: &Cache) -> bool {
1488 let (self_cleared, other_cleared) = if !self.is_borrowed_ref() || !other.is_borrowed_ref() {
1491 (self.without_borrowed_ref(), other.without_borrowed_ref())
1492 } else {
1493 (self, other)
1494 };
1495
1496 if self_cleared.is_type_alias() || other_cleared.is_type_alias() {
1502 return true;
1503 }
1504
1505 match (self_cleared, other_cleared) {
1506 (Type::Tuple(a), Type::Tuple(b)) => {
1508 a.iter().eq_by(b, |a, b| a.is_doc_subtype_of(b, cache))
1509 }
1510 (Type::Slice(a), Type::Slice(b)) => a.is_doc_subtype_of(b, cache),
1511 (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_doc_subtype_of(b, cache),
1512 (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
1513 mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache)
1514 }
1515 (
1516 Type::BorrowedRef { mutability, type_, .. },
1517 Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
1518 ) => mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache),
1519 (Type::Infer, _) | (_, Type::Infer) => true,
1521 (_, Type::Generic(_)) => true,
1524 (Type::Generic(_), _) => false,
1525 (Type::SelfTy, Type::SelfTy) => true,
1527 (Type::Path { path: a }, Type::Path { path: b }) => {
1529 a.def_id() == b.def_id()
1530 && a.generics()
1531 .zip(b.generics())
1532 .map(|(ag, bg)| ag.zip(bg).all(|(at, bt)| at.is_doc_subtype_of(bt, cache)))
1533 .unwrap_or(true)
1534 }
1535 (a, b) => a
1537 .def_id(cache)
1538 .and_then(|a| Some((a, b.def_id(cache)?)))
1539 .map(|(a, b)| a == b)
1540 .unwrap_or(false),
1541 }
1542 }
1543
1544 pub(crate) fn primitive_type(&self) -> Option<PrimitiveType> {
1545 match *self {
1546 Primitive(p) | BorrowedRef { type_: Primitive(p), .. } => Some(p),
1547 Slice(..) | BorrowedRef { type_: Slice(..), .. } => Some(PrimitiveType::Slice),
1548 Array(..) | BorrowedRef { type_: Array(..), .. } => Some(PrimitiveType::Array),
1549 Tuple(ref tys) => {
1550 if tys.is_empty() {
1551 Some(PrimitiveType::Unit)
1552 } else {
1553 Some(PrimitiveType::Tuple)
1554 }
1555 }
1556 RawPointer(..) => Some(PrimitiveType::RawPointer),
1557 BareFunction(..) => Some(PrimitiveType::Fn),
1558 _ => None,
1559 }
1560 }
1561
1562 pub(crate) fn sugared_async_return_type(self) -> Type {
1572 if let Type::ImplTrait(mut v) = self
1573 && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = v.pop()
1574 && let Some(segment) = trait_.segments.pop()
1575 && let GenericArgs::AngleBracketed { mut constraints, .. } = segment.args
1576 && let Some(constraint) = constraints.pop()
1577 && let AssocItemConstraintKind::Equality { term } = constraint.kind
1578 && let Term::Type(ty) = term
1579 {
1580 ty
1581 } else {
1582 panic!("unexpected async fn return type")
1583 }
1584 }
1585
1586 pub(crate) fn is_assoc_ty(&self) -> bool {
1588 match self {
1589 Type::Path { path, .. } => path.is_assoc_ty(),
1590 _ => false,
1591 }
1592 }
1593
1594 pub(crate) fn is_self_type(&self) -> bool {
1595 matches!(*self, Type::SelfTy)
1596 }
1597
1598 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
1599 match self {
1600 Type::Path { path, .. } => path.generic_args(),
1601 _ => None,
1602 }
1603 }
1604
1605 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
1606 match self {
1607 Type::Path { path, .. } => path.generics(),
1608 _ => None,
1609 }
1610 }
1611
1612 pub(crate) fn is_full_generic(&self) -> bool {
1613 matches!(self, Type::Generic(_))
1614 }
1615
1616 pub(crate) fn is_unit(&self) -> bool {
1617 matches!(self, Type::Tuple(v) if v.is_empty())
1618 }
1619
1620 pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
1624 let t: PrimitiveType = match self {
1625 Type::Path { path } => return Some(path.def_id()),
1626 DynTrait(bounds, _) => return bounds.first().map(|b| b.trait_.def_id()),
1627 Primitive(p) => return cache.primitive_locations.get(p).cloned(),
1628 BorrowedRef { type_: Generic(..), .. } => PrimitiveType::Reference,
1629 BorrowedRef { type_, .. } => return type_.def_id(cache),
1630 Tuple(tys) => {
1631 if tys.is_empty() {
1632 PrimitiveType::Unit
1633 } else {
1634 PrimitiveType::Tuple
1635 }
1636 }
1637 BareFunction(..) => PrimitiveType::Fn,
1638 Slice(..) => PrimitiveType::Slice,
1639 Array(..) => PrimitiveType::Array,
1640 Type::Pat(..) => PrimitiveType::Pat,
1641 Type::FieldOf(..) => PrimitiveType::FieldOf,
1642 RawPointer(..) => PrimitiveType::RawPointer,
1643 QPath(QPathData { self_type, .. }) => return self_type.def_id(cache),
1644 Generic(_) | SelfTy | Infer | ImplTrait(_) | UnsafeBinder(_) => return None,
1645 };
1646 Primitive(t).def_id(cache)
1647 }
1648}
1649
1650#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1651pub(crate) struct QPathData {
1652 pub assoc: PathSegment,
1653 pub self_type: Type,
1654 pub should_fully_qualify: bool,
1656 pub trait_: Option<Path>,
1657}
1658
1659#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1666pub(crate) enum PrimitiveType {
1667 Isize,
1668 I8,
1669 I16,
1670 I32,
1671 I64,
1672 I128,
1673 Usize,
1674 U8,
1675 U16,
1676 U32,
1677 U64,
1678 U128,
1679 F16,
1680 F32,
1681 F64,
1682 F128,
1683 Char,
1684 Bool,
1685 Str,
1686 Slice,
1687 Array,
1688 Pat,
1689 FieldOf,
1690 Tuple,
1691 Unit,
1692 RawPointer,
1693 Reference,
1694 Fn,
1695 Never,
1696}
1697
1698type SimplifiedTypes = FxIndexMap<PrimitiveType, ArrayVec<SimplifiedType, 3>>;
1699impl PrimitiveType {
1700 pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1701 use ast::{FloatTy, IntTy, UintTy};
1702 match prim {
1703 hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1704 hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1705 hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1706 hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1707 hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1708 hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1709 hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1710 hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1711 hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1712 hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1713 hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1714 hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1715 hir::PrimTy::Float(FloatTy::F16) => PrimitiveType::F16,
1716 hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1717 hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1718 hir::PrimTy::Float(FloatTy::F128) => PrimitiveType::F128,
1719 hir::PrimTy::Str => PrimitiveType::Str,
1720 hir::PrimTy::Bool => PrimitiveType::Bool,
1721 hir::PrimTy::Char => PrimitiveType::Char,
1722 }
1723 }
1724
1725 pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1726 match s {
1727 sym::isize => Some(PrimitiveType::Isize),
1728 sym::i8 => Some(PrimitiveType::I8),
1729 sym::i16 => Some(PrimitiveType::I16),
1730 sym::i32 => Some(PrimitiveType::I32),
1731 sym::i64 => Some(PrimitiveType::I64),
1732 sym::i128 => Some(PrimitiveType::I128),
1733 sym::usize => Some(PrimitiveType::Usize),
1734 sym::u8 => Some(PrimitiveType::U8),
1735 sym::u16 => Some(PrimitiveType::U16),
1736 sym::u32 => Some(PrimitiveType::U32),
1737 sym::u64 => Some(PrimitiveType::U64),
1738 sym::u128 => Some(PrimitiveType::U128),
1739 sym::bool => Some(PrimitiveType::Bool),
1740 sym::char => Some(PrimitiveType::Char),
1741 sym::str => Some(PrimitiveType::Str),
1742 sym::f16 => Some(PrimitiveType::F16),
1743 sym::f32 => Some(PrimitiveType::F32),
1744 sym::f64 => Some(PrimitiveType::F64),
1745 sym::f128 => Some(PrimitiveType::F128),
1746 sym::array => Some(PrimitiveType::Array),
1747 sym::slice => Some(PrimitiveType::Slice),
1748 sym::tuple => Some(PrimitiveType::Tuple),
1749 sym::unit => Some(PrimitiveType::Unit),
1750 sym::pointer => Some(PrimitiveType::RawPointer),
1751 sym::reference => Some(PrimitiveType::Reference),
1752 kw::Fn => Some(PrimitiveType::Fn),
1753 sym::never => Some(PrimitiveType::Never),
1754 _ => None,
1755 }
1756 }
1757
1758 pub(crate) fn from_ty(ty: Ty<'_>) -> Option<Self> {
1759 match ty.kind() {
1760 ty::Array(..) => Some(Self::Array),
1761 ty::Bool => Some(Self::Bool),
1762 ty::Char => Some(Self::Char),
1763 ty::FnDef(..) | ty::FnPtr(..) => Some(Self::Fn),
1764 ty::Int(int) => Some(Self::from(*int)),
1765 ty::Uint(uint) => Some(Self::from(*uint)),
1766 ty::Float(float) => Some(Self::from(*float)),
1767 ty::Never => Some(Self::Never),
1768 ty::Pat(..) => Some(Self::Pat),
1769 ty::RawPtr(..) => Some(Self::RawPointer),
1770 ty::Ref(..) => Some(Self::Reference),
1771 ty::Slice(..) => Some(Self::Slice),
1772 ty::Str => Some(Self::Str),
1773 ty::Tuple(elems) if elems.is_empty() => Some(Self::Unit),
1774 ty::Tuple(_) => Some(Self::Tuple),
1775 ty::Adt(..)
1776 | ty::Alias(..)
1777 | ty::Bound(..)
1778 | ty::Closure(..)
1779 | ty::Coroutine(..)
1780 | ty::CoroutineClosure(..)
1781 | ty::CoroutineWitness(..)
1782 | ty::Dynamic(..)
1783 | ty::Error(..)
1784 | ty::Foreign(..)
1785 | ty::Infer(..)
1786 | ty::Param(..)
1787 | ty::Placeholder(..)
1788 | ty::UnsafeBinder(..) => None,
1789 }
1790 }
1791
1792 pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
1793 use PrimitiveType::*;
1794 use ty::{FloatTy, IntTy, UintTy};
1795 static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
1796
1797 let single = |x| iter::once(x).collect();
1798 CELL.get_or_init(move || {
1799 map! {
1800 Isize => single(SimplifiedType::Int(IntTy::Isize)),
1801 I8 => single(SimplifiedType::Int(IntTy::I8)),
1802 I16 => single(SimplifiedType::Int(IntTy::I16)),
1803 I32 => single(SimplifiedType::Int(IntTy::I32)),
1804 I64 => single(SimplifiedType::Int(IntTy::I64)),
1805 I128 => single(SimplifiedType::Int(IntTy::I128)),
1806 Usize => single(SimplifiedType::Uint(UintTy::Usize)),
1807 U8 => single(SimplifiedType::Uint(UintTy::U8)),
1808 U16 => single(SimplifiedType::Uint(UintTy::U16)),
1809 U32 => single(SimplifiedType::Uint(UintTy::U32)),
1810 U64 => single(SimplifiedType::Uint(UintTy::U64)),
1811 U128 => single(SimplifiedType::Uint(UintTy::U128)),
1812 F16 => single(SimplifiedType::Float(FloatTy::F16)),
1813 F32 => single(SimplifiedType::Float(FloatTy::F32)),
1814 F64 => single(SimplifiedType::Float(FloatTy::F64)),
1815 F128 => single(SimplifiedType::Float(FloatTy::F128)),
1816 Str => single(SimplifiedType::Str),
1817 Bool => single(SimplifiedType::Bool),
1818 Char => single(SimplifiedType::Char),
1819 Array => single(SimplifiedType::Array),
1820 Slice => single(SimplifiedType::Slice),
1821 Tuple => [SimplifiedType::Tuple(1), SimplifiedType::Tuple(2), SimplifiedType::Tuple(3)].into(),
1827 Unit => single(SimplifiedType::Tuple(0)),
1828 RawPointer => [SimplifiedType::Ptr(Mutability::Not), SimplifiedType::Ptr(Mutability::Mut)].into_iter().collect(),
1829 Reference => [SimplifiedType::Ref(Mutability::Not), SimplifiedType::Ref(Mutability::Mut)].into_iter().collect(),
1830 Fn => single(SimplifiedType::Function(1)),
1833 Never => single(SimplifiedType::Never),
1834 }
1835 })
1836 }
1837
1838 pub(crate) fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = DefId> + 'tcx {
1839 Self::simplified_types()
1840 .get(self)
1841 .into_iter()
1842 .flatten()
1843 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1844 .copied()
1845 }
1846
1847 pub(crate) fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> {
1848 Self::simplified_types()
1849 .values()
1850 .flatten()
1851 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1852 .copied()
1853 }
1854
1855 pub(crate) fn as_sym(&self) -> Symbol {
1856 use PrimitiveType::*;
1857 match self {
1858 Isize => sym::isize,
1859 I8 => sym::i8,
1860 I16 => sym::i16,
1861 I32 => sym::i32,
1862 I64 => sym::i64,
1863 I128 => sym::i128,
1864 Usize => sym::usize,
1865 U8 => sym::u8,
1866 U16 => sym::u16,
1867 U32 => sym::u32,
1868 U64 => sym::u64,
1869 U128 => sym::u128,
1870 F16 => sym::f16,
1871 F32 => sym::f32,
1872 F64 => sym::f64,
1873 F128 => sym::f128,
1874 Str => sym::str,
1875 Bool => sym::bool,
1876 Char => sym::char,
1877 Array => sym::array,
1878 Pat => sym::pat,
1879 FieldOf => sym::field_of,
1880 Slice => sym::slice,
1881 Tuple => sym::tuple,
1882 Unit => sym::unit,
1883 RawPointer => sym::pointer,
1884 Reference => sym::reference,
1885 Fn => kw::Fn,
1886 Never => sym::never,
1887 }
1888 }
1889
1890 pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxIndexMap<PrimitiveType, DefId> {
1902 static PRIMITIVE_LOCATIONS: OnceCell<FxIndexMap<PrimitiveType, DefId>> = OnceCell::new();
1903 PRIMITIVE_LOCATIONS.get_or_init(|| {
1904 let mut primitive_locations = FxIndexMap::default();
1905 for &crate_num in tcx.crates(()) {
1908 let e = ExternalCrate { crate_num };
1909 let crate_name = e.name(tcx);
1910 debug!(?crate_num, ?crate_name);
1911 for (def_id, prim) in e.primitives(tcx) {
1912 if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1914 continue;
1915 }
1916 primitive_locations.insert(prim, def_id);
1917 }
1918 }
1919 let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1920 for (def_id, prim) in local_primitives {
1921 primitive_locations.insert(prim, def_id);
1922 }
1923 primitive_locations
1924 })
1925 }
1926}
1927
1928impl From<ty::IntTy> for PrimitiveType {
1929 fn from(int_ty: ty::IntTy) -> PrimitiveType {
1930 match int_ty {
1931 ty::IntTy::Isize => PrimitiveType::Isize,
1932 ty::IntTy::I8 => PrimitiveType::I8,
1933 ty::IntTy::I16 => PrimitiveType::I16,
1934 ty::IntTy::I32 => PrimitiveType::I32,
1935 ty::IntTy::I64 => PrimitiveType::I64,
1936 ty::IntTy::I128 => PrimitiveType::I128,
1937 }
1938 }
1939}
1940
1941impl From<ty::UintTy> for PrimitiveType {
1942 fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1943 match uint_ty {
1944 ty::UintTy::Usize => PrimitiveType::Usize,
1945 ty::UintTy::U8 => PrimitiveType::U8,
1946 ty::UintTy::U16 => PrimitiveType::U16,
1947 ty::UintTy::U32 => PrimitiveType::U32,
1948 ty::UintTy::U64 => PrimitiveType::U64,
1949 ty::UintTy::U128 => PrimitiveType::U128,
1950 }
1951 }
1952}
1953
1954impl From<ty::FloatTy> for PrimitiveType {
1955 fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1956 match float_ty {
1957 ty::FloatTy::F16 => PrimitiveType::F16,
1958 ty::FloatTy::F32 => PrimitiveType::F32,
1959 ty::FloatTy::F64 => PrimitiveType::F64,
1960 ty::FloatTy::F128 => PrimitiveType::F128,
1961 }
1962 }
1963}
1964
1965impl From<hir::PrimTy> for PrimitiveType {
1966 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1967 match prim_ty {
1968 hir::PrimTy::Int(int_ty) => int_ty.into(),
1969 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1970 hir::PrimTy::Float(float_ty) => float_ty.into(),
1971 hir::PrimTy::Str => PrimitiveType::Str,
1972 hir::PrimTy::Bool => PrimitiveType::Bool,
1973 hir::PrimTy::Char => PrimitiveType::Char,
1974 }
1975 }
1976}
1977
1978#[derive(Clone, Debug)]
1979pub(crate) struct Struct {
1980 pub(crate) ctor_kind: Option<CtorKind>,
1981 pub(crate) generics: Generics,
1982 pub(crate) fields: ThinVec<Item>,
1983}
1984
1985impl Struct {
1986 pub(crate) fn has_stripped_entries(&self) -> bool {
1987 self.fields.iter().any(|f| f.is_stripped())
1988 }
1989}
1990
1991#[derive(Clone, Debug)]
1992pub(crate) struct Union {
1993 pub(crate) generics: Generics,
1994 pub(crate) fields: Vec<Item>,
1995}
1996
1997impl Union {
1998 pub(crate) fn has_stripped_entries(&self) -> bool {
1999 self.fields.iter().any(|f| f.is_stripped())
2000 }
2001}
2002
2003#[derive(Clone, Debug)]
2007pub(crate) struct VariantStruct {
2008 pub(crate) fields: ThinVec<Item>,
2009}
2010
2011impl VariantStruct {
2012 pub(crate) fn has_stripped_entries(&self) -> bool {
2013 self.fields.iter().any(|f| f.is_stripped())
2014 }
2015}
2016
2017#[derive(Clone, Debug)]
2018pub(crate) struct Enum {
2019 pub(crate) variants: IndexVec<VariantIdx, Item>,
2020 pub(crate) generics: Generics,
2021}
2022
2023impl Enum {
2024 pub(crate) fn has_stripped_entries(&self) -> bool {
2025 self.variants.iter().any(|f| f.is_stripped())
2026 }
2027
2028 pub(crate) fn non_stripped_variants(&self) -> impl Iterator<Item = &Item> {
2029 self.variants.iter().filter(|v| !v.is_stripped())
2030 }
2031}
2032
2033#[derive(Clone, Debug)]
2034pub(crate) struct Variant {
2035 pub kind: VariantKind,
2036 pub discriminant: Option<Discriminant>,
2037}
2038
2039#[derive(Clone, Debug)]
2040pub(crate) enum VariantKind {
2041 CLike,
2042 Tuple(ThinVec<Item>),
2043 Struct(VariantStruct),
2044}
2045
2046impl Variant {
2047 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
2048 match &self.kind {
2049 VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()),
2050 VariantKind::CLike | VariantKind::Tuple(_) => None,
2051 }
2052 }
2053}
2054
2055#[derive(Clone, Debug)]
2056pub(crate) struct Discriminant {
2057 pub(super) expr: Option<BodyId>,
2060 pub(super) value: DefId,
2061}
2062
2063impl Discriminant {
2064 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
2067 self.expr
2068 .map(|body| rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body)))
2069 }
2070 pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String {
2071 print_evaluated_const(tcx, self.value, with_underscores, false).unwrap()
2072 }
2073}
2074
2075#[derive(Copy, Clone, Debug)]
2078pub(crate) struct Span(rustc_span::Span);
2079
2080impl Span {
2081 pub(crate) fn new(sp: rustc_span::Span) -> Self {
2086 Self(sp.source_callsite())
2087 }
2088
2089 pub(crate) fn inner(&self) -> rustc_span::Span {
2090 self.0
2091 }
2092
2093 pub(crate) fn filename(&self, sess: &Session) -> FileName {
2094 sess.source_map().span_to_filename(self.0)
2095 }
2096
2097 pub(crate) fn lo(&self, sess: &Session) -> Loc {
2098 sess.source_map().lookup_char_pos(self.0.lo())
2099 }
2100
2101 pub(crate) fn hi(&self, sess: &Session) -> Loc {
2102 sess.source_map().lookup_char_pos(self.0.hi())
2103 }
2104
2105 pub(crate) fn cnum(&self, sess: &Session) -> CrateNum {
2106 self.lo(sess).file.cnum
2108 }
2109}
2110
2111#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2112pub(crate) struct Path {
2113 pub(crate) res: Res,
2114 pub(crate) segments: ThinVec<PathSegment>,
2115}
2116
2117impl Path {
2118 pub(crate) fn def_id(&self) -> DefId {
2119 self.res.def_id()
2120 }
2121
2122 pub(crate) fn last_opt(&self) -> Option<Symbol> {
2123 self.segments.last().map(|s| s.name)
2124 }
2125
2126 pub(crate) fn last(&self) -> Symbol {
2127 self.last_opt().expect("segments were empty")
2128 }
2129
2130 pub(crate) fn whole_name(&self) -> String {
2131 self.segments
2132 .iter()
2133 .map(|s| if s.name == kw::PathRoot { "" } else { s.name.as_str() })
2134 .intersperse("::")
2135 .collect()
2136 }
2137
2138 pub(crate) fn is_assoc_ty(&self) -> bool {
2140 match self.res {
2141 Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _)
2142 if self.segments.len() != 1 =>
2143 {
2144 true
2145 }
2146 Res::Def(DefKind::AssocTy, _) => true,
2147 _ => false,
2148 }
2149 }
2150
2151 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
2152 self.segments.last().map(|seg| &seg.args)
2153 }
2154
2155 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
2156 self.segments.last().and_then(|seg| {
2157 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2158 Some(args.iter().filter_map(|arg| match arg {
2159 GenericArg::Type(ty) => Some(ty),
2160 _ => None,
2161 }))
2162 } else {
2163 None
2164 }
2165 })
2166 }
2167}
2168
2169#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2170pub(crate) enum GenericArg {
2171 Lifetime(Lifetime),
2172 Type(Type),
2173 Const(Box<ConstantKind>),
2174 Infer,
2175}
2176
2177impl GenericArg {
2178 pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
2179 if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2180 }
2181
2182 pub(crate) fn as_ty(&self) -> Option<&Type> {
2183 if let Self::Type(ty) = self { Some(ty) } else { None }
2184 }
2185}
2186
2187#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2188pub(crate) enum GenericArgs {
2189 AngleBracketed { args: ThinVec<GenericArg>, constraints: ThinVec<AssocItemConstraint> },
2191 Parenthesized { inputs: ThinVec<Type>, output: Option<Box<Type>> },
2193 ReturnTypeNotation,
2195}
2196
2197impl GenericArgs {
2198 pub(crate) fn is_empty(&self) -> bool {
2199 match self {
2200 GenericArgs::AngleBracketed { args, constraints } => {
2201 args.is_empty() && constraints.is_empty()
2202 }
2203 GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
2204 GenericArgs::ReturnTypeNotation => false,
2205 }
2206 }
2207 pub(crate) fn constraints(&self) -> Box<dyn Iterator<Item = AssocItemConstraint> + '_> {
2208 match self {
2209 GenericArgs::AngleBracketed { constraints, .. } => {
2210 Box::new(constraints.iter().cloned())
2211 }
2212 GenericArgs::Parenthesized { output, .. } => Box::new(
2213 output
2214 .as_ref()
2215 .map(|ty| AssocItemConstraint {
2216 assoc: PathSegment {
2217 name: sym::Output,
2218 args: GenericArgs::AngleBracketed {
2219 args: ThinVec::new(),
2220 constraints: ThinVec::new(),
2221 },
2222 },
2223 kind: AssocItemConstraintKind::Equality {
2224 term: Term::Type((**ty).clone()),
2225 },
2226 })
2227 .into_iter(),
2228 ),
2229 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2230 }
2231 }
2232}
2233
2234impl<'a> IntoIterator for &'a GenericArgs {
2235 type IntoIter = Box<dyn Iterator<Item = GenericArg> + 'a>;
2236 type Item = GenericArg;
2237 fn into_iter(self) -> Self::IntoIter {
2238 match self {
2239 GenericArgs::AngleBracketed { args, .. } => Box::new(args.iter().cloned()),
2240 GenericArgs::Parenthesized { inputs, .. } => {
2241 Box::new(inputs.iter().cloned().map(GenericArg::Type))
2243 }
2244 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2245 }
2246 }
2247}
2248
2249#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2250pub(crate) struct PathSegment {
2251 pub(crate) name: Symbol,
2252 pub(crate) args: GenericArgs,
2253}
2254
2255#[derive(Clone, Debug)]
2256pub(crate) enum TypeAliasInnerType {
2257 Enum { variants: IndexVec<VariantIdx, Item>, is_non_exhaustive: bool },
2258 Union { fields: Vec<Item> },
2259 Struct { ctor_kind: Option<CtorKind>, fields: Vec<Item> },
2260}
2261
2262impl TypeAliasInnerType {
2263 fn has_stripped_entries(&self) -> Option<bool> {
2264 Some(match self {
2265 Self::Enum { variants, .. } => variants.iter().any(|v| v.is_stripped()),
2266 Self::Union { fields } | Self::Struct { fields, .. } => {
2267 fields.iter().any(|f| f.is_stripped())
2268 }
2269 })
2270 }
2271}
2272
2273#[derive(Clone, Debug)]
2274pub(crate) struct TypeAlias {
2275 pub(crate) type_: Type,
2276 pub(crate) generics: Generics,
2277 pub(crate) inner_type: Option<TypeAliasInnerType>,
2280 pub(crate) item_type: Option<Type>,
2287}
2288
2289#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2290pub(crate) struct BareFunctionDecl {
2291 pub(crate) safety: hir::Safety,
2292 pub(crate) generic_params: Vec<GenericParamDef>,
2293 pub(crate) decl: FnDecl,
2294 pub(crate) abi: ExternAbi,
2295}
2296
2297#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2298pub(crate) struct UnsafeBinderTy {
2299 pub(crate) generic_params: Vec<GenericParamDef>,
2300 pub(crate) ty: Type,
2301}
2302
2303#[derive(Clone, Debug)]
2304pub(crate) struct Static {
2305 pub(crate) type_: Box<Type>,
2306 pub(crate) mutability: Mutability,
2307 pub(crate) expr: Option<BodyId>,
2308}
2309
2310#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2311pub(crate) struct Constant {
2312 pub(crate) generics: Generics,
2313 pub(crate) kind: ConstantKind,
2314 pub(crate) type_: Type,
2315}
2316
2317#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2318pub(crate) enum Term {
2319 Type(Type),
2320 Constant(ConstantKind),
2321}
2322
2323impl Term {
2324 pub(crate) fn ty(&self) -> Option<&Type> {
2325 if let Term::Type(ty) = self { Some(ty) } else { None }
2326 }
2327}
2328
2329impl From<Type> for Term {
2330 fn from(ty: Type) -> Self {
2331 Term::Type(ty)
2332 }
2333}
2334
2335#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2336pub(crate) enum ConstantKind {
2337 TyConst { expr: Box<str> },
2343 Path { path: Box<str> },
2346 Anonymous { body: BodyId },
2350 Extern { def_id: DefId },
2352 Local { def_id: DefId, body: BodyId },
2354 Infer,
2356}
2357
2358impl ConstantKind {
2359 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2360 match *self {
2361 ConstantKind::TyConst { ref expr } => expr.to_string(),
2362 ConstantKind::Path { ref path } => path.to_string(),
2363 ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2364 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2365 rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body))
2366 }
2367 ConstantKind::Infer => "_".to_string(),
2368 }
2369 }
2370
2371 pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2372 match *self {
2373 ConstantKind::TyConst { .. }
2374 | ConstantKind::Path { .. }
2375 | ConstantKind::Anonymous { .. }
2376 | ConstantKind::Infer => None,
2377 ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2378 print_evaluated_const(tcx, def_id, true, true)
2379 }
2380 }
2381 }
2382
2383 pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2384 match *self {
2385 ConstantKind::TyConst { .. }
2386 | ConstantKind::Extern { .. }
2387 | ConstantKind::Path { .. }
2388 | ConstantKind::Infer => false,
2389 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2390 is_literal_expr(tcx, body.hir_id)
2391 }
2392 }
2393 }
2394}
2395
2396#[derive(Clone, Debug)]
2397pub(crate) struct Impl {
2398 pub(crate) safety: hir::Safety,
2399 pub(crate) generics: Generics,
2400 pub(crate) trait_: Option<Path>,
2401 pub(crate) for_: Type,
2402 pub(crate) items: Vec<Item>,
2403 pub(crate) polarity: ty::ImplPolarity,
2404 pub(crate) kind: ImplKind,
2405 pub(crate) is_deprecated: bool,
2406}
2407
2408impl Impl {
2409 pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxIndexSet<Symbol> {
2410 self.trait_
2411 .as_ref()
2412 .map(|t| t.def_id())
2413 .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name()).collect())
2414 .unwrap_or_default()
2415 }
2416
2417 pub(crate) fn is_negative_trait_impl(&self) -> bool {
2418 matches!(self.polarity, ty::ImplPolarity::Negative)
2419 }
2420}
2421
2422#[derive(Clone, Debug)]
2423pub(crate) enum ImplKind {
2424 Normal,
2425 Auto,
2426 FakeVariadic,
2427 Blanket(Box<Type>),
2428}
2429
2430impl ImplKind {
2431 pub(crate) fn is_auto(&self) -> bool {
2432 matches!(self, ImplKind::Auto)
2433 }
2434
2435 pub(crate) fn is_blanket(&self) -> bool {
2436 matches!(self, ImplKind::Blanket(_))
2437 }
2438
2439 pub(crate) fn is_fake_variadic(&self) -> bool {
2440 matches!(self, ImplKind::FakeVariadic)
2441 }
2442
2443 pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
2444 match self {
2445 ImplKind::Blanket(ty) => Some(ty),
2446 _ => None,
2447 }
2448 }
2449}
2450
2451#[derive(Clone, Debug)]
2452pub(crate) struct Import {
2453 pub(crate) kind: ImportKind,
2454 pub(crate) source: ImportSource,
2456 pub(crate) should_be_displayed: bool,
2457}
2458
2459impl Import {
2460 pub(crate) fn new_simple(
2461 name: Symbol,
2462 source: ImportSource,
2463 should_be_displayed: bool,
2464 ) -> Self {
2465 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2466 }
2467
2468 pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2469 Self { kind: ImportKind::Glob, source, should_be_displayed }
2470 }
2471
2472 pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool {
2473 self.source.did.is_some_and(|did| tcx.is_doc_hidden(did))
2474 }
2475}
2476
2477#[derive(Clone, Debug)]
2478pub(crate) enum ImportKind {
2479 Simple(Symbol),
2481 Glob,
2483}
2484
2485#[derive(Clone, Debug)]
2486pub(crate) struct ImportSource {
2487 pub(crate) path: Path,
2488 pub(crate) did: Option<DefId>,
2489}
2490
2491#[derive(Clone, Debug)]
2492pub(crate) struct Macro {
2493 pub(crate) source: String,
2494 pub(crate) macro_rules: bool,
2496}
2497
2498#[derive(Clone, Debug)]
2499pub(crate) struct ProcMacro {
2500 pub(crate) kind: MacroKind,
2501 pub(crate) helpers: Vec<Symbol>,
2502}
2503
2504#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2515pub(crate) struct AssocItemConstraint {
2516 pub(crate) assoc: PathSegment,
2517 pub(crate) kind: AssocItemConstraintKind,
2518}
2519
2520#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2522pub(crate) enum AssocItemConstraintKind {
2523 Equality { term: Term },
2524 Bound { bounds: Vec<GenericBound> },
2525}
2526
2527#[cfg(target_pointer_width = "64")]
2529mod size_asserts {
2530 use rustc_data_structures::static_assert_size;
2531
2532 use super::*;
2533 static_assert_size!(Crate, 16); static_assert_size!(DocFragment, 48);
2536 static_assert_size!(GenericArg, 32);
2537 static_assert_size!(GenericArgs, 24);
2538 static_assert_size!(GenericParamDef, 40);
2539 static_assert_size!(Generics, 16);
2540 static_assert_size!(Item, 8);
2541 static_assert_size!(ItemInner, 136);
2542 static_assert_size!(ItemKind, 48);
2543 static_assert_size!(PathSegment, 32);
2544 static_assert_size!(Type, 32);
2545 }