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