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 pub(crate) fn merge_with(&mut self, other: Self) {
1098 let Self { doc_strings, other_attrs } = other;
1099 self.doc_strings.extend(doc_strings);
1100 self.other_attrs.extend(other_attrs);
1101 }
1102}
1103
1104#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1105pub(crate) enum GenericBound {
1106 TraitBound(PolyTrait, hir::TraitBoundModifiers),
1107 Outlives(Lifetime),
1108 Use(Vec<PreciseCapturingArg>),
1110}
1111
1112impl GenericBound {
1113 pub(crate) fn sized(cx: &mut DocContext<'_>) -> GenericBound {
1114 Self::sized_with(cx, hir::TraitBoundModifiers::NONE)
1115 }
1116
1117 pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1118 Self::sized_with(
1119 cx,
1120 hir::TraitBoundModifiers {
1121 polarity: hir::BoundPolarity::Maybe(DUMMY_SP),
1122 constness: hir::BoundConstness::Never,
1123 },
1124 )
1125 }
1126
1127 fn sized_with(cx: &mut DocContext<'_>, modifiers: hir::TraitBoundModifiers) -> GenericBound {
1128 let did = cx.tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
1129 let empty = ty::Binder::dummy(ty::GenericArgs::empty());
1130 let path = clean_middle_path(cx, did, false, ThinVec::new(), empty);
1131 inline::record_extern_fqn(cx, did, ItemType::Trait);
1132 GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifiers)
1133 }
1134
1135 pub(crate) fn is_trait_bound(&self) -> bool {
1136 matches!(self, Self::TraitBound(..))
1137 }
1138
1139 pub(crate) fn is_sized_bound(&self, tcx: TyCtxt<'_>) -> bool {
1140 self.is_bounded_by_lang_item(tcx, LangItem::Sized)
1141 }
1142
1143 pub(crate) fn is_meta_sized_bound(&self, tcx: TyCtxt<'_>) -> bool {
1144 self.is_bounded_by_lang_item(tcx, LangItem::MetaSized)
1145 }
1146
1147 fn is_bounded_by_lang_item(&self, tcx: TyCtxt<'_>, lang_item: LangItem) -> bool {
1148 if let GenericBound::TraitBound(
1149 PolyTrait { ref trait_, .. },
1150 rustc_hir::TraitBoundModifiers::NONE,
1151 ) = *self
1152 && tcx.is_lang_item(trait_.def_id(), lang_item)
1153 {
1154 return true;
1155 }
1156 false
1157 }
1158
1159 pub(crate) fn get_trait_path(&self) -> Option<Path> {
1160 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1161 Some(trait_.clone())
1162 } else {
1163 None
1164 }
1165 }
1166}
1167
1168#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1169pub(crate) struct Lifetime(pub Symbol);
1170
1171impl Lifetime {
1172 pub(crate) fn statik() -> Lifetime {
1173 Lifetime(kw::StaticLifetime)
1174 }
1175
1176 pub(crate) fn elided() -> Lifetime {
1177 Lifetime(kw::UnderscoreLifetime)
1178 }
1179}
1180
1181#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1182pub(crate) enum PreciseCapturingArg {
1183 Lifetime(Lifetime),
1184 Param(Symbol),
1185}
1186
1187impl PreciseCapturingArg {
1188 pub(crate) fn name(self) -> Symbol {
1189 match self {
1190 PreciseCapturingArg::Lifetime(lt) => lt.0,
1191 PreciseCapturingArg::Param(param) => param,
1192 }
1193 }
1194}
1195
1196#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1197pub(crate) enum WherePredicate {
1198 BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
1199 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1200 EqPredicate { lhs: QPathData, rhs: Term },
1201}
1202
1203impl WherePredicate {
1204 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1205 match self {
1206 WherePredicate::BoundPredicate { bounds, .. } => Some(bounds),
1207 WherePredicate::RegionPredicate { bounds, .. } => Some(bounds),
1208 _ => None,
1209 }
1210 }
1211}
1212
1213#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1214pub(crate) enum GenericParamDefKind {
1215 Lifetime { outlives: ThinVec<Lifetime> },
1216 Type { bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
1217 Const { ty: Box<Type>, default: Option<Box<String>> },
1219}
1220
1221impl GenericParamDefKind {
1222 pub(crate) fn is_type(&self) -> bool {
1223 matches!(self, GenericParamDefKind::Type { .. })
1224 }
1225}
1226
1227#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1228pub(crate) struct GenericParamDef {
1229 pub(crate) name: Symbol,
1230 pub(crate) def_id: DefId,
1231 pub(crate) kind: GenericParamDefKind,
1232}
1233
1234impl GenericParamDef {
1235 pub(crate) fn lifetime(def_id: DefId, name: Symbol) -> Self {
1236 Self { name, def_id, kind: GenericParamDefKind::Lifetime { outlives: ThinVec::new() } }
1237 }
1238
1239 pub(crate) fn is_synthetic_param(&self) -> bool {
1240 match self.kind {
1241 GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
1242 GenericParamDefKind::Type { synthetic, .. } => synthetic,
1243 }
1244 }
1245
1246 pub(crate) fn is_type(&self) -> bool {
1247 self.kind.is_type()
1248 }
1249
1250 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1251 match self.kind {
1252 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1253 _ => None,
1254 }
1255 }
1256}
1257
1258#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
1260pub(crate) struct Generics {
1261 pub(crate) params: ThinVec<GenericParamDef>,
1262 pub(crate) where_predicates: ThinVec<WherePredicate>,
1263}
1264
1265impl Generics {
1266 pub(crate) fn is_empty(&self) -> bool {
1267 self.params.is_empty() && self.where_predicates.is_empty()
1268 }
1269}
1270
1271#[derive(Clone, Debug)]
1272pub(crate) struct Function {
1273 pub(crate) decl: FnDecl,
1274 pub(crate) generics: Generics,
1275}
1276
1277#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1278pub(crate) struct FnDecl {
1279 pub(crate) inputs: Vec<Parameter>,
1280 pub(crate) output: Type,
1281 pub(crate) c_variadic: bool,
1282}
1283
1284impl FnDecl {
1285 pub(crate) fn receiver_type(&self) -> Option<&Type> {
1286 self.inputs.first().and_then(|v| v.to_receiver())
1287 }
1288}
1289
1290#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1292pub(crate) struct Parameter {
1293 pub(crate) name: Option<Symbol>,
1294 pub(crate) type_: Type,
1295 pub(crate) is_const: bool,
1298}
1299
1300impl Parameter {
1301 pub(crate) fn to_receiver(&self) -> Option<&Type> {
1302 if self.name == Some(kw::SelfLower) { Some(&self.type_) } else { None }
1303 }
1304}
1305
1306#[derive(Clone, Debug)]
1307pub(crate) struct Trait {
1308 pub(crate) def_id: DefId,
1309 pub(crate) items: Vec<Item>,
1310 pub(crate) generics: Generics,
1311 pub(crate) bounds: Vec<GenericBound>,
1312}
1313
1314impl Trait {
1315 pub(crate) fn is_auto(&self, tcx: TyCtxt<'_>) -> bool {
1316 tcx.trait_is_auto(self.def_id)
1317 }
1318 pub(crate) fn is_notable_trait(&self, tcx: TyCtxt<'_>) -> bool {
1319 tcx.is_doc_notable_trait(self.def_id)
1320 }
1321 pub(crate) fn safety(&self, tcx: TyCtxt<'_>) -> hir::Safety {
1322 tcx.trait_def(self.def_id).safety
1323 }
1324 pub(crate) fn is_dyn_compatible(&self, tcx: TyCtxt<'_>) -> bool {
1325 tcx.is_dyn_compatible(self.def_id)
1326 }
1327 pub(crate) fn is_deprecated(&self, tcx: TyCtxt<'_>) -> bool {
1328 tcx.lookup_deprecation(self.def_id).is_some_and(|deprecation| deprecation.is_in_effect())
1329 }
1330}
1331
1332#[derive(Clone, Debug)]
1333pub(crate) struct TraitAlias {
1334 pub(crate) generics: Generics,
1335 pub(crate) bounds: Vec<GenericBound>,
1336}
1337
1338#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1340pub(crate) struct PolyTrait {
1341 pub(crate) trait_: Path,
1342 pub(crate) generic_params: Vec<GenericParamDef>,
1343}
1344
1345#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1347pub(crate) enum Type {
1348 Path {
1353 path: Path,
1354 },
1355 DynTrait(Vec<PolyTrait>, Option<Lifetime>),
1357 Generic(Symbol),
1359 SelfTy,
1361 Primitive(PrimitiveType),
1363 BareFunction(Box<BareFunctionDecl>),
1365 Tuple(Vec<Type>),
1367 Slice(Box<Type>),
1369 Array(Box<Type>, Box<str>),
1373 Pat(Box<Type>, Box<str>),
1374 FieldOf(Box<Type>, Box<str>),
1375 RawPointer(Mutability, Box<Type>),
1377 BorrowedRef {
1379 lifetime: Option<Lifetime>,
1380 mutability: Mutability,
1381 type_: Box<Type>,
1382 },
1383
1384 QPath(Box<QPathData>),
1386
1387 Infer,
1389
1390 ImplTrait(Vec<GenericBound>),
1392
1393 UnsafeBinder(Box<UnsafeBinderTy>),
1394}
1395
1396impl Type {
1397 pub(crate) fn without_borrowed_ref(&self) -> &Type {
1399 let mut result = self;
1400 while let Type::BorrowedRef { type_, .. } = result {
1401 result = type_;
1402 }
1403 result
1404 }
1405
1406 pub(crate) fn is_borrowed_ref(&self) -> bool {
1407 matches!(self, Type::BorrowedRef { .. })
1408 }
1409
1410 fn is_type_alias(&self) -> bool {
1411 matches!(self, Type::Path { path: Path { res: Res::Def(DefKind::TyAlias, _), .. } })
1412 }
1413
1414 pub(crate) fn is_doc_subtype_of(&self, other: &Self, cache: &Cache) -> bool {
1435 let (self_cleared, other_cleared) = if !self.is_borrowed_ref() || !other.is_borrowed_ref() {
1438 (self.without_borrowed_ref(), other.without_borrowed_ref())
1439 } else {
1440 (self, other)
1441 };
1442
1443 if self_cleared.is_type_alias() || other_cleared.is_type_alias() {
1449 return true;
1450 }
1451
1452 match (self_cleared, other_cleared) {
1453 (Type::Tuple(a), Type::Tuple(b)) => {
1455 a.iter().eq_by(b, |a, b| a.is_doc_subtype_of(b, cache))
1456 }
1457 (Type::Slice(a), Type::Slice(b)) => a.is_doc_subtype_of(b, cache),
1458 (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_doc_subtype_of(b, cache),
1459 (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
1460 mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache)
1461 }
1462 (
1463 Type::BorrowedRef { mutability, type_, .. },
1464 Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
1465 ) => mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache),
1466 (Type::Infer, _) | (_, Type::Infer) => true,
1468 (_, Type::Generic(_)) => true,
1471 (Type::Generic(_), _) => false,
1472 (Type::SelfTy, Type::SelfTy) => true,
1474 (Type::Path { path: a }, Type::Path { path: b }) => {
1476 a.def_id() == b.def_id()
1477 && a.generics()
1478 .zip(b.generics())
1479 .map(|(ag, bg)| ag.zip(bg).all(|(at, bt)| at.is_doc_subtype_of(bt, cache)))
1480 .unwrap_or(true)
1481 }
1482 (a, b) => a
1484 .def_id(cache)
1485 .and_then(|a| Some((a, b.def_id(cache)?)))
1486 .map(|(a, b)| a == b)
1487 .unwrap_or(false),
1488 }
1489 }
1490
1491 pub(crate) fn primitive_type(&self) -> Option<PrimitiveType> {
1492 match *self {
1493 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1494 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1495 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1496 Tuple(ref tys) => {
1497 if tys.is_empty() {
1498 Some(PrimitiveType::Unit)
1499 } else {
1500 Some(PrimitiveType::Tuple)
1501 }
1502 }
1503 RawPointer(..) => Some(PrimitiveType::RawPointer),
1504 BareFunction(..) => Some(PrimitiveType::Fn),
1505 _ => None,
1506 }
1507 }
1508
1509 pub(crate) fn sugared_async_return_type(self) -> Type {
1519 if let Type::ImplTrait(mut v) = self
1520 && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = v.pop()
1521 && let Some(segment) = trait_.segments.pop()
1522 && let GenericArgs::AngleBracketed { mut constraints, .. } = segment.args
1523 && let Some(constraint) = constraints.pop()
1524 && let AssocItemConstraintKind::Equality { term } = constraint.kind
1525 && let Term::Type(ty) = term
1526 {
1527 ty
1528 } else {
1529 panic!("unexpected async fn return type")
1530 }
1531 }
1532
1533 pub(crate) fn is_assoc_ty(&self) -> bool {
1535 match self {
1536 Type::Path { path, .. } => path.is_assoc_ty(),
1537 _ => false,
1538 }
1539 }
1540
1541 pub(crate) fn is_self_type(&self) -> bool {
1542 matches!(*self, Type::SelfTy)
1543 }
1544
1545 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
1546 match self {
1547 Type::Path { path, .. } => path.generic_args(),
1548 _ => None,
1549 }
1550 }
1551
1552 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
1553 match self {
1554 Type::Path { path, .. } => path.generics(),
1555 _ => None,
1556 }
1557 }
1558
1559 pub(crate) fn is_full_generic(&self) -> bool {
1560 matches!(self, Type::Generic(_))
1561 }
1562
1563 pub(crate) fn is_unit(&self) -> bool {
1564 matches!(self, Type::Tuple(v) if v.is_empty())
1565 }
1566
1567 pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
1571 let t: PrimitiveType = match self {
1572 Type::Path { path } => return Some(path.def_id()),
1573 DynTrait(bounds, _) => return bounds.first().map(|b| b.trait_.def_id()),
1574 Primitive(p) => return cache.primitive_locations.get(p).cloned(),
1575 BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
1576 BorrowedRef { type_, .. } => return type_.def_id(cache),
1577 Tuple(tys) => {
1578 if tys.is_empty() {
1579 PrimitiveType::Unit
1580 } else {
1581 PrimitiveType::Tuple
1582 }
1583 }
1584 BareFunction(..) => PrimitiveType::Fn,
1585 Slice(..) => PrimitiveType::Slice,
1586 Array(..) => PrimitiveType::Array,
1587 Type::Pat(..) => PrimitiveType::Pat,
1588 Type::FieldOf(..) => PrimitiveType::FieldOf,
1589 RawPointer(..) => PrimitiveType::RawPointer,
1590 QPath(box QPathData { self_type, .. }) => return self_type.def_id(cache),
1591 Generic(_) | SelfTy | Infer | ImplTrait(_) | UnsafeBinder(_) => return None,
1592 };
1593 Primitive(t).def_id(cache)
1594 }
1595}
1596
1597#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1598pub(crate) struct QPathData {
1599 pub assoc: PathSegment,
1600 pub self_type: Type,
1601 pub should_fully_qualify: bool,
1603 pub trait_: Option<Path>,
1604}
1605
1606#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1613pub(crate) enum PrimitiveType {
1614 Isize,
1615 I8,
1616 I16,
1617 I32,
1618 I64,
1619 I128,
1620 Usize,
1621 U8,
1622 U16,
1623 U32,
1624 U64,
1625 U128,
1626 F16,
1627 F32,
1628 F64,
1629 F128,
1630 Char,
1631 Bool,
1632 Str,
1633 Slice,
1634 Array,
1635 Pat,
1636 FieldOf,
1637 Tuple,
1638 Unit,
1639 RawPointer,
1640 Reference,
1641 Fn,
1642 Never,
1643}
1644
1645type SimplifiedTypes = FxIndexMap<PrimitiveType, ArrayVec<SimplifiedType, 3>>;
1646impl PrimitiveType {
1647 pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1648 use ast::{FloatTy, IntTy, UintTy};
1649 match prim {
1650 hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1651 hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1652 hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1653 hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1654 hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1655 hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1656 hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1657 hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1658 hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1659 hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1660 hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1661 hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1662 hir::PrimTy::Float(FloatTy::F16) => PrimitiveType::F16,
1663 hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1664 hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1665 hir::PrimTy::Float(FloatTy::F128) => PrimitiveType::F128,
1666 hir::PrimTy::Str => PrimitiveType::Str,
1667 hir::PrimTy::Bool => PrimitiveType::Bool,
1668 hir::PrimTy::Char => PrimitiveType::Char,
1669 }
1670 }
1671
1672 pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1673 match s {
1674 sym::isize => Some(PrimitiveType::Isize),
1675 sym::i8 => Some(PrimitiveType::I8),
1676 sym::i16 => Some(PrimitiveType::I16),
1677 sym::i32 => Some(PrimitiveType::I32),
1678 sym::i64 => Some(PrimitiveType::I64),
1679 sym::i128 => Some(PrimitiveType::I128),
1680 sym::usize => Some(PrimitiveType::Usize),
1681 sym::u8 => Some(PrimitiveType::U8),
1682 sym::u16 => Some(PrimitiveType::U16),
1683 sym::u32 => Some(PrimitiveType::U32),
1684 sym::u64 => Some(PrimitiveType::U64),
1685 sym::u128 => Some(PrimitiveType::U128),
1686 sym::bool => Some(PrimitiveType::Bool),
1687 sym::char => Some(PrimitiveType::Char),
1688 sym::str => Some(PrimitiveType::Str),
1689 sym::f16 => Some(PrimitiveType::F16),
1690 sym::f32 => Some(PrimitiveType::F32),
1691 sym::f64 => Some(PrimitiveType::F64),
1692 sym::f128 => Some(PrimitiveType::F128),
1693 sym::array => Some(PrimitiveType::Array),
1694 sym::slice => Some(PrimitiveType::Slice),
1695 sym::tuple => Some(PrimitiveType::Tuple),
1696 sym::unit => Some(PrimitiveType::Unit),
1697 sym::pointer => Some(PrimitiveType::RawPointer),
1698 sym::reference => Some(PrimitiveType::Reference),
1699 kw::Fn => Some(PrimitiveType::Fn),
1700 sym::never => Some(PrimitiveType::Never),
1701 _ => None,
1702 }
1703 }
1704
1705 pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
1706 use PrimitiveType::*;
1707 use ty::{FloatTy, IntTy, UintTy};
1708 static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
1709
1710 let single = |x| iter::once(x).collect();
1711 CELL.get_or_init(move || {
1712 map! {
1713 Isize => single(SimplifiedType::Int(IntTy::Isize)),
1714 I8 => single(SimplifiedType::Int(IntTy::I8)),
1715 I16 => single(SimplifiedType::Int(IntTy::I16)),
1716 I32 => single(SimplifiedType::Int(IntTy::I32)),
1717 I64 => single(SimplifiedType::Int(IntTy::I64)),
1718 I128 => single(SimplifiedType::Int(IntTy::I128)),
1719 Usize => single(SimplifiedType::Uint(UintTy::Usize)),
1720 U8 => single(SimplifiedType::Uint(UintTy::U8)),
1721 U16 => single(SimplifiedType::Uint(UintTy::U16)),
1722 U32 => single(SimplifiedType::Uint(UintTy::U32)),
1723 U64 => single(SimplifiedType::Uint(UintTy::U64)),
1724 U128 => single(SimplifiedType::Uint(UintTy::U128)),
1725 F16 => single(SimplifiedType::Float(FloatTy::F16)),
1726 F32 => single(SimplifiedType::Float(FloatTy::F32)),
1727 F64 => single(SimplifiedType::Float(FloatTy::F64)),
1728 F128 => single(SimplifiedType::Float(FloatTy::F128)),
1729 Str => single(SimplifiedType::Str),
1730 Bool => single(SimplifiedType::Bool),
1731 Char => single(SimplifiedType::Char),
1732 Array => single(SimplifiedType::Array),
1733 Slice => single(SimplifiedType::Slice),
1734 Tuple => [SimplifiedType::Tuple(1), SimplifiedType::Tuple(2), SimplifiedType::Tuple(3)].into(),
1740 Unit => single(SimplifiedType::Tuple(0)),
1741 RawPointer => [SimplifiedType::Ptr(Mutability::Not), SimplifiedType::Ptr(Mutability::Mut)].into_iter().collect(),
1742 Reference => [SimplifiedType::Ref(Mutability::Not), SimplifiedType::Ref(Mutability::Mut)].into_iter().collect(),
1743 Fn => single(SimplifiedType::Function(1)),
1746 Never => single(SimplifiedType::Never),
1747 }
1748 })
1749 }
1750
1751 pub(crate) fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = DefId> + 'tcx {
1752 Self::simplified_types()
1753 .get(self)
1754 .into_iter()
1755 .flatten()
1756 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1757 .copied()
1758 }
1759
1760 pub(crate) fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> {
1761 Self::simplified_types()
1762 .values()
1763 .flatten()
1764 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1765 .copied()
1766 }
1767
1768 pub(crate) fn as_sym(&self) -> Symbol {
1769 use PrimitiveType::*;
1770 match self {
1771 Isize => sym::isize,
1772 I8 => sym::i8,
1773 I16 => sym::i16,
1774 I32 => sym::i32,
1775 I64 => sym::i64,
1776 I128 => sym::i128,
1777 Usize => sym::usize,
1778 U8 => sym::u8,
1779 U16 => sym::u16,
1780 U32 => sym::u32,
1781 U64 => sym::u64,
1782 U128 => sym::u128,
1783 F16 => sym::f16,
1784 F32 => sym::f32,
1785 F64 => sym::f64,
1786 F128 => sym::f128,
1787 Str => sym::str,
1788 Bool => sym::bool,
1789 Char => sym::char,
1790 Array => sym::array,
1791 Pat => sym::pat,
1792 FieldOf => sym::field_of,
1793 Slice => sym::slice,
1794 Tuple => sym::tuple,
1795 Unit => sym::unit,
1796 RawPointer => sym::pointer,
1797 Reference => sym::reference,
1798 Fn => kw::Fn,
1799 Never => sym::never,
1800 }
1801 }
1802
1803 pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxIndexMap<PrimitiveType, DefId> {
1815 static PRIMITIVE_LOCATIONS: OnceCell<FxIndexMap<PrimitiveType, DefId>> = OnceCell::new();
1816 PRIMITIVE_LOCATIONS.get_or_init(|| {
1817 let mut primitive_locations = FxIndexMap::default();
1818 for &crate_num in tcx.crates(()) {
1821 let e = ExternalCrate { crate_num };
1822 let crate_name = e.name(tcx);
1823 debug!(?crate_num, ?crate_name);
1824 for (def_id, prim) in e.primitives(tcx) {
1825 if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1827 continue;
1828 }
1829 primitive_locations.insert(prim, def_id);
1830 }
1831 }
1832 let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1833 for (def_id, prim) in local_primitives {
1834 primitive_locations.insert(prim, def_id);
1835 }
1836 primitive_locations
1837 })
1838 }
1839}
1840
1841impl From<ty::IntTy> for PrimitiveType {
1842 fn from(int_ty: ty::IntTy) -> PrimitiveType {
1843 match int_ty {
1844 ty::IntTy::Isize => PrimitiveType::Isize,
1845 ty::IntTy::I8 => PrimitiveType::I8,
1846 ty::IntTy::I16 => PrimitiveType::I16,
1847 ty::IntTy::I32 => PrimitiveType::I32,
1848 ty::IntTy::I64 => PrimitiveType::I64,
1849 ty::IntTy::I128 => PrimitiveType::I128,
1850 }
1851 }
1852}
1853
1854impl From<ty::UintTy> for PrimitiveType {
1855 fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1856 match uint_ty {
1857 ty::UintTy::Usize => PrimitiveType::Usize,
1858 ty::UintTy::U8 => PrimitiveType::U8,
1859 ty::UintTy::U16 => PrimitiveType::U16,
1860 ty::UintTy::U32 => PrimitiveType::U32,
1861 ty::UintTy::U64 => PrimitiveType::U64,
1862 ty::UintTy::U128 => PrimitiveType::U128,
1863 }
1864 }
1865}
1866
1867impl From<ty::FloatTy> for PrimitiveType {
1868 fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1869 match float_ty {
1870 ty::FloatTy::F16 => PrimitiveType::F16,
1871 ty::FloatTy::F32 => PrimitiveType::F32,
1872 ty::FloatTy::F64 => PrimitiveType::F64,
1873 ty::FloatTy::F128 => PrimitiveType::F128,
1874 }
1875 }
1876}
1877
1878impl From<hir::PrimTy> for PrimitiveType {
1879 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1880 match prim_ty {
1881 hir::PrimTy::Int(int_ty) => int_ty.into(),
1882 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1883 hir::PrimTy::Float(float_ty) => float_ty.into(),
1884 hir::PrimTy::Str => PrimitiveType::Str,
1885 hir::PrimTy::Bool => PrimitiveType::Bool,
1886 hir::PrimTy::Char => PrimitiveType::Char,
1887 }
1888 }
1889}
1890
1891#[derive(Clone, Debug)]
1892pub(crate) struct Struct {
1893 pub(crate) ctor_kind: Option<CtorKind>,
1894 pub(crate) generics: Generics,
1895 pub(crate) fields: ThinVec<Item>,
1896}
1897
1898impl Struct {
1899 pub(crate) fn has_stripped_entries(&self) -> bool {
1900 self.fields.iter().any(|f| f.is_stripped())
1901 }
1902}
1903
1904#[derive(Clone, Debug)]
1905pub(crate) struct Union {
1906 pub(crate) generics: Generics,
1907 pub(crate) fields: Vec<Item>,
1908}
1909
1910impl Union {
1911 pub(crate) fn has_stripped_entries(&self) -> bool {
1912 self.fields.iter().any(|f| f.is_stripped())
1913 }
1914}
1915
1916#[derive(Clone, Debug)]
1920pub(crate) struct VariantStruct {
1921 pub(crate) fields: ThinVec<Item>,
1922}
1923
1924impl VariantStruct {
1925 pub(crate) fn has_stripped_entries(&self) -> bool {
1926 self.fields.iter().any(|f| f.is_stripped())
1927 }
1928}
1929
1930#[derive(Clone, Debug)]
1931pub(crate) struct Enum {
1932 pub(crate) variants: IndexVec<VariantIdx, Item>,
1933 pub(crate) generics: Generics,
1934}
1935
1936impl Enum {
1937 pub(crate) fn has_stripped_entries(&self) -> bool {
1938 self.variants.iter().any(|f| f.is_stripped())
1939 }
1940
1941 pub(crate) fn non_stripped_variants(&self) -> impl Iterator<Item = &Item> {
1942 self.variants.iter().filter(|v| !v.is_stripped())
1943 }
1944}
1945
1946#[derive(Clone, Debug)]
1947pub(crate) struct Variant {
1948 pub kind: VariantKind,
1949 pub discriminant: Option<Discriminant>,
1950}
1951
1952#[derive(Clone, Debug)]
1953pub(crate) enum VariantKind {
1954 CLike,
1955 Tuple(ThinVec<Item>),
1956 Struct(VariantStruct),
1957}
1958
1959impl Variant {
1960 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
1961 match &self.kind {
1962 VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()),
1963 VariantKind::CLike | VariantKind::Tuple(_) => None,
1964 }
1965 }
1966}
1967
1968#[derive(Clone, Debug)]
1969pub(crate) struct Discriminant {
1970 pub(super) expr: Option<BodyId>,
1973 pub(super) value: DefId,
1974}
1975
1976impl Discriminant {
1977 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
1980 self.expr
1981 .map(|body| rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body)))
1982 }
1983 pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String {
1984 print_evaluated_const(tcx, self.value, with_underscores, false).unwrap()
1985 }
1986}
1987
1988#[derive(Copy, Clone, Debug)]
1991pub(crate) struct Span(rustc_span::Span);
1992
1993impl Span {
1994 pub(crate) fn new(sp: rustc_span::Span) -> Self {
1999 Self(sp.source_callsite())
2000 }
2001
2002 pub(crate) fn inner(&self) -> rustc_span::Span {
2003 self.0
2004 }
2005
2006 pub(crate) fn filename(&self, sess: &Session) -> FileName {
2007 sess.source_map().span_to_filename(self.0)
2008 }
2009
2010 pub(crate) fn lo(&self, sess: &Session) -> Loc {
2011 sess.source_map().lookup_char_pos(self.0.lo())
2012 }
2013
2014 pub(crate) fn hi(&self, sess: &Session) -> Loc {
2015 sess.source_map().lookup_char_pos(self.0.hi())
2016 }
2017
2018 pub(crate) fn cnum(&self, sess: &Session) -> CrateNum {
2019 self.lo(sess).file.cnum
2021 }
2022}
2023
2024#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2025pub(crate) struct Path {
2026 pub(crate) res: Res,
2027 pub(crate) segments: ThinVec<PathSegment>,
2028}
2029
2030impl Path {
2031 pub(crate) fn def_id(&self) -> DefId {
2032 self.res.def_id()
2033 }
2034
2035 pub(crate) fn last_opt(&self) -> Option<Symbol> {
2036 self.segments.last().map(|s| s.name)
2037 }
2038
2039 pub(crate) fn last(&self) -> Symbol {
2040 self.last_opt().expect("segments were empty")
2041 }
2042
2043 pub(crate) fn whole_name(&self) -> String {
2044 self.segments
2045 .iter()
2046 .map(|s| if s.name == kw::PathRoot { "" } else { s.name.as_str() })
2047 .intersperse("::")
2048 .collect()
2049 }
2050
2051 pub(crate) fn is_assoc_ty(&self) -> bool {
2053 match self.res {
2054 Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _)
2055 if self.segments.len() != 1 =>
2056 {
2057 true
2058 }
2059 Res::Def(DefKind::AssocTy, _) => true,
2060 _ => false,
2061 }
2062 }
2063
2064 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
2065 self.segments.last().map(|seg| &seg.args)
2066 }
2067
2068 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
2069 self.segments.last().and_then(|seg| {
2070 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2071 Some(args.iter().filter_map(|arg| match arg {
2072 GenericArg::Type(ty) => Some(ty),
2073 _ => None,
2074 }))
2075 } else {
2076 None
2077 }
2078 })
2079 }
2080}
2081
2082#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2083pub(crate) enum GenericArg {
2084 Lifetime(Lifetime),
2085 Type(Type),
2086 Const(Box<ConstantKind>),
2087 Infer,
2088}
2089
2090impl GenericArg {
2091 pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
2092 if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2093 }
2094
2095 pub(crate) fn as_ty(&self) -> Option<&Type> {
2096 if let Self::Type(ty) = self { Some(ty) } else { None }
2097 }
2098}
2099
2100#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2101pub(crate) enum GenericArgs {
2102 AngleBracketed { args: ThinVec<GenericArg>, constraints: ThinVec<AssocItemConstraint> },
2104 Parenthesized { inputs: ThinVec<Type>, output: Option<Box<Type>> },
2106 ReturnTypeNotation,
2108}
2109
2110impl GenericArgs {
2111 pub(crate) fn is_empty(&self) -> bool {
2112 match self {
2113 GenericArgs::AngleBracketed { args, constraints } => {
2114 args.is_empty() && constraints.is_empty()
2115 }
2116 GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
2117 GenericArgs::ReturnTypeNotation => false,
2118 }
2119 }
2120 pub(crate) fn constraints(&self) -> Box<dyn Iterator<Item = AssocItemConstraint> + '_> {
2121 match self {
2122 GenericArgs::AngleBracketed { constraints, .. } => {
2123 Box::new(constraints.iter().cloned())
2124 }
2125 GenericArgs::Parenthesized { output, .. } => Box::new(
2126 output
2127 .as_ref()
2128 .map(|ty| AssocItemConstraint {
2129 assoc: PathSegment {
2130 name: sym::Output,
2131 args: GenericArgs::AngleBracketed {
2132 args: ThinVec::new(),
2133 constraints: ThinVec::new(),
2134 },
2135 },
2136 kind: AssocItemConstraintKind::Equality {
2137 term: Term::Type((**ty).clone()),
2138 },
2139 })
2140 .into_iter(),
2141 ),
2142 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2143 }
2144 }
2145}
2146
2147impl<'a> IntoIterator for &'a GenericArgs {
2148 type IntoIter = Box<dyn Iterator<Item = GenericArg> + 'a>;
2149 type Item = GenericArg;
2150 fn into_iter(self) -> Self::IntoIter {
2151 match self {
2152 GenericArgs::AngleBracketed { args, .. } => Box::new(args.iter().cloned()),
2153 GenericArgs::Parenthesized { inputs, .. } => {
2154 Box::new(inputs.iter().cloned().map(GenericArg::Type))
2156 }
2157 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2158 }
2159 }
2160}
2161
2162#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2163pub(crate) struct PathSegment {
2164 pub(crate) name: Symbol,
2165 pub(crate) args: GenericArgs,
2166}
2167
2168#[derive(Clone, Debug)]
2169pub(crate) enum TypeAliasInnerType {
2170 Enum { variants: IndexVec<VariantIdx, Item>, is_non_exhaustive: bool },
2171 Union { fields: Vec<Item> },
2172 Struct { ctor_kind: Option<CtorKind>, fields: Vec<Item> },
2173}
2174
2175impl TypeAliasInnerType {
2176 fn has_stripped_entries(&self) -> Option<bool> {
2177 Some(match self {
2178 Self::Enum { variants, .. } => variants.iter().any(|v| v.is_stripped()),
2179 Self::Union { fields } | Self::Struct { fields, .. } => {
2180 fields.iter().any(|f| f.is_stripped())
2181 }
2182 })
2183 }
2184}
2185
2186#[derive(Clone, Debug)]
2187pub(crate) struct TypeAlias {
2188 pub(crate) type_: Type,
2189 pub(crate) generics: Generics,
2190 pub(crate) inner_type: Option<TypeAliasInnerType>,
2193 pub(crate) item_type: Option<Type>,
2200}
2201
2202#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2203pub(crate) struct BareFunctionDecl {
2204 pub(crate) safety: hir::Safety,
2205 pub(crate) generic_params: Vec<GenericParamDef>,
2206 pub(crate) decl: FnDecl,
2207 pub(crate) abi: ExternAbi,
2208}
2209
2210#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2211pub(crate) struct UnsafeBinderTy {
2212 pub(crate) generic_params: Vec<GenericParamDef>,
2213 pub(crate) ty: Type,
2214}
2215
2216#[derive(Clone, Debug)]
2217pub(crate) struct Static {
2218 pub(crate) type_: Box<Type>,
2219 pub(crate) mutability: Mutability,
2220 pub(crate) expr: Option<BodyId>,
2221}
2222
2223#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2224pub(crate) struct Constant {
2225 pub(crate) generics: Generics,
2226 pub(crate) kind: ConstantKind,
2227 pub(crate) type_: Type,
2228}
2229
2230#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2231pub(crate) enum Term {
2232 Type(Type),
2233 Constant(ConstantKind),
2234}
2235
2236impl Term {
2237 pub(crate) fn ty(&self) -> Option<&Type> {
2238 if let Term::Type(ty) = self { Some(ty) } else { None }
2239 }
2240}
2241
2242impl From<Type> for Term {
2243 fn from(ty: Type) -> Self {
2244 Term::Type(ty)
2245 }
2246}
2247
2248#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2249pub(crate) enum ConstantKind {
2250 TyConst { expr: Box<str> },
2256 Path { path: Box<str> },
2259 Anonymous { body: BodyId },
2263 Extern { def_id: DefId },
2265 Local { def_id: DefId, body: BodyId },
2267 Infer,
2269}
2270
2271impl ConstantKind {
2272 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2273 match *self {
2274 ConstantKind::TyConst { ref expr } => expr.to_string(),
2275 ConstantKind::Path { ref path } => path.to_string(),
2276 ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2277 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2278 rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body))
2279 }
2280 ConstantKind::Infer => "_".to_string(),
2281 }
2282 }
2283
2284 pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2285 match *self {
2286 ConstantKind::TyConst { .. }
2287 | ConstantKind::Path { .. }
2288 | ConstantKind::Anonymous { .. }
2289 | ConstantKind::Infer => None,
2290 ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2291 print_evaluated_const(tcx, def_id, true, true)
2292 }
2293 }
2294 }
2295
2296 pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2297 match *self {
2298 ConstantKind::TyConst { .. }
2299 | ConstantKind::Extern { .. }
2300 | ConstantKind::Path { .. }
2301 | ConstantKind::Infer => false,
2302 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2303 is_literal_expr(tcx, body.hir_id)
2304 }
2305 }
2306 }
2307}
2308
2309#[derive(Clone, Debug)]
2310pub(crate) struct Impl {
2311 pub(crate) safety: hir::Safety,
2312 pub(crate) generics: Generics,
2313 pub(crate) trait_: Option<Path>,
2314 pub(crate) for_: Type,
2315 pub(crate) items: Vec<Item>,
2316 pub(crate) polarity: ty::ImplPolarity,
2317 pub(crate) kind: ImplKind,
2318 pub(crate) is_deprecated: bool,
2319}
2320
2321impl Impl {
2322 pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxIndexSet<Symbol> {
2323 self.trait_
2324 .as_ref()
2325 .map(|t| t.def_id())
2326 .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name()).collect())
2327 .unwrap_or_default()
2328 }
2329
2330 pub(crate) fn is_negative_trait_impl(&self) -> bool {
2331 matches!(self.polarity, ty::ImplPolarity::Negative)
2332 }
2333}
2334
2335#[derive(Clone, Debug)]
2336pub(crate) enum ImplKind {
2337 Normal,
2338 Auto,
2339 FakeVariadic,
2340 Blanket(Box<Type>),
2341}
2342
2343impl ImplKind {
2344 pub(crate) fn is_auto(&self) -> bool {
2345 matches!(self, ImplKind::Auto)
2346 }
2347
2348 pub(crate) fn is_blanket(&self) -> bool {
2349 matches!(self, ImplKind::Blanket(_))
2350 }
2351
2352 pub(crate) fn is_fake_variadic(&self) -> bool {
2353 matches!(self, ImplKind::FakeVariadic)
2354 }
2355
2356 pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
2357 match self {
2358 ImplKind::Blanket(ty) => Some(ty),
2359 _ => None,
2360 }
2361 }
2362}
2363
2364#[derive(Clone, Debug)]
2365pub(crate) struct Import {
2366 pub(crate) kind: ImportKind,
2367 pub(crate) source: ImportSource,
2369 pub(crate) should_be_displayed: bool,
2370}
2371
2372impl Import {
2373 pub(crate) fn new_simple(
2374 name: Symbol,
2375 source: ImportSource,
2376 should_be_displayed: bool,
2377 ) -> Self {
2378 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2379 }
2380
2381 pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2382 Self { kind: ImportKind::Glob, source, should_be_displayed }
2383 }
2384
2385 pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool {
2386 self.source.did.is_some_and(|did| tcx.is_doc_hidden(did))
2387 }
2388}
2389
2390#[derive(Clone, Debug)]
2391pub(crate) enum ImportKind {
2392 Simple(Symbol),
2394 Glob,
2396}
2397
2398#[derive(Clone, Debug)]
2399pub(crate) struct ImportSource {
2400 pub(crate) path: Path,
2401 pub(crate) did: Option<DefId>,
2402}
2403
2404#[derive(Clone, Debug)]
2405pub(crate) struct Macro {
2406 pub(crate) source: String,
2407 pub(crate) macro_rules: bool,
2409}
2410
2411#[derive(Clone, Debug)]
2412pub(crate) struct ProcMacro {
2413 pub(crate) kind: MacroKind,
2414 pub(crate) helpers: Vec<Symbol>,
2415}
2416
2417#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2428pub(crate) struct AssocItemConstraint {
2429 pub(crate) assoc: PathSegment,
2430 pub(crate) kind: AssocItemConstraintKind,
2431}
2432
2433#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2435pub(crate) enum AssocItemConstraintKind {
2436 Equality { term: Term },
2437 Bound { bounds: Vec<GenericBound> },
2438}
2439
2440#[cfg(target_pointer_width = "64")]
2442mod size_asserts {
2443 use rustc_data_structures::static_assert_size;
2444
2445 use super::*;
2446 static_assert_size!(Crate, 16); static_assert_size!(DocFragment, 48);
2449 static_assert_size!(GenericArg, 32);
2450 static_assert_size!(GenericArgs, 24);
2451 static_assert_size!(GenericParamDef, 40);
2452 static_assert_size!(Generics, 16);
2453 static_assert_size!(Item, 8);
2454 static_assert_size!(ItemInner, 136);
2455 static_assert_size!(ItemKind, 48);
2456 static_assert_size!(PathSegment, 32);
2457 static_assert_size!(Type, 32);
2458 }