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::attr::AttributeExt;
11use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
12use rustc_data_structures::thin_vec::ThinVec;
13use rustc_hir::attrs::{AttributeKind, DeprecatedSince, Deprecation, DocAttribute};
14use rustc_hir::def::{CtorKind, DefKind, Res};
15use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
16use rustc_hir::lang_items::LangItem;
17use rustc_hir::{Attribute, BodyId, ConstStability, Mutability, Stability, StableSince, find_attr};
18use rustc_index::IndexVec;
19use rustc_metadata::rendered_const;
20use rustc_middle::span_bug;
21use rustc_middle::ty::fast_reject::SimplifiedType;
22use rustc_middle::ty::{self, TyCtxt, Visibility};
23use rustc_resolve::rustdoc::{
24 DocFragment, add_doc_fragment, attrs_to_doc_fragments, inner_docs, span_of_fragments,
25};
26use rustc_session::Session;
27use rustc_span::hygiene::MacroKind;
28use rustc_span::symbol::{Symbol, kw, sym};
29use rustc_span::{DUMMY_SP, FileName, Ident, Loc, RemapPathScopeComponents};
30use tracing::{debug, trace};
31use {rustc_ast as ast, rustc_hir as hir};
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
64impl ItemId {
65 #[inline]
66 pub(crate) fn is_local(self) -> bool {
67 match self {
68 ItemId::Auto { for_: id, .. }
69 | ItemId::Blanket { for_: id, .. }
70 | ItemId::DefId(id) => id.is_local(),
71 }
72 }
73
74 #[inline]
75 #[track_caller]
76 pub(crate) fn expect_def_id(self) -> DefId {
77 self.as_def_id()
78 .unwrap_or_else(|| panic!("ItemId::expect_def_id: `{self:?}` isn't a DefId"))
79 }
80
81 #[inline]
82 pub(crate) fn as_def_id(self) -> Option<DefId> {
83 match self {
84 ItemId::DefId(id) => Some(id),
85 _ => None,
86 }
87 }
88
89 #[inline]
90 pub(crate) fn as_local_def_id(self) -> Option<LocalDefId> {
91 self.as_def_id().and_then(|id| id.as_local())
92 }
93
94 #[inline]
95 pub(crate) fn krate(self) -> CrateNum {
96 match self {
97 ItemId::Auto { for_: id, .. }
98 | ItemId::Blanket { for_: id, .. }
99 | ItemId::DefId(id) => id.krate,
100 }
101 }
102}
103
104impl From<DefId> for ItemId {
105 fn from(id: DefId) -> Self {
106 Self::DefId(id)
107 }
108}
109
110#[derive(Debug)]
112pub(crate) struct Crate {
113 pub(crate) module: Item,
114 pub(crate) external_traits: Box<FxIndexMap<DefId, Trait>>,
116}
117
118impl Crate {
119 pub(crate) fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
120 ExternalCrate::LOCAL.name(tcx)
121 }
122
123 pub(crate) fn src(&self, tcx: TyCtxt<'_>) -> FileName {
124 ExternalCrate::LOCAL.src(tcx)
125 }
126}
127
128#[derive(Copy, Clone, Debug)]
129pub(crate) struct ExternalCrate {
130 pub(crate) crate_num: CrateNum,
131}
132
133impl ExternalCrate {
134 const LOCAL: Self = Self { crate_num: LOCAL_CRATE };
135
136 #[inline]
137 pub(crate) fn def_id(&self) -> DefId {
138 self.crate_num.as_def_id()
139 }
140
141 pub(crate) fn src(&self, tcx: TyCtxt<'_>) -> FileName {
142 let krate_span = tcx.def_span(self.def_id());
143 tcx.sess.source_map().span_to_filename(krate_span)
144 }
145
146 pub(crate) fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
147 tcx.crate_name(self.crate_num)
148 }
149
150 pub(crate) fn src_root(&self, tcx: TyCtxt<'_>) -> PathBuf {
151 match self.src(tcx) {
152 FileName::Real(ref p) => {
153 match p
154 .local_path()
155 .or(Some(p.path(RemapPathScopeComponents::DOCUMENTATION)))
156 .unwrap()
157 .parent()
158 {
159 Some(p) => p.to_path_buf(),
160 None => PathBuf::new(),
161 }
162 }
163 _ => PathBuf::new(),
164 }
165 }
166
167 pub(crate) fn location(
170 &self,
171 extern_url: Option<&str>,
172 extern_url_takes_precedence: bool,
173 dst: &std::path::Path,
174 tcx: TyCtxt<'_>,
175 ) -> ExternalLocation {
176 use ExternalLocation::*;
177
178 fn to_remote(url: impl ToString) -> ExternalLocation {
179 let mut url = url.to_string();
180 if !url.ends_with('/') {
181 url.push('/');
182 }
183 Remote(url)
184 }
185
186 let local_location = dst.join(self.name(tcx).as_str());
190 if local_location.is_dir() {
191 return Local;
192 }
193
194 if extern_url_takes_precedence && let Some(url) = extern_url {
195 return to_remote(url);
196 }
197
198 let did = self.crate_num.as_def_id();
201 tcx.get_all_attrs(did)
202 .iter()
203 .find_map(|a| match a {
204 Attribute::Parsed(AttributeKind::Doc(d)) => d.html_root_url.map(|(url, _)| url),
205 _ => None,
206 })
207 .map(to_remote)
208 .or_else(|| extern_url.map(to_remote)) .unwrap_or(Unknown) }
211
212 fn mapped_root_modules<T>(
213 &self,
214 tcx: TyCtxt<'_>,
215 f: impl Fn(DefId, TyCtxt<'_>) -> Option<(DefId, T)>,
216 ) -> impl Iterator<Item = (DefId, T)> {
217 let root = self.def_id();
218
219 if root.is_local() {
220 Either::Left(
221 tcx.hir_root_module()
222 .item_ids
223 .iter()
224 .filter(move |&&id| matches!(tcx.hir_item(id).kind, hir::ItemKind::Mod(..)))
225 .filter_map(move |&id| f(id.owner_id.into(), tcx)),
226 )
227 } else {
228 Either::Right(
229 tcx.module_children(root)
230 .iter()
231 .filter_map(|item| {
232 if let Res::Def(DefKind::Mod, did) = item.res { Some(did) } else { None }
233 })
234 .filter_map(move |did| f(did, tcx)),
235 )
236 }
237 }
238
239 pub(crate) fn keywords(&self, tcx: TyCtxt<'_>) -> impl Iterator<Item = (DefId, Symbol)> {
240 self.retrieve_keywords_or_documented_attributes(tcx, |d| d.keyword.map(|(v, _)| v))
241 }
242 pub(crate) fn documented_attributes(
243 &self,
244 tcx: TyCtxt<'_>,
245 ) -> impl Iterator<Item = (DefId, Symbol)> {
246 self.retrieve_keywords_or_documented_attributes(tcx, |d| d.attribute.map(|(v, _)| v))
247 }
248
249 fn retrieve_keywords_or_documented_attributes<F: Fn(&DocAttribute) -> Option<Symbol>>(
250 &self,
251 tcx: TyCtxt<'_>,
252 callback: F,
253 ) -> impl Iterator<Item = (DefId, Symbol)> {
254 let as_target = move |did: DefId, tcx: TyCtxt<'_>| -> Option<(DefId, Symbol)> {
255 tcx.get_all_attrs(did)
256 .iter()
257 .find_map(|attr| match attr {
258 Attribute::Parsed(AttributeKind::Doc(d)) => callback(d),
259 _ => None,
260 })
261 .map(|value| (did, value))
262 };
263 self.mapped_root_modules(tcx, as_target)
264 }
265
266 pub(crate) fn primitives(
267 &self,
268 tcx: TyCtxt<'_>,
269 ) -> impl Iterator<Item = (DefId, PrimitiveType)> {
270 fn as_primitive(def_id: DefId, tcx: TyCtxt<'_>) -> Option<(DefId, PrimitiveType)> {
288 tcx.get_attrs(def_id, sym::rustc_doc_primitive).next().map(|attr| {
289 let attr_value = attr.value_str().expect("syntax should already be validated");
290 let Some(prim) = PrimitiveType::from_symbol(attr_value) else {
291 span_bug!(
292 attr.span(),
293 "primitive `{attr_value}` is not a member of `PrimitiveType`"
294 );
295 };
296
297 (def_id, prim)
298 })
299 }
300
301 self.mapped_root_modules(tcx, as_primitive)
302 }
303}
304
305#[derive(Debug)]
307pub(crate) enum ExternalLocation {
308 Remote(String),
310 Local,
312 Unknown,
314}
315
316#[derive(Clone)]
320pub(crate) struct Item {
321 pub(crate) inner: Box<ItemInner>,
322}
323
324#[derive(Clone)]
330pub(crate) struct ItemInner {
331 pub(crate) name: Option<Symbol>,
334 pub(crate) kind: ItemKind,
337 pub(crate) attrs: Attributes,
338 pub(crate) stability: Option<Stability>,
340 pub(crate) item_id: ItemId,
341 pub(crate) inline_stmt_id: Option<LocalDefId>,
345 pub(crate) cfg: Option<Arc<Cfg>>,
346}
347
348impl std::ops::Deref for Item {
349 type Target = ItemInner;
350 fn deref(&self) -> &ItemInner {
351 &self.inner
352 }
353}
354
355impl fmt::Debug for Item {
358 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
359 let alternate = f.alternate();
360 let mut fmt = f.debug_struct("Item");
362 fmt.field("name", &self.name).field("item_id", &self.item_id);
363 if alternate {
365 fmt.field("attrs", &self.attrs).field("kind", &self.kind).field("cfg", &self.cfg);
366 } else {
367 fmt.field("kind", &self.type_());
368 fmt.field("docs", &self.doc_value());
369 }
370 fmt.finish()
371 }
372}
373
374pub(crate) fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
375 Span::new(def_id.as_local().map_or_else(
376 || tcx.def_span(def_id),
377 |local| tcx.hir_span_with_body(tcx.local_def_id_to_hir_id(local)),
378 ))
379}
380
381fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
382 let parent = tcx.parent(def_id);
383 match tcx.def_kind(parent) {
384 DefKind::Struct | DefKind::Union => false,
385 DefKind::Variant => true,
386 parent_kind => panic!("unexpected parent kind: {parent_kind:?}"),
387 }
388}
389
390impl Item {
391 pub(crate) fn stability(&self, tcx: TyCtxt<'_>) -> Option<Stability> {
395 let stability = self.inner.stability;
396 debug_assert!(
397 stability.is_some()
398 || self.def_id().is_none_or(|did| tcx.lookup_stability(did).is_none()),
399 "missing stability for cleaned item: {self:?}",
400 );
401 stability
402 }
403
404 pub(crate) fn const_stability(&self, tcx: TyCtxt<'_>) -> Option<ConstStability> {
405 self.def_id().and_then(|did| tcx.lookup_const_stability(did))
406 }
407
408 pub(crate) fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
409 self.def_id().and_then(|did| tcx.lookup_deprecation(did)).or_else(|| {
410 let stab = self.stability(tcx)?;
414 if let rustc_hir::StabilityLevel::Stable {
415 allowed_through_unstable_modules: Some(note),
416 ..
417 } = stab.level
418 {
419 Some(Deprecation {
420 since: DeprecatedSince::Unspecified,
421 note: Some(Ident { name: note, span: DUMMY_SP }),
422 suggestion: None,
423 })
424 } else {
425 None
426 }
427 })
428 }
429
430 pub(crate) fn is_deprecated(&self, tcx: TyCtxt<'_>) -> bool {
431 self.deprecation(tcx).is_some_and(|deprecation| deprecation.is_in_effect())
432 }
433
434 pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
435 self.item_id.as_def_id().map(|did| inner_docs(tcx.get_all_attrs(did))).unwrap_or(false)
436 }
437
438 pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option<Span> {
439 let kind = match &self.kind {
440 ItemKind::StrippedItem(k) => k,
441 _ => &self.kind,
442 };
443 match kind {
444 ItemKind::ModuleItem(Module { span, .. }) => Some(*span),
445 ItemKind::ImplItem(box Impl { kind: ImplKind::Auto, .. }) => None,
446 ItemKind::ImplItem(box Impl { kind: ImplKind::Blanket(_), .. }) => {
447 if let ItemId::Blanket { impl_id, .. } = self.item_id {
448 Some(rustc_span(impl_id, tcx))
449 } else {
450 panic!("blanket impl item has non-blanket ID")
451 }
452 }
453 _ => self.def_id().map(|did| rustc_span(did, tcx)),
454 }
455 }
456
457 pub(crate) fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
458 let deprecation_notes = self
459 .attrs
460 .other_attrs
461 .iter()
462 .filter_map(|attr| attr.deprecation_note().map(|note| note.span));
463
464 span_of_fragments(&self.attrs.doc_strings)
465 .into_iter()
466 .chain(deprecation_notes)
467 .reduce(|a, b| a.to(b))
468 .unwrap_or_else(|| self.span(tcx).map_or(DUMMY_SP, |span| span.inner()))
469 }
470
471 pub(crate) fn doc_value(&self) -> String {
473 self.attrs.doc_value()
474 }
475
476 pub(crate) fn opt_doc_value(&self) -> Option<String> {
480 self.attrs.opt_doc_value()
481 }
482
483 pub(crate) fn from_def_id_and_parts(
484 def_id: DefId,
485 name: Option<Symbol>,
486 kind: ItemKind,
487 cx: &mut DocContext<'_>,
488 ) -> Item {
489 let hir_attrs = cx.tcx.get_all_attrs(def_id);
490
491 Self::from_def_id_and_attrs_and_parts(
492 def_id,
493 name,
494 kind,
495 Attributes::from_hir(hir_attrs),
496 None,
497 )
498 }
499
500 pub(crate) fn from_def_id_and_attrs_and_parts(
501 def_id: DefId,
502 name: Option<Symbol>,
503 kind: ItemKind,
504 attrs: Attributes,
505 cfg: Option<Arc<Cfg>>,
506 ) -> Item {
507 trace!("name={name:?}, def_id={def_id:?} cfg={cfg:?}");
508
509 Item {
510 inner: Box::new(ItemInner {
511 item_id: def_id.into(),
512 kind,
513 attrs,
514 stability: None,
515 name,
516 cfg,
517 inline_stmt_id: None,
518 }),
519 }
520 }
521
522 pub(crate) fn item_or_reexport_id(&self) -> ItemId {
528 self.attrs
530 .doc_strings
531 .first()
532 .map(|x| x.item_id)
533 .flatten()
534 .map(ItemId::from)
535 .unwrap_or(self.item_id)
536 }
537
538 pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
539 use crate::html::format::{href, link_tooltip};
540
541 let Some(links) = cx.cache().intra_doc_links.get(&self.item_or_reexport_id()) else {
542 return vec![];
543 };
544 links
545 .iter()
546 .filter_map(|ItemLink { link: s, link_text, page_id: id, fragment }| {
547 debug!(?id);
548 if let Ok(HrefInfo { mut url, .. }) = href(*id, cx) {
549 debug!(?url);
550 match fragment {
551 Some(UrlFragment::Item(def_id)) => {
552 write!(url, "{}", crate::html::format::fragment(*def_id, cx.tcx()))
553 .unwrap();
554 }
555 Some(UrlFragment::UserWritten(raw)) => {
556 url.push('#');
557 url.push_str(raw);
558 }
559 None => {}
560 }
561 Some(RenderedLink {
562 original_text: s.clone(),
563 new_text: link_text.clone(),
564 tooltip: link_tooltip(*id, fragment, cx).to_string(),
565 href: url,
566 })
567 } else {
568 None
569 }
570 })
571 .collect()
572 }
573
574 pub(crate) fn link_names(&self, cache: &Cache) -> Vec<RenderedLink> {
580 let Some(links) = cache.intra_doc_links.get(&self.item_id) else {
581 return vec![];
582 };
583 links
584 .iter()
585 .map(|ItemLink { link: s, link_text, .. }| RenderedLink {
586 original_text: s.clone(),
587 new_text: link_text.clone(),
588 href: String::new(),
589 tooltip: String::new(),
590 })
591 .collect()
592 }
593
594 pub(crate) fn is_crate(&self) -> bool {
595 self.is_mod() && self.def_id().is_some_and(|did| did.is_crate_root())
596 }
597 pub(crate) fn is_mod(&self) -> bool {
598 self.type_() == ItemType::Module
599 }
600 pub(crate) fn is_struct(&self) -> bool {
601 self.type_() == ItemType::Struct
602 }
603 pub(crate) fn is_enum(&self) -> bool {
604 self.type_() == ItemType::Enum
605 }
606 pub(crate) fn is_variant(&self) -> bool {
607 self.type_() == ItemType::Variant
608 }
609 pub(crate) fn is_associated_type(&self) -> bool {
610 matches!(self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..)))
611 }
612 pub(crate) fn is_required_associated_type(&self) -> bool {
613 matches!(self.kind, RequiredAssocTypeItem(..) | StrippedItem(box RequiredAssocTypeItem(..)))
614 }
615 pub(crate) fn is_associated_const(&self) -> bool {
616 matches!(self.kind, ProvidedAssocConstItem(..) | ImplAssocConstItem(..) | StrippedItem(box (ProvidedAssocConstItem(..) | ImplAssocConstItem(..))))
617 }
618 pub(crate) fn is_required_associated_const(&self) -> bool {
619 matches!(self.kind, RequiredAssocConstItem(..) | StrippedItem(box RequiredAssocConstItem(..)))
620 }
621 pub(crate) fn is_method(&self) -> bool {
622 self.type_() == ItemType::Method
623 }
624 pub(crate) fn is_ty_method(&self) -> bool {
625 self.type_() == ItemType::TyMethod
626 }
627 pub(crate) fn is_primitive(&self) -> bool {
628 self.type_() == ItemType::Primitive
629 }
630 pub(crate) fn is_union(&self) -> bool {
631 self.type_() == ItemType::Union
632 }
633 pub(crate) fn is_import(&self) -> bool {
634 self.type_() == ItemType::Import
635 }
636 pub(crate) fn is_extern_crate(&self) -> bool {
637 self.type_() == ItemType::ExternCrate
638 }
639 pub(crate) fn is_keyword(&self) -> bool {
640 self.type_() == ItemType::Keyword
641 }
642 pub(crate) fn is_attribute(&self) -> bool {
643 self.type_() == ItemType::Attribute
644 }
645 pub(crate) fn is_fake_item(&self) -> bool {
654 matches!(self.type_(), ItemType::Primitive | ItemType::Keyword | ItemType::Attribute)
655 }
656 pub(crate) fn is_stripped(&self) -> bool {
657 match self.kind {
658 StrippedItem(..) => true,
659 ImportItem(ref i) => !i.should_be_displayed,
660 _ => false,
661 }
662 }
663 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
664 match self.kind {
665 StructItem(ref struct_) => Some(struct_.has_stripped_entries()),
666 UnionItem(ref union_) => Some(union_.has_stripped_entries()),
667 EnumItem(ref enum_) => Some(enum_.has_stripped_entries()),
668 VariantItem(ref v) => v.has_stripped_entries(),
669 TypeAliasItem(ref type_alias) => {
670 type_alias.inner_type.as_ref().and_then(|t| t.has_stripped_entries())
671 }
672 _ => None,
673 }
674 }
675
676 pub(crate) fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
677 self.stability(tcx).as_ref().and_then(|s| {
678 let mut classes = Vec::with_capacity(2);
679
680 if s.is_unstable() {
681 classes.push("unstable");
682 }
683
684 if self.deprecation(tcx).is_some() {
686 classes.push("deprecated");
687 }
688
689 if !classes.is_empty() { Some(classes.join(" ")) } else { None }
690 })
691 }
692
693 pub(crate) fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<StableSince> {
694 self.stability(tcx).and_then(|stability| stability.stable_since())
695 }
696
697 pub(crate) fn is_non_exhaustive(&self) -> bool {
698 find_attr!(&self.attrs.other_attrs, AttributeKind::NonExhaustive(..))
699 }
700
701 pub(crate) fn type_(&self) -> ItemType {
703 ItemType::from(self)
704 }
705
706 pub(crate) fn is_default(&self) -> bool {
707 match self.kind {
708 ItemKind::MethodItem(_, Some(defaultness)) => {
709 defaultness.has_value() && !defaultness.is_final()
710 }
711 _ => false,
712 }
713 }
714
715 pub(crate) fn fn_header(&self, tcx: TyCtxt<'_>) -> Option<hir::FnHeader> {
717 fn build_fn_header(
718 def_id: DefId,
719 tcx: TyCtxt<'_>,
720 asyncness: ty::Asyncness,
721 ) -> hir::FnHeader {
722 let sig = tcx.fn_sig(def_id).skip_binder();
723 let constness = if tcx.is_const_fn(def_id) {
724 if let Some(assoc) = tcx.opt_associated_item(def_id)
728 && let ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) =
729 assoc.container
730 {
731 hir::Constness::NotConst
732 } else {
733 hir::Constness::Const
734 }
735 } else {
736 hir::Constness::NotConst
737 };
738 let asyncness = match asyncness {
739 ty::Asyncness::Yes => hir::IsAsync::Async(DUMMY_SP),
740 ty::Asyncness::No => hir::IsAsync::NotAsync,
741 };
742 hir::FnHeader {
743 safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
744 hir::HeaderSafety::SafeTargetFeatures
745 } else {
746 sig.safety().into()
747 },
748 abi: sig.abi(),
749 constness,
750 asyncness,
751 }
752 }
753 let header = match self.kind {
754 ItemKind::ForeignFunctionItem(_, safety) => {
755 let def_id = self.def_id().unwrap();
756 let abi = tcx.fn_sig(def_id).skip_binder().abi();
757 hir::FnHeader {
758 safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
759 hir::HeaderSafety::SafeTargetFeatures
760 } else {
761 safety.into()
762 },
763 abi,
764 constness: if tcx.is_const_fn(def_id) {
765 hir::Constness::Const
766 } else {
767 hir::Constness::NotConst
768 },
769 asyncness: hir::IsAsync::NotAsync,
770 }
771 }
772 ItemKind::FunctionItem(_)
773 | ItemKind::MethodItem(_, _)
774 | ItemKind::RequiredMethodItem(_) => {
775 let def_id = self.def_id().unwrap();
776 build_fn_header(def_id, tcx, tcx.asyncness(def_id))
777 }
778 _ => return None,
779 };
780 Some(header)
781 }
782
783 pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option<Visibility<DefId>> {
786 let def_id = match self.item_id {
787 ItemId::Auto { .. } | ItemId::Blanket { .. } => return None,
789 ItemId::DefId(def_id) => def_id,
790 };
791
792 match self.kind {
793 ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) | ItemKind::AttributeItem => {
797 return Some(Visibility::Public);
798 }
799 StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => {
801 return None;
802 }
803 VariantItem(..) | ImplItem(..) => return None,
805 RequiredAssocConstItem(..)
807 | ProvidedAssocConstItem(..)
808 | ImplAssocConstItem(..)
809 | AssocTypeItem(..)
810 | RequiredAssocTypeItem(..)
811 | RequiredMethodItem(..)
812 | MethodItem(..) => {
813 match tcx.associated_item(def_id).container {
814 ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) => {
817 return None;
818 }
819 ty::AssocContainer::InherentImpl => {}
820 }
821 }
822 _ => {}
823 }
824 let def_id = match self.inline_stmt_id {
825 Some(inlined) => inlined.to_def_id(),
826 None => def_id,
827 };
828 Some(tcx.visibility(def_id))
829 }
830
831 pub fn is_doc_hidden(&self) -> bool {
832 self.attrs.is_doc_hidden()
833 }
834
835 pub fn def_id(&self) -> Option<DefId> {
836 self.item_id.as_def_id()
837 }
838}
839
840#[derive(Clone, Debug)]
841pub(crate) enum ItemKind {
842 ExternCrateItem {
843 src: Option<Symbol>,
845 },
846 ImportItem(Import),
847 StructItem(Struct),
848 UnionItem(Union),
849 EnumItem(Enum),
850 FunctionItem(Box<Function>),
851 ModuleItem(Module),
852 TypeAliasItem(Box<TypeAlias>),
853 StaticItem(Static),
854 TraitItem(Box<Trait>),
855 TraitAliasItem(TraitAlias),
856 ImplItem(Box<Impl>),
857 RequiredMethodItem(Box<Function>),
859 MethodItem(Box<Function>, Option<hir::Defaultness>),
863 StructFieldItem(Type),
864 VariantItem(Variant),
865 ForeignFunctionItem(Box<Function>, hir::Safety),
867 ForeignStaticItem(Static, hir::Safety),
869 ForeignTypeItem,
871 MacroItem(Macro),
872 ProcMacroItem(ProcMacro),
873 PrimitiveItem(PrimitiveType),
874 RequiredAssocConstItem(Generics, Box<Type>),
876 ConstantItem(Box<Constant>),
877 ProvidedAssocConstItem(Box<Constant>),
879 ImplAssocConstItem(Box<Constant>),
881 RequiredAssocTypeItem(Generics, Vec<GenericBound>),
885 AssocTypeItem(Box<TypeAlias>, Vec<GenericBound>),
887 StrippedItem(Box<ItemKind>),
889 KeywordItem,
892 AttributeItem,
895}
896
897impl ItemKind {
898 pub(crate) fn inner_items(&self) -> impl Iterator<Item = &Item> {
901 match self {
902 StructItem(s) => s.fields.iter(),
903 UnionItem(u) => u.fields.iter(),
904 VariantItem(v) => match &v.kind {
905 VariantKind::CLike => [].iter(),
906 VariantKind::Tuple(t) => t.iter(),
907 VariantKind::Struct(s) => s.fields.iter(),
908 },
909 EnumItem(e) => e.variants.iter(),
910 TraitItem(t) => t.items.iter(),
911 ImplItem(i) => i.items.iter(),
912 ModuleItem(m) => m.items.iter(),
913 ExternCrateItem { .. }
914 | ImportItem(_)
915 | FunctionItem(_)
916 | TypeAliasItem(_)
917 | StaticItem(_)
918 | ConstantItem(_)
919 | TraitAliasItem(_)
920 | RequiredMethodItem(_)
921 | MethodItem(_, _)
922 | StructFieldItem(_)
923 | ForeignFunctionItem(_, _)
924 | ForeignStaticItem(_, _)
925 | ForeignTypeItem
926 | MacroItem(_)
927 | ProcMacroItem(_)
928 | PrimitiveItem(_)
929 | RequiredAssocConstItem(..)
930 | ProvidedAssocConstItem(..)
931 | ImplAssocConstItem(..)
932 | RequiredAssocTypeItem(..)
933 | AssocTypeItem(..)
934 | StrippedItem(_)
935 | KeywordItem
936 | AttributeItem => [].iter(),
937 }
938 }
939}
940
941#[derive(Clone, Debug)]
942pub(crate) struct Module {
943 pub(crate) items: Vec<Item>,
944 pub(crate) span: Span,
945}
946
947#[derive(Clone, Debug, PartialEq, Eq, Hash)]
951pub(crate) struct ItemLink {
952 pub(crate) link: Box<str>,
954 pub(crate) link_text: Box<str>,
959 pub(crate) page_id: DefId,
963 pub(crate) fragment: Option<UrlFragment>,
965}
966
967pub struct RenderedLink {
968 pub(crate) original_text: Box<str>,
972 pub(crate) new_text: Box<str>,
974 pub(crate) href: String,
976 pub(crate) tooltip: String,
978}
979
980#[derive(Clone, Debug, Default)]
983pub(crate) struct Attributes {
984 pub(crate) doc_strings: Vec<DocFragment>,
985 pub(crate) other_attrs: ThinVec<hir::Attribute>,
986}
987
988impl Attributes {
989 pub(crate) fn has_doc_flag<F: Fn(&DocAttribute) -> bool>(&self, callback: F) -> bool {
990 self.other_attrs
991 .iter()
992 .any(|a| matches!(a, Attribute::Parsed(AttributeKind::Doc(d)) if callback(d)))
993 }
994
995 pub(crate) fn is_doc_hidden(&self) -> bool {
996 find_attr!(&self.other_attrs, AttributeKind::Doc(d) if d.hidden.is_some())
997 }
998
999 pub(crate) fn from_hir(attrs: &[hir::Attribute]) -> Attributes {
1000 Attributes::from_hir_iter(attrs.iter().map(|attr| (attr, None)), false)
1001 }
1002
1003 pub(crate) fn from_hir_with_additional(
1004 attrs: &[hir::Attribute],
1005 (additional_attrs, def_id): (&[hir::Attribute], DefId),
1006 ) -> Attributes {
1007 let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id)));
1009 let attrs2 = attrs.iter().map(|attr| (attr, None));
1010 Attributes::from_hir_iter(attrs1.chain(attrs2), false)
1011 }
1012
1013 pub(crate) fn from_hir_iter<'a>(
1014 attrs: impl Iterator<Item = (&'a hir::Attribute, Option<DefId>)>,
1015 doc_only: bool,
1016 ) -> Attributes {
1017 let (doc_strings, other_attrs) = attrs_to_doc_fragments(attrs, doc_only);
1018 Attributes { doc_strings, other_attrs }
1019 }
1020
1021 pub(crate) fn doc_value(&self) -> String {
1023 self.opt_doc_value().unwrap_or_default()
1024 }
1025
1026 pub(crate) fn opt_doc_value(&self) -> Option<String> {
1030 (!self.doc_strings.is_empty()).then(|| {
1031 let mut res = String::new();
1032 for frag in &self.doc_strings {
1033 add_doc_fragment(&mut res, frag);
1034 }
1035 res.pop();
1036 res
1037 })
1038 }
1039
1040 pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> {
1041 let mut aliases = FxIndexSet::default();
1042
1043 for attr in &self.other_attrs {
1044 if let Attribute::Parsed(AttributeKind::Doc(d)) = attr {
1045 for (alias, _) in &d.aliases {
1046 aliases.insert(*alias);
1047 }
1048 }
1049 }
1050 aliases.into_iter().collect::<Vec<_>>().into()
1051 }
1052}
1053
1054#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1055pub(crate) enum GenericBound {
1056 TraitBound(PolyTrait, hir::TraitBoundModifiers),
1057 Outlives(Lifetime),
1058 Use(Vec<PreciseCapturingArg>),
1060}
1061
1062impl GenericBound {
1063 pub(crate) fn sized(cx: &mut DocContext<'_>) -> GenericBound {
1064 Self::sized_with(cx, hir::TraitBoundModifiers::NONE)
1065 }
1066
1067 pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1068 Self::sized_with(
1069 cx,
1070 hir::TraitBoundModifiers {
1071 polarity: hir::BoundPolarity::Maybe(DUMMY_SP),
1072 constness: hir::BoundConstness::Never,
1073 },
1074 )
1075 }
1076
1077 fn sized_with(cx: &mut DocContext<'_>, modifiers: hir::TraitBoundModifiers) -> GenericBound {
1078 let did = cx.tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
1079 let empty = ty::Binder::dummy(ty::GenericArgs::empty());
1080 let path = clean_middle_path(cx, did, false, ThinVec::new(), empty);
1081 inline::record_extern_fqn(cx, did, ItemType::Trait);
1082 GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifiers)
1083 }
1084
1085 pub(crate) fn is_trait_bound(&self) -> bool {
1086 matches!(self, Self::TraitBound(..))
1087 }
1088
1089 pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1090 self.is_bounded_by_lang_item(cx, LangItem::Sized)
1091 }
1092
1093 pub(crate) fn is_meta_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1094 self.is_bounded_by_lang_item(cx, LangItem::MetaSized)
1095 }
1096
1097 fn is_bounded_by_lang_item(&self, cx: &DocContext<'_>, lang_item: LangItem) -> bool {
1098 if let GenericBound::TraitBound(
1099 PolyTrait { ref trait_, .. },
1100 rustc_hir::TraitBoundModifiers::NONE,
1101 ) = *self
1102 && cx.tcx.is_lang_item(trait_.def_id(), lang_item)
1103 {
1104 return true;
1105 }
1106 false
1107 }
1108
1109 pub(crate) fn get_trait_path(&self) -> Option<Path> {
1110 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1111 Some(trait_.clone())
1112 } else {
1113 None
1114 }
1115 }
1116}
1117
1118#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1119pub(crate) struct Lifetime(pub Symbol);
1120
1121impl Lifetime {
1122 pub(crate) fn statik() -> Lifetime {
1123 Lifetime(kw::StaticLifetime)
1124 }
1125
1126 pub(crate) fn elided() -> Lifetime {
1127 Lifetime(kw::UnderscoreLifetime)
1128 }
1129}
1130
1131#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1132pub(crate) enum PreciseCapturingArg {
1133 Lifetime(Lifetime),
1134 Param(Symbol),
1135}
1136
1137impl PreciseCapturingArg {
1138 pub(crate) fn name(self) -> Symbol {
1139 match self {
1140 PreciseCapturingArg::Lifetime(lt) => lt.0,
1141 PreciseCapturingArg::Param(param) => param,
1142 }
1143 }
1144}
1145
1146#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1147pub(crate) enum WherePredicate {
1148 BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
1149 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1150 EqPredicate { lhs: QPathData, rhs: Term },
1151}
1152
1153impl WherePredicate {
1154 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1155 match self {
1156 WherePredicate::BoundPredicate { bounds, .. } => Some(bounds),
1157 WherePredicate::RegionPredicate { bounds, .. } => Some(bounds),
1158 _ => None,
1159 }
1160 }
1161}
1162
1163#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1164pub(crate) enum GenericParamDefKind {
1165 Lifetime { outlives: ThinVec<Lifetime> },
1166 Type { bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
1167 Const { ty: Box<Type>, default: Option<Box<String>> },
1169}
1170
1171impl GenericParamDefKind {
1172 pub(crate) fn is_type(&self) -> bool {
1173 matches!(self, GenericParamDefKind::Type { .. })
1174 }
1175}
1176
1177#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1178pub(crate) struct GenericParamDef {
1179 pub(crate) name: Symbol,
1180 pub(crate) def_id: DefId,
1181 pub(crate) kind: GenericParamDefKind,
1182}
1183
1184impl GenericParamDef {
1185 pub(crate) fn lifetime(def_id: DefId, name: Symbol) -> Self {
1186 Self { name, def_id, kind: GenericParamDefKind::Lifetime { outlives: ThinVec::new() } }
1187 }
1188
1189 pub(crate) fn is_synthetic_param(&self) -> bool {
1190 match self.kind {
1191 GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
1192 GenericParamDefKind::Type { synthetic, .. } => synthetic,
1193 }
1194 }
1195
1196 pub(crate) fn is_type(&self) -> bool {
1197 self.kind.is_type()
1198 }
1199
1200 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1201 match self.kind {
1202 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1203 _ => None,
1204 }
1205 }
1206}
1207
1208#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
1210pub(crate) struct Generics {
1211 pub(crate) params: ThinVec<GenericParamDef>,
1212 pub(crate) where_predicates: ThinVec<WherePredicate>,
1213}
1214
1215impl Generics {
1216 pub(crate) fn is_empty(&self) -> bool {
1217 self.params.is_empty() && self.where_predicates.is_empty()
1218 }
1219}
1220
1221#[derive(Clone, Debug)]
1222pub(crate) struct Function {
1223 pub(crate) decl: FnDecl,
1224 pub(crate) generics: Generics,
1225}
1226
1227#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1228pub(crate) struct FnDecl {
1229 pub(crate) inputs: Vec<Parameter>,
1230 pub(crate) output: Type,
1231 pub(crate) c_variadic: bool,
1232}
1233
1234impl FnDecl {
1235 pub(crate) fn receiver_type(&self) -> Option<&Type> {
1236 self.inputs.first().and_then(|v| v.to_receiver())
1237 }
1238}
1239
1240#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1242pub(crate) struct Parameter {
1243 pub(crate) name: Option<Symbol>,
1244 pub(crate) type_: Type,
1245 pub(crate) is_const: bool,
1248}
1249
1250impl Parameter {
1251 pub(crate) fn to_receiver(&self) -> Option<&Type> {
1252 if self.name == Some(kw::SelfLower) { Some(&self.type_) } else { None }
1253 }
1254}
1255
1256#[derive(Clone, Debug)]
1257pub(crate) struct Trait {
1258 pub(crate) def_id: DefId,
1259 pub(crate) items: Vec<Item>,
1260 pub(crate) generics: Generics,
1261 pub(crate) bounds: Vec<GenericBound>,
1262}
1263
1264impl Trait {
1265 pub(crate) fn is_auto(&self, tcx: TyCtxt<'_>) -> bool {
1266 tcx.trait_is_auto(self.def_id)
1267 }
1268 pub(crate) fn is_notable_trait(&self, tcx: TyCtxt<'_>) -> bool {
1269 tcx.is_doc_notable_trait(self.def_id)
1270 }
1271 pub(crate) fn safety(&self, tcx: TyCtxt<'_>) -> hir::Safety {
1272 tcx.trait_def(self.def_id).safety
1273 }
1274 pub(crate) fn is_dyn_compatible(&self, tcx: TyCtxt<'_>) -> bool {
1275 tcx.is_dyn_compatible(self.def_id)
1276 }
1277 pub(crate) fn is_deprecated(&self, tcx: TyCtxt<'_>) -> bool {
1278 tcx.lookup_deprecation(self.def_id).is_some_and(|deprecation| deprecation.is_in_effect())
1279 }
1280}
1281
1282#[derive(Clone, Debug)]
1283pub(crate) struct TraitAlias {
1284 pub(crate) generics: Generics,
1285 pub(crate) bounds: Vec<GenericBound>,
1286}
1287
1288#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1290pub(crate) struct PolyTrait {
1291 pub(crate) trait_: Path,
1292 pub(crate) generic_params: Vec<GenericParamDef>,
1293}
1294
1295#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1297pub(crate) enum Type {
1298 Path {
1303 path: Path,
1304 },
1305 DynTrait(Vec<PolyTrait>, Option<Lifetime>),
1307 Generic(Symbol),
1309 SelfTy,
1311 Primitive(PrimitiveType),
1313 BareFunction(Box<BareFunctionDecl>),
1315 Tuple(Vec<Type>),
1317 Slice(Box<Type>),
1319 Array(Box<Type>, Box<str>),
1323 Pat(Box<Type>, Box<str>),
1324 RawPointer(Mutability, Box<Type>),
1326 BorrowedRef {
1328 lifetime: Option<Lifetime>,
1329 mutability: Mutability,
1330 type_: Box<Type>,
1331 },
1332
1333 QPath(Box<QPathData>),
1335
1336 Infer,
1338
1339 ImplTrait(Vec<GenericBound>),
1341
1342 UnsafeBinder(Box<UnsafeBinderTy>),
1343}
1344
1345impl Type {
1346 pub(crate) fn without_borrowed_ref(&self) -> &Type {
1348 let mut result = self;
1349 while let Type::BorrowedRef { type_, .. } = result {
1350 result = type_;
1351 }
1352 result
1353 }
1354
1355 pub(crate) fn is_borrowed_ref(&self) -> bool {
1356 matches!(self, Type::BorrowedRef { .. })
1357 }
1358
1359 fn is_type_alias(&self) -> bool {
1360 matches!(self, Type::Path { path: Path { res: Res::Def(DefKind::TyAlias, _), .. } })
1361 }
1362
1363 pub(crate) fn is_doc_subtype_of(&self, other: &Self, cache: &Cache) -> bool {
1384 let (self_cleared, other_cleared) = if !self.is_borrowed_ref() || !other.is_borrowed_ref() {
1387 (self.without_borrowed_ref(), other.without_borrowed_ref())
1388 } else {
1389 (self, other)
1390 };
1391
1392 if self_cleared.is_type_alias() || other_cleared.is_type_alias() {
1398 return true;
1399 }
1400
1401 match (self_cleared, other_cleared) {
1402 (Type::Tuple(a), Type::Tuple(b)) => {
1404 a.iter().eq_by(b, |a, b| a.is_doc_subtype_of(b, cache))
1405 }
1406 (Type::Slice(a), Type::Slice(b)) => a.is_doc_subtype_of(b, cache),
1407 (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_doc_subtype_of(b, cache),
1408 (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
1409 mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache)
1410 }
1411 (
1412 Type::BorrowedRef { mutability, type_, .. },
1413 Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
1414 ) => mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache),
1415 (Type::Infer, _) | (_, Type::Infer) => true,
1417 (_, Type::Generic(_)) => true,
1420 (Type::Generic(_), _) => false,
1421 (Type::SelfTy, Type::SelfTy) => true,
1423 (Type::Path { path: a }, Type::Path { path: b }) => {
1425 a.def_id() == b.def_id()
1426 && a.generics()
1427 .zip(b.generics())
1428 .map(|(ag, bg)| ag.zip(bg).all(|(at, bt)| at.is_doc_subtype_of(bt, cache)))
1429 .unwrap_or(true)
1430 }
1431 (a, b) => a
1433 .def_id(cache)
1434 .and_then(|a| Some((a, b.def_id(cache)?)))
1435 .map(|(a, b)| a == b)
1436 .unwrap_or(false),
1437 }
1438 }
1439
1440 pub(crate) fn primitive_type(&self) -> Option<PrimitiveType> {
1441 match *self {
1442 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1443 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1444 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1445 Tuple(ref tys) => {
1446 if tys.is_empty() {
1447 Some(PrimitiveType::Unit)
1448 } else {
1449 Some(PrimitiveType::Tuple)
1450 }
1451 }
1452 RawPointer(..) => Some(PrimitiveType::RawPointer),
1453 BareFunction(..) => Some(PrimitiveType::Fn),
1454 _ => None,
1455 }
1456 }
1457
1458 pub(crate) fn sugared_async_return_type(self) -> Type {
1468 if let Type::ImplTrait(mut v) = self
1469 && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = v.pop()
1470 && let Some(segment) = trait_.segments.pop()
1471 && let GenericArgs::AngleBracketed { mut constraints, .. } = segment.args
1472 && let Some(constraint) = constraints.pop()
1473 && let AssocItemConstraintKind::Equality { term } = constraint.kind
1474 && let Term::Type(ty) = term
1475 {
1476 ty
1477 } else {
1478 panic!("unexpected async fn return type")
1479 }
1480 }
1481
1482 pub(crate) fn is_assoc_ty(&self) -> bool {
1484 match self {
1485 Type::Path { path, .. } => path.is_assoc_ty(),
1486 _ => false,
1487 }
1488 }
1489
1490 pub(crate) fn is_self_type(&self) -> bool {
1491 matches!(*self, Type::SelfTy)
1492 }
1493
1494 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
1495 match self {
1496 Type::Path { path, .. } => path.generic_args(),
1497 _ => None,
1498 }
1499 }
1500
1501 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
1502 match self {
1503 Type::Path { path, .. } => path.generics(),
1504 _ => None,
1505 }
1506 }
1507
1508 pub(crate) fn is_full_generic(&self) -> bool {
1509 matches!(self, Type::Generic(_))
1510 }
1511
1512 pub(crate) fn is_unit(&self) -> bool {
1513 matches!(self, Type::Tuple(v) if v.is_empty())
1514 }
1515
1516 pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
1520 let t: PrimitiveType = match self {
1521 Type::Path { path } => return Some(path.def_id()),
1522 DynTrait(bounds, _) => return bounds.first().map(|b| b.trait_.def_id()),
1523 Primitive(p) => return cache.primitive_locations.get(p).cloned(),
1524 BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
1525 BorrowedRef { type_, .. } => return type_.def_id(cache),
1526 Tuple(tys) => {
1527 if tys.is_empty() {
1528 PrimitiveType::Unit
1529 } else {
1530 PrimitiveType::Tuple
1531 }
1532 }
1533 BareFunction(..) => PrimitiveType::Fn,
1534 Slice(..) => PrimitiveType::Slice,
1535 Array(..) => PrimitiveType::Array,
1536 Type::Pat(..) => PrimitiveType::Pat,
1537 RawPointer(..) => PrimitiveType::RawPointer,
1538 QPath(box QPathData { self_type, .. }) => return self_type.def_id(cache),
1539 Generic(_) | SelfTy | Infer | ImplTrait(_) | UnsafeBinder(_) => return None,
1540 };
1541 Primitive(t).def_id(cache)
1542 }
1543}
1544
1545#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1546pub(crate) struct QPathData {
1547 pub assoc: PathSegment,
1548 pub self_type: Type,
1549 pub should_fully_qualify: bool,
1551 pub trait_: Option<Path>,
1552}
1553
1554#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1561pub(crate) enum PrimitiveType {
1562 Isize,
1563 I8,
1564 I16,
1565 I32,
1566 I64,
1567 I128,
1568 Usize,
1569 U8,
1570 U16,
1571 U32,
1572 U64,
1573 U128,
1574 F16,
1575 F32,
1576 F64,
1577 F128,
1578 Char,
1579 Bool,
1580 Str,
1581 Slice,
1582 Array,
1583 Pat,
1584 Tuple,
1585 Unit,
1586 RawPointer,
1587 Reference,
1588 Fn,
1589 Never,
1590}
1591
1592type SimplifiedTypes = FxIndexMap<PrimitiveType, ArrayVec<SimplifiedType, 3>>;
1593impl PrimitiveType {
1594 pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1595 use ast::{FloatTy, IntTy, UintTy};
1596 match prim {
1597 hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1598 hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1599 hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1600 hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1601 hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1602 hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1603 hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1604 hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1605 hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1606 hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1607 hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1608 hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1609 hir::PrimTy::Float(FloatTy::F16) => PrimitiveType::F16,
1610 hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1611 hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1612 hir::PrimTy::Float(FloatTy::F128) => PrimitiveType::F128,
1613 hir::PrimTy::Str => PrimitiveType::Str,
1614 hir::PrimTy::Bool => PrimitiveType::Bool,
1615 hir::PrimTy::Char => PrimitiveType::Char,
1616 }
1617 }
1618
1619 pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1620 match s {
1621 sym::isize => Some(PrimitiveType::Isize),
1622 sym::i8 => Some(PrimitiveType::I8),
1623 sym::i16 => Some(PrimitiveType::I16),
1624 sym::i32 => Some(PrimitiveType::I32),
1625 sym::i64 => Some(PrimitiveType::I64),
1626 sym::i128 => Some(PrimitiveType::I128),
1627 sym::usize => Some(PrimitiveType::Usize),
1628 sym::u8 => Some(PrimitiveType::U8),
1629 sym::u16 => Some(PrimitiveType::U16),
1630 sym::u32 => Some(PrimitiveType::U32),
1631 sym::u64 => Some(PrimitiveType::U64),
1632 sym::u128 => Some(PrimitiveType::U128),
1633 sym::bool => Some(PrimitiveType::Bool),
1634 sym::char => Some(PrimitiveType::Char),
1635 sym::str => Some(PrimitiveType::Str),
1636 sym::f16 => Some(PrimitiveType::F16),
1637 sym::f32 => Some(PrimitiveType::F32),
1638 sym::f64 => Some(PrimitiveType::F64),
1639 sym::f128 => Some(PrimitiveType::F128),
1640 sym::array => Some(PrimitiveType::Array),
1641 sym::slice => Some(PrimitiveType::Slice),
1642 sym::tuple => Some(PrimitiveType::Tuple),
1643 sym::unit => Some(PrimitiveType::Unit),
1644 sym::pointer => Some(PrimitiveType::RawPointer),
1645 sym::reference => Some(PrimitiveType::Reference),
1646 kw::Fn => Some(PrimitiveType::Fn),
1647 sym::never => Some(PrimitiveType::Never),
1648 _ => None,
1649 }
1650 }
1651
1652 pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
1653 use PrimitiveType::*;
1654 use ty::{FloatTy, IntTy, UintTy};
1655 static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
1656
1657 let single = |x| iter::once(x).collect();
1658 CELL.get_or_init(move || {
1659 map! {
1660 Isize => single(SimplifiedType::Int(IntTy::Isize)),
1661 I8 => single(SimplifiedType::Int(IntTy::I8)),
1662 I16 => single(SimplifiedType::Int(IntTy::I16)),
1663 I32 => single(SimplifiedType::Int(IntTy::I32)),
1664 I64 => single(SimplifiedType::Int(IntTy::I64)),
1665 I128 => single(SimplifiedType::Int(IntTy::I128)),
1666 Usize => single(SimplifiedType::Uint(UintTy::Usize)),
1667 U8 => single(SimplifiedType::Uint(UintTy::U8)),
1668 U16 => single(SimplifiedType::Uint(UintTy::U16)),
1669 U32 => single(SimplifiedType::Uint(UintTy::U32)),
1670 U64 => single(SimplifiedType::Uint(UintTy::U64)),
1671 U128 => single(SimplifiedType::Uint(UintTy::U128)),
1672 F16 => single(SimplifiedType::Float(FloatTy::F16)),
1673 F32 => single(SimplifiedType::Float(FloatTy::F32)),
1674 F64 => single(SimplifiedType::Float(FloatTy::F64)),
1675 F128 => single(SimplifiedType::Float(FloatTy::F128)),
1676 Str => single(SimplifiedType::Str),
1677 Bool => single(SimplifiedType::Bool),
1678 Char => single(SimplifiedType::Char),
1679 Array => single(SimplifiedType::Array),
1680 Slice => single(SimplifiedType::Slice),
1681 Tuple => [SimplifiedType::Tuple(1), SimplifiedType::Tuple(2), SimplifiedType::Tuple(3)].into(),
1687 Unit => single(SimplifiedType::Tuple(0)),
1688 RawPointer => [SimplifiedType::Ptr(Mutability::Not), SimplifiedType::Ptr(Mutability::Mut)].into_iter().collect(),
1689 Reference => [SimplifiedType::Ref(Mutability::Not), SimplifiedType::Ref(Mutability::Mut)].into_iter().collect(),
1690 Fn => single(SimplifiedType::Function(1)),
1693 Never => single(SimplifiedType::Never),
1694 }
1695 })
1696 }
1697
1698 pub(crate) fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = DefId> + 'tcx {
1699 Self::simplified_types()
1700 .get(self)
1701 .into_iter()
1702 .flatten()
1703 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1704 .copied()
1705 }
1706
1707 pub(crate) fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> {
1708 Self::simplified_types()
1709 .values()
1710 .flatten()
1711 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1712 .copied()
1713 }
1714
1715 pub(crate) fn as_sym(&self) -> Symbol {
1716 use PrimitiveType::*;
1717 match self {
1718 Isize => sym::isize,
1719 I8 => sym::i8,
1720 I16 => sym::i16,
1721 I32 => sym::i32,
1722 I64 => sym::i64,
1723 I128 => sym::i128,
1724 Usize => sym::usize,
1725 U8 => sym::u8,
1726 U16 => sym::u16,
1727 U32 => sym::u32,
1728 U64 => sym::u64,
1729 U128 => sym::u128,
1730 F16 => sym::f16,
1731 F32 => sym::f32,
1732 F64 => sym::f64,
1733 F128 => sym::f128,
1734 Str => sym::str,
1735 Bool => sym::bool,
1736 Char => sym::char,
1737 Array => sym::array,
1738 Pat => sym::pat,
1739 Slice => sym::slice,
1740 Tuple => sym::tuple,
1741 Unit => sym::unit,
1742 RawPointer => sym::pointer,
1743 Reference => sym::reference,
1744 Fn => kw::Fn,
1745 Never => sym::never,
1746 }
1747 }
1748
1749 pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxIndexMap<PrimitiveType, DefId> {
1761 static PRIMITIVE_LOCATIONS: OnceCell<FxIndexMap<PrimitiveType, DefId>> = OnceCell::new();
1762 PRIMITIVE_LOCATIONS.get_or_init(|| {
1763 let mut primitive_locations = FxIndexMap::default();
1764 for &crate_num in tcx.crates(()) {
1767 let e = ExternalCrate { crate_num };
1768 let crate_name = e.name(tcx);
1769 debug!(?crate_num, ?crate_name);
1770 for (def_id, prim) in e.primitives(tcx) {
1771 if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1773 continue;
1774 }
1775 primitive_locations.insert(prim, def_id);
1776 }
1777 }
1778 let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1779 for (def_id, prim) in local_primitives {
1780 primitive_locations.insert(prim, def_id);
1781 }
1782 primitive_locations
1783 })
1784 }
1785}
1786
1787impl From<ty::IntTy> for PrimitiveType {
1788 fn from(int_ty: ty::IntTy) -> PrimitiveType {
1789 match int_ty {
1790 ty::IntTy::Isize => PrimitiveType::Isize,
1791 ty::IntTy::I8 => PrimitiveType::I8,
1792 ty::IntTy::I16 => PrimitiveType::I16,
1793 ty::IntTy::I32 => PrimitiveType::I32,
1794 ty::IntTy::I64 => PrimitiveType::I64,
1795 ty::IntTy::I128 => PrimitiveType::I128,
1796 }
1797 }
1798}
1799
1800impl From<ty::UintTy> for PrimitiveType {
1801 fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1802 match uint_ty {
1803 ty::UintTy::Usize => PrimitiveType::Usize,
1804 ty::UintTy::U8 => PrimitiveType::U8,
1805 ty::UintTy::U16 => PrimitiveType::U16,
1806 ty::UintTy::U32 => PrimitiveType::U32,
1807 ty::UintTy::U64 => PrimitiveType::U64,
1808 ty::UintTy::U128 => PrimitiveType::U128,
1809 }
1810 }
1811}
1812
1813impl From<ty::FloatTy> for PrimitiveType {
1814 fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1815 match float_ty {
1816 ty::FloatTy::F16 => PrimitiveType::F16,
1817 ty::FloatTy::F32 => PrimitiveType::F32,
1818 ty::FloatTy::F64 => PrimitiveType::F64,
1819 ty::FloatTy::F128 => PrimitiveType::F128,
1820 }
1821 }
1822}
1823
1824impl From<hir::PrimTy> for PrimitiveType {
1825 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1826 match prim_ty {
1827 hir::PrimTy::Int(int_ty) => int_ty.into(),
1828 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1829 hir::PrimTy::Float(float_ty) => float_ty.into(),
1830 hir::PrimTy::Str => PrimitiveType::Str,
1831 hir::PrimTy::Bool => PrimitiveType::Bool,
1832 hir::PrimTy::Char => PrimitiveType::Char,
1833 }
1834 }
1835}
1836
1837#[derive(Clone, Debug)]
1838pub(crate) struct Struct {
1839 pub(crate) ctor_kind: Option<CtorKind>,
1840 pub(crate) generics: Generics,
1841 pub(crate) fields: ThinVec<Item>,
1842}
1843
1844impl Struct {
1845 pub(crate) fn has_stripped_entries(&self) -> bool {
1846 self.fields.iter().any(|f| f.is_stripped())
1847 }
1848}
1849
1850#[derive(Clone, Debug)]
1851pub(crate) struct Union {
1852 pub(crate) generics: Generics,
1853 pub(crate) fields: Vec<Item>,
1854}
1855
1856impl Union {
1857 pub(crate) fn has_stripped_entries(&self) -> bool {
1858 self.fields.iter().any(|f| f.is_stripped())
1859 }
1860}
1861
1862#[derive(Clone, Debug)]
1866pub(crate) struct VariantStruct {
1867 pub(crate) fields: ThinVec<Item>,
1868}
1869
1870impl VariantStruct {
1871 pub(crate) fn has_stripped_entries(&self) -> bool {
1872 self.fields.iter().any(|f| f.is_stripped())
1873 }
1874}
1875
1876#[derive(Clone, Debug)]
1877pub(crate) struct Enum {
1878 pub(crate) variants: IndexVec<VariantIdx, Item>,
1879 pub(crate) generics: Generics,
1880}
1881
1882impl Enum {
1883 pub(crate) fn has_stripped_entries(&self) -> bool {
1884 self.variants.iter().any(|f| f.is_stripped())
1885 }
1886
1887 pub(crate) fn non_stripped_variants(&self) -> impl Iterator<Item = &Item> {
1888 self.variants.iter().filter(|v| !v.is_stripped())
1889 }
1890}
1891
1892#[derive(Clone, Debug)]
1893pub(crate) struct Variant {
1894 pub kind: VariantKind,
1895 pub discriminant: Option<Discriminant>,
1896}
1897
1898#[derive(Clone, Debug)]
1899pub(crate) enum VariantKind {
1900 CLike,
1901 Tuple(ThinVec<Item>),
1902 Struct(VariantStruct),
1903}
1904
1905impl Variant {
1906 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
1907 match &self.kind {
1908 VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()),
1909 VariantKind::CLike | VariantKind::Tuple(_) => None,
1910 }
1911 }
1912}
1913
1914#[derive(Clone, Debug)]
1915pub(crate) struct Discriminant {
1916 pub(super) expr: Option<BodyId>,
1919 pub(super) value: DefId,
1920}
1921
1922impl Discriminant {
1923 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
1926 self.expr
1927 .map(|body| rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body)))
1928 }
1929 pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String {
1930 print_evaluated_const(tcx, self.value, with_underscores, false).unwrap()
1931 }
1932}
1933
1934#[derive(Copy, Clone, Debug)]
1937pub(crate) struct Span(rustc_span::Span);
1938
1939impl Span {
1940 pub(crate) fn new(sp: rustc_span::Span) -> Self {
1945 Self(sp.source_callsite())
1946 }
1947
1948 pub(crate) fn inner(&self) -> rustc_span::Span {
1949 self.0
1950 }
1951
1952 pub(crate) fn filename(&self, sess: &Session) -> FileName {
1953 sess.source_map().span_to_filename(self.0)
1954 }
1955
1956 pub(crate) fn lo(&self, sess: &Session) -> Loc {
1957 sess.source_map().lookup_char_pos(self.0.lo())
1958 }
1959
1960 pub(crate) fn hi(&self, sess: &Session) -> Loc {
1961 sess.source_map().lookup_char_pos(self.0.hi())
1962 }
1963
1964 pub(crate) fn cnum(&self, sess: &Session) -> CrateNum {
1965 self.lo(sess).file.cnum
1967 }
1968}
1969
1970#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1971pub(crate) struct Path {
1972 pub(crate) res: Res,
1973 pub(crate) segments: ThinVec<PathSegment>,
1974}
1975
1976impl Path {
1977 pub(crate) fn def_id(&self) -> DefId {
1978 self.res.def_id()
1979 }
1980
1981 pub(crate) fn last_opt(&self) -> Option<Symbol> {
1982 self.segments.last().map(|s| s.name)
1983 }
1984
1985 pub(crate) fn last(&self) -> Symbol {
1986 self.last_opt().expect("segments were empty")
1987 }
1988
1989 pub(crate) fn whole_name(&self) -> String {
1990 self.segments
1991 .iter()
1992 .map(|s| if s.name == kw::PathRoot { "" } else { s.name.as_str() })
1993 .intersperse("::")
1994 .collect()
1995 }
1996
1997 pub(crate) fn is_assoc_ty(&self) -> bool {
1999 match self.res {
2000 Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _)
2001 if self.segments.len() != 1 =>
2002 {
2003 true
2004 }
2005 Res::Def(DefKind::AssocTy, _) => true,
2006 _ => false,
2007 }
2008 }
2009
2010 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
2011 self.segments.last().map(|seg| &seg.args)
2012 }
2013
2014 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
2015 self.segments.last().and_then(|seg| {
2016 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2017 Some(args.iter().filter_map(|arg| match arg {
2018 GenericArg::Type(ty) => Some(ty),
2019 _ => None,
2020 }))
2021 } else {
2022 None
2023 }
2024 })
2025 }
2026}
2027
2028#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2029pub(crate) enum GenericArg {
2030 Lifetime(Lifetime),
2031 Type(Type),
2032 Const(Box<ConstantKind>),
2033 Infer,
2034}
2035
2036impl GenericArg {
2037 pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
2038 if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2039 }
2040
2041 pub(crate) fn as_ty(&self) -> Option<&Type> {
2042 if let Self::Type(ty) = self { Some(ty) } else { None }
2043 }
2044}
2045
2046#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2047pub(crate) enum GenericArgs {
2048 AngleBracketed { args: ThinVec<GenericArg>, constraints: ThinVec<AssocItemConstraint> },
2050 Parenthesized { inputs: ThinVec<Type>, output: Option<Box<Type>> },
2052 ReturnTypeNotation,
2054}
2055
2056impl GenericArgs {
2057 pub(crate) fn is_empty(&self) -> bool {
2058 match self {
2059 GenericArgs::AngleBracketed { args, constraints } => {
2060 args.is_empty() && constraints.is_empty()
2061 }
2062 GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
2063 GenericArgs::ReturnTypeNotation => false,
2064 }
2065 }
2066 pub(crate) fn constraints(&self) -> Box<dyn Iterator<Item = AssocItemConstraint> + '_> {
2067 match self {
2068 GenericArgs::AngleBracketed { constraints, .. } => {
2069 Box::new(constraints.iter().cloned())
2070 }
2071 GenericArgs::Parenthesized { output, .. } => Box::new(
2072 output
2073 .as_ref()
2074 .map(|ty| AssocItemConstraint {
2075 assoc: PathSegment {
2076 name: sym::Output,
2077 args: GenericArgs::AngleBracketed {
2078 args: ThinVec::new(),
2079 constraints: ThinVec::new(),
2080 },
2081 },
2082 kind: AssocItemConstraintKind::Equality {
2083 term: Term::Type((**ty).clone()),
2084 },
2085 })
2086 .into_iter(),
2087 ),
2088 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2089 }
2090 }
2091}
2092
2093impl<'a> IntoIterator for &'a GenericArgs {
2094 type IntoIter = Box<dyn Iterator<Item = GenericArg> + 'a>;
2095 type Item = GenericArg;
2096 fn into_iter(self) -> Self::IntoIter {
2097 match self {
2098 GenericArgs::AngleBracketed { args, .. } => Box::new(args.iter().cloned()),
2099 GenericArgs::Parenthesized { inputs, .. } => {
2100 Box::new(inputs.iter().cloned().map(GenericArg::Type))
2102 }
2103 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2104 }
2105 }
2106}
2107
2108#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2109pub(crate) struct PathSegment {
2110 pub(crate) name: Symbol,
2111 pub(crate) args: GenericArgs,
2112}
2113
2114#[derive(Clone, Debug)]
2115pub(crate) enum TypeAliasInnerType {
2116 Enum { variants: IndexVec<VariantIdx, Item>, is_non_exhaustive: bool },
2117 Union { fields: Vec<Item> },
2118 Struct { ctor_kind: Option<CtorKind>, fields: Vec<Item> },
2119}
2120
2121impl TypeAliasInnerType {
2122 fn has_stripped_entries(&self) -> Option<bool> {
2123 Some(match self {
2124 Self::Enum { variants, .. } => variants.iter().any(|v| v.is_stripped()),
2125 Self::Union { fields } | Self::Struct { fields, .. } => {
2126 fields.iter().any(|f| f.is_stripped())
2127 }
2128 })
2129 }
2130}
2131
2132#[derive(Clone, Debug)]
2133pub(crate) struct TypeAlias {
2134 pub(crate) type_: Type,
2135 pub(crate) generics: Generics,
2136 pub(crate) inner_type: Option<TypeAliasInnerType>,
2139 pub(crate) item_type: Option<Type>,
2146}
2147
2148#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2149pub(crate) struct BareFunctionDecl {
2150 pub(crate) safety: hir::Safety,
2151 pub(crate) generic_params: Vec<GenericParamDef>,
2152 pub(crate) decl: FnDecl,
2153 pub(crate) abi: ExternAbi,
2154}
2155
2156#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2157pub(crate) struct UnsafeBinderTy {
2158 pub(crate) generic_params: Vec<GenericParamDef>,
2159 pub(crate) ty: Type,
2160}
2161
2162#[derive(Clone, Debug)]
2163pub(crate) struct Static {
2164 pub(crate) type_: Box<Type>,
2165 pub(crate) mutability: Mutability,
2166 pub(crate) expr: Option<BodyId>,
2167}
2168
2169#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2170pub(crate) struct Constant {
2171 pub(crate) generics: Generics,
2172 pub(crate) kind: ConstantKind,
2173 pub(crate) type_: Type,
2174}
2175
2176#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2177pub(crate) enum Term {
2178 Type(Type),
2179 Constant(ConstantKind),
2180}
2181
2182impl Term {
2183 pub(crate) fn ty(&self) -> Option<&Type> {
2184 if let Term::Type(ty) = self { Some(ty) } else { None }
2185 }
2186}
2187
2188impl From<Type> for Term {
2189 fn from(ty: Type) -> Self {
2190 Term::Type(ty)
2191 }
2192}
2193
2194#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2195pub(crate) enum ConstantKind {
2196 TyConst { expr: Box<str> },
2202 Path { path: Box<str> },
2205 Anonymous { body: BodyId },
2209 Extern { def_id: DefId },
2211 Local { def_id: DefId, body: BodyId },
2213 Infer,
2215}
2216
2217impl ConstantKind {
2218 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2219 match *self {
2220 ConstantKind::TyConst { ref expr } => expr.to_string(),
2221 ConstantKind::Path { ref path } => path.to_string(),
2222 ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2223 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2224 rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body))
2225 }
2226 ConstantKind::Infer => "_".to_string(),
2227 }
2228 }
2229
2230 pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2231 match *self {
2232 ConstantKind::TyConst { .. }
2233 | ConstantKind::Path { .. }
2234 | ConstantKind::Anonymous { .. }
2235 | ConstantKind::Infer => None,
2236 ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2237 print_evaluated_const(tcx, def_id, true, true)
2238 }
2239 }
2240 }
2241
2242 pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2243 match *self {
2244 ConstantKind::TyConst { .. }
2245 | ConstantKind::Extern { .. }
2246 | ConstantKind::Path { .. }
2247 | ConstantKind::Infer => false,
2248 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2249 is_literal_expr(tcx, body.hir_id)
2250 }
2251 }
2252 }
2253}
2254
2255#[derive(Clone, Debug)]
2256pub(crate) struct Impl {
2257 pub(crate) safety: hir::Safety,
2258 pub(crate) generics: Generics,
2259 pub(crate) trait_: Option<Path>,
2260 pub(crate) for_: Type,
2261 pub(crate) items: Vec<Item>,
2262 pub(crate) polarity: ty::ImplPolarity,
2263 pub(crate) kind: ImplKind,
2264 pub(crate) is_deprecated: bool,
2265}
2266
2267impl Impl {
2268 pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxIndexSet<Symbol> {
2269 self.trait_
2270 .as_ref()
2271 .map(|t| t.def_id())
2272 .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name()).collect())
2273 .unwrap_or_default()
2274 }
2275
2276 pub(crate) fn is_negative_trait_impl(&self) -> bool {
2277 matches!(self.polarity, ty::ImplPolarity::Negative)
2278 }
2279}
2280
2281#[derive(Clone, Debug)]
2282pub(crate) enum ImplKind {
2283 Normal,
2284 Auto,
2285 FakeVariadic,
2286 Blanket(Box<Type>),
2287}
2288
2289impl ImplKind {
2290 pub(crate) fn is_auto(&self) -> bool {
2291 matches!(self, ImplKind::Auto)
2292 }
2293
2294 pub(crate) fn is_blanket(&self) -> bool {
2295 matches!(self, ImplKind::Blanket(_))
2296 }
2297
2298 pub(crate) fn is_fake_variadic(&self) -> bool {
2299 matches!(self, ImplKind::FakeVariadic)
2300 }
2301
2302 pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
2303 match self {
2304 ImplKind::Blanket(ty) => Some(ty),
2305 _ => None,
2306 }
2307 }
2308}
2309
2310#[derive(Clone, Debug)]
2311pub(crate) struct Import {
2312 pub(crate) kind: ImportKind,
2313 pub(crate) source: ImportSource,
2315 pub(crate) should_be_displayed: bool,
2316}
2317
2318impl Import {
2319 pub(crate) fn new_simple(
2320 name: Symbol,
2321 source: ImportSource,
2322 should_be_displayed: bool,
2323 ) -> Self {
2324 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2325 }
2326
2327 pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2328 Self { kind: ImportKind::Glob, source, should_be_displayed }
2329 }
2330
2331 pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool {
2332 self.source.did.is_some_and(|did| tcx.is_doc_hidden(did))
2333 }
2334}
2335
2336#[derive(Clone, Debug)]
2337pub(crate) enum ImportKind {
2338 Simple(Symbol),
2340 Glob,
2342}
2343
2344#[derive(Clone, Debug)]
2345pub(crate) struct ImportSource {
2346 pub(crate) path: Path,
2347 pub(crate) did: Option<DefId>,
2348}
2349
2350#[derive(Clone, Debug)]
2351pub(crate) struct Macro {
2352 pub(crate) source: String,
2353 pub(crate) macro_rules: bool,
2355}
2356
2357#[derive(Clone, Debug)]
2358pub(crate) struct ProcMacro {
2359 pub(crate) kind: MacroKind,
2360 pub(crate) helpers: Vec<Symbol>,
2361}
2362
2363#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2374pub(crate) struct AssocItemConstraint {
2375 pub(crate) assoc: PathSegment,
2376 pub(crate) kind: AssocItemConstraintKind,
2377}
2378
2379#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2381pub(crate) enum AssocItemConstraintKind {
2382 Equality { term: Term },
2383 Bound { bounds: Vec<GenericBound> },
2384}
2385
2386#[cfg(target_pointer_width = "64")]
2388mod size_asserts {
2389 use rustc_data_structures::static_assert_size;
2390
2391 use super::*;
2392 static_assert_size!(Crate, 16); static_assert_size!(DocFragment, 48);
2395 static_assert_size!(GenericArg, 32);
2396 static_assert_size!(GenericArgs, 24);
2397 static_assert_size!(GenericParamDef, 40);
2398 static_assert_size!(Generics, 16);
2399 static_assert_size!(Item, 8);
2400 static_assert_size!(ItemInner, 144);
2401 static_assert_size!(ItemKind, 48);
2402 static_assert_size!(PathSegment, 32);
2403 static_assert_size!(Type, 32);
2404 }