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 is_unstable(&self) -> bool {
435 self.stability.is_some_and(|x| x.is_unstable())
436 }
437
438 pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
439 self.item_id.as_def_id().map(|did| inner_docs(tcx.get_all_attrs(did))).unwrap_or(false)
440 }
441
442 pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option<Span> {
443 let kind = match &self.kind {
444 ItemKind::StrippedItem(k) => k,
445 _ => &self.kind,
446 };
447 match kind {
448 ItemKind::ModuleItem(Module { span, .. }) => Some(*span),
449 ItemKind::ImplItem(box Impl { kind: ImplKind::Auto, .. }) => None,
450 ItemKind::ImplItem(box Impl { kind: ImplKind::Blanket(_), .. }) => {
451 if let ItemId::Blanket { impl_id, .. } = self.item_id {
452 Some(rustc_span(impl_id, tcx))
453 } else {
454 panic!("blanket impl item has non-blanket ID")
455 }
456 }
457 _ => self.def_id().map(|did| rustc_span(did, tcx)),
458 }
459 }
460
461 pub(crate) fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
462 let deprecation_notes = self
463 .attrs
464 .other_attrs
465 .iter()
466 .filter_map(|attr| attr.deprecation_note().map(|note| note.span));
467
468 span_of_fragments(&self.attrs.doc_strings)
469 .into_iter()
470 .chain(deprecation_notes)
471 .reduce(|a, b| a.to(b))
472 .unwrap_or_else(|| self.span(tcx).map_or(DUMMY_SP, |span| span.inner()))
473 }
474
475 pub(crate) fn doc_value(&self) -> String {
477 self.attrs.doc_value()
478 }
479
480 pub(crate) fn opt_doc_value(&self) -> Option<String> {
484 self.attrs.opt_doc_value()
485 }
486
487 pub(crate) fn from_def_id_and_parts(
488 def_id: DefId,
489 name: Option<Symbol>,
490 kind: ItemKind,
491 cx: &mut DocContext<'_>,
492 ) -> Item {
493 let hir_attrs = cx.tcx.get_all_attrs(def_id);
494
495 Self::from_def_id_and_attrs_and_parts(
496 def_id,
497 name,
498 kind,
499 Attributes::from_hir(hir_attrs),
500 None,
501 )
502 }
503
504 pub(crate) fn from_def_id_and_attrs_and_parts(
505 def_id: DefId,
506 name: Option<Symbol>,
507 kind: ItemKind,
508 attrs: Attributes,
509 cfg: Option<Arc<Cfg>>,
510 ) -> Item {
511 trace!("name={name:?}, def_id={def_id:?} cfg={cfg:?}");
512
513 Item {
514 inner: Box::new(ItemInner {
515 item_id: def_id.into(),
516 kind,
517 attrs,
518 stability: None,
519 name,
520 cfg,
521 inline_stmt_id: None,
522 }),
523 }
524 }
525
526 pub(crate) fn item_or_reexport_id(&self) -> ItemId {
532 self.attrs
534 .doc_strings
535 .first()
536 .map(|x| x.item_id)
537 .flatten()
538 .map(ItemId::from)
539 .unwrap_or(self.item_id)
540 }
541
542 pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
543 use crate::html::format::{href, link_tooltip};
544
545 let Some(links) = cx.cache().intra_doc_links.get(&self.item_or_reexport_id()) else {
546 return vec![];
547 };
548 links
549 .iter()
550 .filter_map(|ItemLink { link: s, link_text, page_id: id, fragment }| {
551 debug!(?id);
552 if let Ok(HrefInfo { mut url, .. }) = href(*id, cx) {
553 debug!(?url);
554 match fragment {
555 Some(UrlFragment::Item(def_id)) => {
556 write!(url, "{}", crate::html::format::fragment(*def_id, cx.tcx()))
557 .unwrap();
558 }
559 Some(UrlFragment::UserWritten(raw)) => {
560 url.push('#');
561 url.push_str(raw);
562 }
563 None => {}
564 }
565 Some(RenderedLink {
566 original_text: s.clone(),
567 new_text: link_text.clone(),
568 tooltip: link_tooltip(*id, fragment, cx).to_string(),
569 href: url,
570 })
571 } else {
572 None
573 }
574 })
575 .collect()
576 }
577
578 pub(crate) fn link_names(&self, cache: &Cache) -> Vec<RenderedLink> {
584 let Some(links) = cache.intra_doc_links.get(&self.item_id) else {
585 return vec![];
586 };
587 links
588 .iter()
589 .map(|ItemLink { link: s, link_text, .. }| RenderedLink {
590 original_text: s.clone(),
591 new_text: link_text.clone(),
592 href: String::new(),
593 tooltip: String::new(),
594 })
595 .collect()
596 }
597
598 pub(crate) fn is_crate(&self) -> bool {
599 self.is_mod() && self.def_id().is_some_and(|did| did.is_crate_root())
600 }
601 pub(crate) fn is_mod(&self) -> bool {
602 self.type_() == ItemType::Module
603 }
604 pub(crate) fn is_struct(&self) -> bool {
605 self.type_() == ItemType::Struct
606 }
607 pub(crate) fn is_enum(&self) -> bool {
608 self.type_() == ItemType::Enum
609 }
610 pub(crate) fn is_variant(&self) -> bool {
611 self.type_() == ItemType::Variant
612 }
613 pub(crate) fn is_associated_type(&self) -> bool {
614 matches!(self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..)))
615 }
616 pub(crate) fn is_required_associated_type(&self) -> bool {
617 matches!(self.kind, RequiredAssocTypeItem(..) | StrippedItem(box RequiredAssocTypeItem(..)))
618 }
619 pub(crate) fn is_associated_const(&self) -> bool {
620 matches!(self.kind, ProvidedAssocConstItem(..) | ImplAssocConstItem(..) | StrippedItem(box (ProvidedAssocConstItem(..) | ImplAssocConstItem(..))))
621 }
622 pub(crate) fn is_required_associated_const(&self) -> bool {
623 matches!(self.kind, RequiredAssocConstItem(..) | StrippedItem(box RequiredAssocConstItem(..)))
624 }
625 pub(crate) fn is_method(&self) -> bool {
626 self.type_() == ItemType::Method
627 }
628 pub(crate) fn is_ty_method(&self) -> bool {
629 self.type_() == ItemType::TyMethod
630 }
631 pub(crate) fn is_primitive(&self) -> bool {
632 self.type_() == ItemType::Primitive
633 }
634 pub(crate) fn is_union(&self) -> bool {
635 self.type_() == ItemType::Union
636 }
637 pub(crate) fn is_import(&self) -> bool {
638 self.type_() == ItemType::Import
639 }
640 pub(crate) fn is_extern_crate(&self) -> bool {
641 self.type_() == ItemType::ExternCrate
642 }
643 pub(crate) fn is_keyword(&self) -> bool {
644 self.type_() == ItemType::Keyword
645 }
646 pub(crate) fn is_attribute(&self) -> bool {
647 self.type_() == ItemType::Attribute
648 }
649 pub(crate) fn is_fake_item(&self) -> bool {
658 matches!(self.type_(), ItemType::Primitive | ItemType::Keyword | ItemType::Attribute)
659 }
660 pub(crate) fn is_stripped(&self) -> bool {
661 match self.kind {
662 StrippedItem(..) => true,
663 ImportItem(ref i) => !i.should_be_displayed,
664 _ => false,
665 }
666 }
667 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
668 match self.kind {
669 StructItem(ref struct_) => Some(struct_.has_stripped_entries()),
670 UnionItem(ref union_) => Some(union_.has_stripped_entries()),
671 EnumItem(ref enum_) => Some(enum_.has_stripped_entries()),
672 VariantItem(ref v) => v.has_stripped_entries(),
673 TypeAliasItem(ref type_alias) => {
674 type_alias.inner_type.as_ref().and_then(|t| t.has_stripped_entries())
675 }
676 _ => None,
677 }
678 }
679
680 pub(crate) fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
681 self.stability(tcx).as_ref().and_then(|s| {
682 let mut classes = Vec::with_capacity(2);
683
684 if s.is_unstable() {
685 classes.push("unstable");
686 }
687
688 if self.deprecation(tcx).is_some() {
690 classes.push("deprecated");
691 }
692
693 if !classes.is_empty() { Some(classes.join(" ")) } else { None }
694 })
695 }
696
697 pub(crate) fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<StableSince> {
698 self.stability(tcx).and_then(|stability| stability.stable_since())
699 }
700
701 pub(crate) fn is_non_exhaustive(&self) -> bool {
702 find_attr!(&self.attrs.other_attrs, AttributeKind::NonExhaustive(..))
703 }
704
705 pub(crate) fn type_(&self) -> ItemType {
707 ItemType::from(self)
708 }
709
710 pub(crate) fn is_default(&self) -> bool {
711 match self.kind {
712 ItemKind::MethodItem(_, Some(defaultness)) => {
713 defaultness.has_value() && !defaultness.is_final()
714 }
715 _ => false,
716 }
717 }
718
719 pub(crate) fn fn_header(&self, tcx: TyCtxt<'_>) -> Option<hir::FnHeader> {
721 fn build_fn_header(
722 def_id: DefId,
723 tcx: TyCtxt<'_>,
724 asyncness: ty::Asyncness,
725 ) -> hir::FnHeader {
726 let sig = tcx.fn_sig(def_id).skip_binder();
727 let constness = if tcx.is_const_fn(def_id) {
728 if let Some(assoc) = tcx.opt_associated_item(def_id)
732 && let ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) =
733 assoc.container
734 {
735 hir::Constness::NotConst
736 } else {
737 hir::Constness::Const
738 }
739 } else {
740 hir::Constness::NotConst
741 };
742 let asyncness = match asyncness {
743 ty::Asyncness::Yes => hir::IsAsync::Async(DUMMY_SP),
744 ty::Asyncness::No => hir::IsAsync::NotAsync,
745 };
746 hir::FnHeader {
747 safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
748 hir::HeaderSafety::SafeTargetFeatures
749 } else {
750 sig.safety().into()
751 },
752 abi: sig.abi(),
753 constness,
754 asyncness,
755 }
756 }
757 let header = match self.kind {
758 ItemKind::ForeignFunctionItem(_, safety) => {
759 let def_id = self.def_id().unwrap();
760 let abi = tcx.fn_sig(def_id).skip_binder().abi();
761 hir::FnHeader {
762 safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
763 hir::HeaderSafety::SafeTargetFeatures
764 } else {
765 safety.into()
766 },
767 abi,
768 constness: if tcx.is_const_fn(def_id) {
769 hir::Constness::Const
770 } else {
771 hir::Constness::NotConst
772 },
773 asyncness: hir::IsAsync::NotAsync,
774 }
775 }
776 ItemKind::FunctionItem(_)
777 | ItemKind::MethodItem(_, _)
778 | ItemKind::RequiredMethodItem(_) => {
779 let def_id = self.def_id().unwrap();
780 build_fn_header(def_id, tcx, tcx.asyncness(def_id))
781 }
782 _ => return None,
783 };
784 Some(header)
785 }
786
787 pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option<Visibility<DefId>> {
790 let def_id = match self.item_id {
791 ItemId::Auto { .. } | ItemId::Blanket { .. } => return None,
793 ItemId::DefId(def_id) => def_id,
794 };
795
796 match self.kind {
797 ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) | ItemKind::AttributeItem => {
801 return Some(Visibility::Public);
802 }
803 StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => {
805 return None;
806 }
807 VariantItem(..) | ImplItem(..) => return None,
809 RequiredAssocConstItem(..)
811 | ProvidedAssocConstItem(..)
812 | ImplAssocConstItem(..)
813 | AssocTypeItem(..)
814 | RequiredAssocTypeItem(..)
815 | RequiredMethodItem(..)
816 | MethodItem(..) => {
817 match tcx.associated_item(def_id).container {
818 ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) => {
821 return None;
822 }
823 ty::AssocContainer::InherentImpl => {}
824 }
825 }
826 _ => {}
827 }
828 let def_id = match self.inline_stmt_id {
829 Some(inlined) => inlined.to_def_id(),
830 None => def_id,
831 };
832 Some(tcx.visibility(def_id))
833 }
834
835 pub fn is_doc_hidden(&self) -> bool {
836 self.attrs.is_doc_hidden()
837 }
838
839 pub fn def_id(&self) -> Option<DefId> {
840 self.item_id.as_def_id()
841 }
842}
843
844#[derive(Clone, Debug)]
845pub(crate) enum ItemKind {
846 ExternCrateItem {
847 src: Option<Symbol>,
849 },
850 ImportItem(Import),
851 StructItem(Struct),
852 UnionItem(Union),
853 EnumItem(Enum),
854 FunctionItem(Box<Function>),
855 ModuleItem(Module),
856 TypeAliasItem(Box<TypeAlias>),
857 StaticItem(Static),
858 TraitItem(Box<Trait>),
859 TraitAliasItem(TraitAlias),
860 ImplItem(Box<Impl>),
861 RequiredMethodItem(Box<Function>),
863 MethodItem(Box<Function>, Option<hir::Defaultness>),
867 StructFieldItem(Type),
868 VariantItem(Variant),
869 ForeignFunctionItem(Box<Function>, hir::Safety),
871 ForeignStaticItem(Static, hir::Safety),
873 ForeignTypeItem,
875 MacroItem(Macro),
876 ProcMacroItem(ProcMacro),
877 PrimitiveItem(PrimitiveType),
878 RequiredAssocConstItem(Generics, Box<Type>),
880 ConstantItem(Box<Constant>),
881 ProvidedAssocConstItem(Box<Constant>),
883 ImplAssocConstItem(Box<Constant>),
885 RequiredAssocTypeItem(Generics, Vec<GenericBound>),
889 AssocTypeItem(Box<TypeAlias>, Vec<GenericBound>),
891 StrippedItem(Box<ItemKind>),
893 KeywordItem,
896 AttributeItem,
899}
900
901impl ItemKind {
902 pub(crate) fn inner_items(&self) -> impl Iterator<Item = &Item> {
905 match self {
906 StructItem(s) => s.fields.iter(),
907 UnionItem(u) => u.fields.iter(),
908 VariantItem(v) => match &v.kind {
909 VariantKind::CLike => [].iter(),
910 VariantKind::Tuple(t) => t.iter(),
911 VariantKind::Struct(s) => s.fields.iter(),
912 },
913 EnumItem(e) => e.variants.iter(),
914 TraitItem(t) => t.items.iter(),
915 ImplItem(i) => i.items.iter(),
916 ModuleItem(m) => m.items.iter(),
917 ExternCrateItem { .. }
918 | ImportItem(_)
919 | FunctionItem(_)
920 | TypeAliasItem(_)
921 | StaticItem(_)
922 | ConstantItem(_)
923 | TraitAliasItem(_)
924 | RequiredMethodItem(_)
925 | MethodItem(_, _)
926 | StructFieldItem(_)
927 | ForeignFunctionItem(_, _)
928 | ForeignStaticItem(_, _)
929 | ForeignTypeItem
930 | MacroItem(_)
931 | ProcMacroItem(_)
932 | PrimitiveItem(_)
933 | RequiredAssocConstItem(..)
934 | ProvidedAssocConstItem(..)
935 | ImplAssocConstItem(..)
936 | RequiredAssocTypeItem(..)
937 | AssocTypeItem(..)
938 | StrippedItem(_)
939 | KeywordItem
940 | AttributeItem => [].iter(),
941 }
942 }
943}
944
945#[derive(Clone, Debug)]
946pub(crate) struct Module {
947 pub(crate) items: Vec<Item>,
948 pub(crate) span: Span,
949}
950
951#[derive(Clone, Debug, PartialEq, Eq, Hash)]
955pub(crate) struct ItemLink {
956 pub(crate) link: Box<str>,
958 pub(crate) link_text: Box<str>,
963 pub(crate) page_id: DefId,
967 pub(crate) fragment: Option<UrlFragment>,
969}
970
971pub struct RenderedLink {
972 pub(crate) original_text: Box<str>,
976 pub(crate) new_text: Box<str>,
978 pub(crate) href: String,
980 pub(crate) tooltip: String,
982}
983
984#[derive(Clone, Debug, Default)]
987pub(crate) struct Attributes {
988 pub(crate) doc_strings: Vec<DocFragment>,
989 pub(crate) other_attrs: ThinVec<hir::Attribute>,
990}
991
992impl Attributes {
993 pub(crate) fn has_doc_flag<F: Fn(&DocAttribute) -> bool>(&self, callback: F) -> bool {
994 self.other_attrs
995 .iter()
996 .any(|a| matches!(a, Attribute::Parsed(AttributeKind::Doc(d)) if callback(d)))
997 }
998
999 pub(crate) fn is_doc_hidden(&self) -> bool {
1000 find_attr!(&self.other_attrs, AttributeKind::Doc(d) if d.hidden.is_some())
1001 }
1002
1003 pub(crate) fn from_hir(attrs: &[hir::Attribute]) -> Attributes {
1004 Attributes::from_hir_iter(attrs.iter().map(|attr| (attr, None)), false)
1005 }
1006
1007 pub(crate) fn from_hir_with_additional(
1008 attrs: &[hir::Attribute],
1009 (additional_attrs, def_id): (&[hir::Attribute], DefId),
1010 ) -> Attributes {
1011 let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id)));
1013 let attrs2 = attrs.iter().map(|attr| (attr, None));
1014 Attributes::from_hir_iter(attrs1.chain(attrs2), false)
1015 }
1016
1017 pub(crate) fn from_hir_iter<'a>(
1018 attrs: impl Iterator<Item = (&'a hir::Attribute, Option<DefId>)>,
1019 doc_only: bool,
1020 ) -> Attributes {
1021 let (doc_strings, other_attrs) = attrs_to_doc_fragments(attrs, doc_only);
1022 Attributes { doc_strings, other_attrs }
1023 }
1024
1025 pub(crate) fn doc_value(&self) -> String {
1027 self.opt_doc_value().unwrap_or_default()
1028 }
1029
1030 pub(crate) fn opt_doc_value(&self) -> Option<String> {
1034 (!self.doc_strings.is_empty()).then(|| {
1035 let mut res = String::new();
1036 for frag in &self.doc_strings {
1037 add_doc_fragment(&mut res, frag);
1038 }
1039 res.pop();
1040 res
1041 })
1042 }
1043
1044 pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> {
1045 let mut aliases = FxIndexSet::default();
1046
1047 for attr in &self.other_attrs {
1048 if let Attribute::Parsed(AttributeKind::Doc(d)) = attr {
1049 for (alias, _) in &d.aliases {
1050 aliases.insert(*alias);
1051 }
1052 }
1053 }
1054 aliases.into_iter().collect::<Vec<_>>().into()
1055 }
1056}
1057
1058#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1059pub(crate) enum GenericBound {
1060 TraitBound(PolyTrait, hir::TraitBoundModifiers),
1061 Outlives(Lifetime),
1062 Use(Vec<PreciseCapturingArg>),
1064}
1065
1066impl GenericBound {
1067 pub(crate) fn sized(cx: &mut DocContext<'_>) -> GenericBound {
1068 Self::sized_with(cx, hir::TraitBoundModifiers::NONE)
1069 }
1070
1071 pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1072 Self::sized_with(
1073 cx,
1074 hir::TraitBoundModifiers {
1075 polarity: hir::BoundPolarity::Maybe(DUMMY_SP),
1076 constness: hir::BoundConstness::Never,
1077 },
1078 )
1079 }
1080
1081 fn sized_with(cx: &mut DocContext<'_>, modifiers: hir::TraitBoundModifiers) -> GenericBound {
1082 let did = cx.tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
1083 let empty = ty::Binder::dummy(ty::GenericArgs::empty());
1084 let path = clean_middle_path(cx, did, false, ThinVec::new(), empty);
1085 inline::record_extern_fqn(cx, did, ItemType::Trait);
1086 GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifiers)
1087 }
1088
1089 pub(crate) fn is_trait_bound(&self) -> bool {
1090 matches!(self, Self::TraitBound(..))
1091 }
1092
1093 pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1094 self.is_bounded_by_lang_item(cx, LangItem::Sized)
1095 }
1096
1097 pub(crate) fn is_meta_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1098 self.is_bounded_by_lang_item(cx, LangItem::MetaSized)
1099 }
1100
1101 fn is_bounded_by_lang_item(&self, cx: &DocContext<'_>, lang_item: LangItem) -> bool {
1102 if let GenericBound::TraitBound(
1103 PolyTrait { ref trait_, .. },
1104 rustc_hir::TraitBoundModifiers::NONE,
1105 ) = *self
1106 && cx.tcx.is_lang_item(trait_.def_id(), lang_item)
1107 {
1108 return true;
1109 }
1110 false
1111 }
1112
1113 pub(crate) fn get_trait_path(&self) -> Option<Path> {
1114 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1115 Some(trait_.clone())
1116 } else {
1117 None
1118 }
1119 }
1120}
1121
1122#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1123pub(crate) struct Lifetime(pub Symbol);
1124
1125impl Lifetime {
1126 pub(crate) fn statik() -> Lifetime {
1127 Lifetime(kw::StaticLifetime)
1128 }
1129
1130 pub(crate) fn elided() -> Lifetime {
1131 Lifetime(kw::UnderscoreLifetime)
1132 }
1133}
1134
1135#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1136pub(crate) enum PreciseCapturingArg {
1137 Lifetime(Lifetime),
1138 Param(Symbol),
1139}
1140
1141impl PreciseCapturingArg {
1142 pub(crate) fn name(self) -> Symbol {
1143 match self {
1144 PreciseCapturingArg::Lifetime(lt) => lt.0,
1145 PreciseCapturingArg::Param(param) => param,
1146 }
1147 }
1148}
1149
1150#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1151pub(crate) enum WherePredicate {
1152 BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
1153 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1154 EqPredicate { lhs: QPathData, rhs: Term },
1155}
1156
1157impl WherePredicate {
1158 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1159 match self {
1160 WherePredicate::BoundPredicate { bounds, .. } => Some(bounds),
1161 WherePredicate::RegionPredicate { bounds, .. } => Some(bounds),
1162 _ => None,
1163 }
1164 }
1165}
1166
1167#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1168pub(crate) enum GenericParamDefKind {
1169 Lifetime { outlives: ThinVec<Lifetime> },
1170 Type { bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
1171 Const { ty: Box<Type>, default: Option<Box<String>> },
1173}
1174
1175impl GenericParamDefKind {
1176 pub(crate) fn is_type(&self) -> bool {
1177 matches!(self, GenericParamDefKind::Type { .. })
1178 }
1179}
1180
1181#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1182pub(crate) struct GenericParamDef {
1183 pub(crate) name: Symbol,
1184 pub(crate) def_id: DefId,
1185 pub(crate) kind: GenericParamDefKind,
1186}
1187
1188impl GenericParamDef {
1189 pub(crate) fn lifetime(def_id: DefId, name: Symbol) -> Self {
1190 Self { name, def_id, kind: GenericParamDefKind::Lifetime { outlives: ThinVec::new() } }
1191 }
1192
1193 pub(crate) fn is_synthetic_param(&self) -> bool {
1194 match self.kind {
1195 GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
1196 GenericParamDefKind::Type { synthetic, .. } => synthetic,
1197 }
1198 }
1199
1200 pub(crate) fn is_type(&self) -> bool {
1201 self.kind.is_type()
1202 }
1203
1204 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1205 match self.kind {
1206 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1207 _ => None,
1208 }
1209 }
1210}
1211
1212#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
1214pub(crate) struct Generics {
1215 pub(crate) params: ThinVec<GenericParamDef>,
1216 pub(crate) where_predicates: ThinVec<WherePredicate>,
1217}
1218
1219impl Generics {
1220 pub(crate) fn is_empty(&self) -> bool {
1221 self.params.is_empty() && self.where_predicates.is_empty()
1222 }
1223}
1224
1225#[derive(Clone, Debug)]
1226pub(crate) struct Function {
1227 pub(crate) decl: FnDecl,
1228 pub(crate) generics: Generics,
1229}
1230
1231#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1232pub(crate) struct FnDecl {
1233 pub(crate) inputs: Vec<Parameter>,
1234 pub(crate) output: Type,
1235 pub(crate) c_variadic: bool,
1236}
1237
1238impl FnDecl {
1239 pub(crate) fn receiver_type(&self) -> Option<&Type> {
1240 self.inputs.first().and_then(|v| v.to_receiver())
1241 }
1242}
1243
1244#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1246pub(crate) struct Parameter {
1247 pub(crate) name: Option<Symbol>,
1248 pub(crate) type_: Type,
1249 pub(crate) is_const: bool,
1252}
1253
1254impl Parameter {
1255 pub(crate) fn to_receiver(&self) -> Option<&Type> {
1256 if self.name == Some(kw::SelfLower) { Some(&self.type_) } else { None }
1257 }
1258}
1259
1260#[derive(Clone, Debug)]
1261pub(crate) struct Trait {
1262 pub(crate) def_id: DefId,
1263 pub(crate) items: Vec<Item>,
1264 pub(crate) generics: Generics,
1265 pub(crate) bounds: Vec<GenericBound>,
1266}
1267
1268impl Trait {
1269 pub(crate) fn is_auto(&self, tcx: TyCtxt<'_>) -> bool {
1270 tcx.trait_is_auto(self.def_id)
1271 }
1272 pub(crate) fn is_notable_trait(&self, tcx: TyCtxt<'_>) -> bool {
1273 tcx.is_doc_notable_trait(self.def_id)
1274 }
1275 pub(crate) fn safety(&self, tcx: TyCtxt<'_>) -> hir::Safety {
1276 tcx.trait_def(self.def_id).safety
1277 }
1278 pub(crate) fn is_dyn_compatible(&self, tcx: TyCtxt<'_>) -> bool {
1279 tcx.is_dyn_compatible(self.def_id)
1280 }
1281 pub(crate) fn is_deprecated(&self, tcx: TyCtxt<'_>) -> bool {
1282 tcx.lookup_deprecation(self.def_id).is_some_and(|deprecation| deprecation.is_in_effect())
1283 }
1284}
1285
1286#[derive(Clone, Debug)]
1287pub(crate) struct TraitAlias {
1288 pub(crate) generics: Generics,
1289 pub(crate) bounds: Vec<GenericBound>,
1290}
1291
1292#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1294pub(crate) struct PolyTrait {
1295 pub(crate) trait_: Path,
1296 pub(crate) generic_params: Vec<GenericParamDef>,
1297}
1298
1299#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1301pub(crate) enum Type {
1302 Path {
1307 path: Path,
1308 },
1309 DynTrait(Vec<PolyTrait>, Option<Lifetime>),
1311 Generic(Symbol),
1313 SelfTy,
1315 Primitive(PrimitiveType),
1317 BareFunction(Box<BareFunctionDecl>),
1319 Tuple(Vec<Type>),
1321 Slice(Box<Type>),
1323 Array(Box<Type>, Box<str>),
1327 Pat(Box<Type>, Box<str>),
1328 RawPointer(Mutability, Box<Type>),
1330 BorrowedRef {
1332 lifetime: Option<Lifetime>,
1333 mutability: Mutability,
1334 type_: Box<Type>,
1335 },
1336
1337 QPath(Box<QPathData>),
1339
1340 Infer,
1342
1343 ImplTrait(Vec<GenericBound>),
1345
1346 UnsafeBinder(Box<UnsafeBinderTy>),
1347}
1348
1349impl Type {
1350 pub(crate) fn without_borrowed_ref(&self) -> &Type {
1352 let mut result = self;
1353 while let Type::BorrowedRef { type_, .. } = result {
1354 result = type_;
1355 }
1356 result
1357 }
1358
1359 pub(crate) fn is_borrowed_ref(&self) -> bool {
1360 matches!(self, Type::BorrowedRef { .. })
1361 }
1362
1363 fn is_type_alias(&self) -> bool {
1364 matches!(self, Type::Path { path: Path { res: Res::Def(DefKind::TyAlias, _), .. } })
1365 }
1366
1367 pub(crate) fn is_doc_subtype_of(&self, other: &Self, cache: &Cache) -> bool {
1388 let (self_cleared, other_cleared) = if !self.is_borrowed_ref() || !other.is_borrowed_ref() {
1391 (self.without_borrowed_ref(), other.without_borrowed_ref())
1392 } else {
1393 (self, other)
1394 };
1395
1396 if self_cleared.is_type_alias() || other_cleared.is_type_alias() {
1402 return true;
1403 }
1404
1405 match (self_cleared, other_cleared) {
1406 (Type::Tuple(a), Type::Tuple(b)) => {
1408 a.iter().eq_by(b, |a, b| a.is_doc_subtype_of(b, cache))
1409 }
1410 (Type::Slice(a), Type::Slice(b)) => a.is_doc_subtype_of(b, cache),
1411 (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_doc_subtype_of(b, cache),
1412 (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
1413 mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache)
1414 }
1415 (
1416 Type::BorrowedRef { mutability, type_, .. },
1417 Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
1418 ) => mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache),
1419 (Type::Infer, _) | (_, Type::Infer) => true,
1421 (_, Type::Generic(_)) => true,
1424 (Type::Generic(_), _) => false,
1425 (Type::SelfTy, Type::SelfTy) => true,
1427 (Type::Path { path: a }, Type::Path { path: b }) => {
1429 a.def_id() == b.def_id()
1430 && a.generics()
1431 .zip(b.generics())
1432 .map(|(ag, bg)| ag.zip(bg).all(|(at, bt)| at.is_doc_subtype_of(bt, cache)))
1433 .unwrap_or(true)
1434 }
1435 (a, b) => a
1437 .def_id(cache)
1438 .and_then(|a| Some((a, b.def_id(cache)?)))
1439 .map(|(a, b)| a == b)
1440 .unwrap_or(false),
1441 }
1442 }
1443
1444 pub(crate) fn primitive_type(&self) -> Option<PrimitiveType> {
1445 match *self {
1446 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1447 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1448 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1449 Tuple(ref tys) => {
1450 if tys.is_empty() {
1451 Some(PrimitiveType::Unit)
1452 } else {
1453 Some(PrimitiveType::Tuple)
1454 }
1455 }
1456 RawPointer(..) => Some(PrimitiveType::RawPointer),
1457 BareFunction(..) => Some(PrimitiveType::Fn),
1458 _ => None,
1459 }
1460 }
1461
1462 pub(crate) fn sugared_async_return_type(self) -> Type {
1472 if let Type::ImplTrait(mut v) = self
1473 && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = v.pop()
1474 && let Some(segment) = trait_.segments.pop()
1475 && let GenericArgs::AngleBracketed { mut constraints, .. } = segment.args
1476 && let Some(constraint) = constraints.pop()
1477 && let AssocItemConstraintKind::Equality { term } = constraint.kind
1478 && let Term::Type(ty) = term
1479 {
1480 ty
1481 } else {
1482 panic!("unexpected async fn return type")
1483 }
1484 }
1485
1486 pub(crate) fn is_assoc_ty(&self) -> bool {
1488 match self {
1489 Type::Path { path, .. } => path.is_assoc_ty(),
1490 _ => false,
1491 }
1492 }
1493
1494 pub(crate) fn is_self_type(&self) -> bool {
1495 matches!(*self, Type::SelfTy)
1496 }
1497
1498 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
1499 match self {
1500 Type::Path { path, .. } => path.generic_args(),
1501 _ => None,
1502 }
1503 }
1504
1505 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
1506 match self {
1507 Type::Path { path, .. } => path.generics(),
1508 _ => None,
1509 }
1510 }
1511
1512 pub(crate) fn is_full_generic(&self) -> bool {
1513 matches!(self, Type::Generic(_))
1514 }
1515
1516 pub(crate) fn is_unit(&self) -> bool {
1517 matches!(self, Type::Tuple(v) if v.is_empty())
1518 }
1519
1520 pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
1524 let t: PrimitiveType = match self {
1525 Type::Path { path } => return Some(path.def_id()),
1526 DynTrait(bounds, _) => return bounds.first().map(|b| b.trait_.def_id()),
1527 Primitive(p) => return cache.primitive_locations.get(p).cloned(),
1528 BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
1529 BorrowedRef { type_, .. } => return type_.def_id(cache),
1530 Tuple(tys) => {
1531 if tys.is_empty() {
1532 PrimitiveType::Unit
1533 } else {
1534 PrimitiveType::Tuple
1535 }
1536 }
1537 BareFunction(..) => PrimitiveType::Fn,
1538 Slice(..) => PrimitiveType::Slice,
1539 Array(..) => PrimitiveType::Array,
1540 Type::Pat(..) => PrimitiveType::Pat,
1541 RawPointer(..) => PrimitiveType::RawPointer,
1542 QPath(box QPathData { self_type, .. }) => return self_type.def_id(cache),
1543 Generic(_) | SelfTy | Infer | ImplTrait(_) | UnsafeBinder(_) => return None,
1544 };
1545 Primitive(t).def_id(cache)
1546 }
1547}
1548
1549#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1550pub(crate) struct QPathData {
1551 pub assoc: PathSegment,
1552 pub self_type: Type,
1553 pub should_fully_qualify: bool,
1555 pub trait_: Option<Path>,
1556}
1557
1558#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1565pub(crate) enum PrimitiveType {
1566 Isize,
1567 I8,
1568 I16,
1569 I32,
1570 I64,
1571 I128,
1572 Usize,
1573 U8,
1574 U16,
1575 U32,
1576 U64,
1577 U128,
1578 F16,
1579 F32,
1580 F64,
1581 F128,
1582 Char,
1583 Bool,
1584 Str,
1585 Slice,
1586 Array,
1587 Pat,
1588 Tuple,
1589 Unit,
1590 RawPointer,
1591 Reference,
1592 Fn,
1593 Never,
1594}
1595
1596type SimplifiedTypes = FxIndexMap<PrimitiveType, ArrayVec<SimplifiedType, 3>>;
1597impl PrimitiveType {
1598 pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1599 use ast::{FloatTy, IntTy, UintTy};
1600 match prim {
1601 hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1602 hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1603 hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1604 hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1605 hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1606 hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1607 hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1608 hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1609 hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1610 hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1611 hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1612 hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1613 hir::PrimTy::Float(FloatTy::F16) => PrimitiveType::F16,
1614 hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1615 hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1616 hir::PrimTy::Float(FloatTy::F128) => PrimitiveType::F128,
1617 hir::PrimTy::Str => PrimitiveType::Str,
1618 hir::PrimTy::Bool => PrimitiveType::Bool,
1619 hir::PrimTy::Char => PrimitiveType::Char,
1620 }
1621 }
1622
1623 pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1624 match s {
1625 sym::isize => Some(PrimitiveType::Isize),
1626 sym::i8 => Some(PrimitiveType::I8),
1627 sym::i16 => Some(PrimitiveType::I16),
1628 sym::i32 => Some(PrimitiveType::I32),
1629 sym::i64 => Some(PrimitiveType::I64),
1630 sym::i128 => Some(PrimitiveType::I128),
1631 sym::usize => Some(PrimitiveType::Usize),
1632 sym::u8 => Some(PrimitiveType::U8),
1633 sym::u16 => Some(PrimitiveType::U16),
1634 sym::u32 => Some(PrimitiveType::U32),
1635 sym::u64 => Some(PrimitiveType::U64),
1636 sym::u128 => Some(PrimitiveType::U128),
1637 sym::bool => Some(PrimitiveType::Bool),
1638 sym::char => Some(PrimitiveType::Char),
1639 sym::str => Some(PrimitiveType::Str),
1640 sym::f16 => Some(PrimitiveType::F16),
1641 sym::f32 => Some(PrimitiveType::F32),
1642 sym::f64 => Some(PrimitiveType::F64),
1643 sym::f128 => Some(PrimitiveType::F128),
1644 sym::array => Some(PrimitiveType::Array),
1645 sym::slice => Some(PrimitiveType::Slice),
1646 sym::tuple => Some(PrimitiveType::Tuple),
1647 sym::unit => Some(PrimitiveType::Unit),
1648 sym::pointer => Some(PrimitiveType::RawPointer),
1649 sym::reference => Some(PrimitiveType::Reference),
1650 kw::Fn => Some(PrimitiveType::Fn),
1651 sym::never => Some(PrimitiveType::Never),
1652 _ => None,
1653 }
1654 }
1655
1656 pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
1657 use PrimitiveType::*;
1658 use ty::{FloatTy, IntTy, UintTy};
1659 static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
1660
1661 let single = |x| iter::once(x).collect();
1662 CELL.get_or_init(move || {
1663 map! {
1664 Isize => single(SimplifiedType::Int(IntTy::Isize)),
1665 I8 => single(SimplifiedType::Int(IntTy::I8)),
1666 I16 => single(SimplifiedType::Int(IntTy::I16)),
1667 I32 => single(SimplifiedType::Int(IntTy::I32)),
1668 I64 => single(SimplifiedType::Int(IntTy::I64)),
1669 I128 => single(SimplifiedType::Int(IntTy::I128)),
1670 Usize => single(SimplifiedType::Uint(UintTy::Usize)),
1671 U8 => single(SimplifiedType::Uint(UintTy::U8)),
1672 U16 => single(SimplifiedType::Uint(UintTy::U16)),
1673 U32 => single(SimplifiedType::Uint(UintTy::U32)),
1674 U64 => single(SimplifiedType::Uint(UintTy::U64)),
1675 U128 => single(SimplifiedType::Uint(UintTy::U128)),
1676 F16 => single(SimplifiedType::Float(FloatTy::F16)),
1677 F32 => single(SimplifiedType::Float(FloatTy::F32)),
1678 F64 => single(SimplifiedType::Float(FloatTy::F64)),
1679 F128 => single(SimplifiedType::Float(FloatTy::F128)),
1680 Str => single(SimplifiedType::Str),
1681 Bool => single(SimplifiedType::Bool),
1682 Char => single(SimplifiedType::Char),
1683 Array => single(SimplifiedType::Array),
1684 Slice => single(SimplifiedType::Slice),
1685 Tuple => [SimplifiedType::Tuple(1), SimplifiedType::Tuple(2), SimplifiedType::Tuple(3)].into(),
1691 Unit => single(SimplifiedType::Tuple(0)),
1692 RawPointer => [SimplifiedType::Ptr(Mutability::Not), SimplifiedType::Ptr(Mutability::Mut)].into_iter().collect(),
1693 Reference => [SimplifiedType::Ref(Mutability::Not), SimplifiedType::Ref(Mutability::Mut)].into_iter().collect(),
1694 Fn => single(SimplifiedType::Function(1)),
1697 Never => single(SimplifiedType::Never),
1698 }
1699 })
1700 }
1701
1702 pub(crate) fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = DefId> + 'tcx {
1703 Self::simplified_types()
1704 .get(self)
1705 .into_iter()
1706 .flatten()
1707 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1708 .copied()
1709 }
1710
1711 pub(crate) fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> {
1712 Self::simplified_types()
1713 .values()
1714 .flatten()
1715 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1716 .copied()
1717 }
1718
1719 pub(crate) fn as_sym(&self) -> Symbol {
1720 use PrimitiveType::*;
1721 match self {
1722 Isize => sym::isize,
1723 I8 => sym::i8,
1724 I16 => sym::i16,
1725 I32 => sym::i32,
1726 I64 => sym::i64,
1727 I128 => sym::i128,
1728 Usize => sym::usize,
1729 U8 => sym::u8,
1730 U16 => sym::u16,
1731 U32 => sym::u32,
1732 U64 => sym::u64,
1733 U128 => sym::u128,
1734 F16 => sym::f16,
1735 F32 => sym::f32,
1736 F64 => sym::f64,
1737 F128 => sym::f128,
1738 Str => sym::str,
1739 Bool => sym::bool,
1740 Char => sym::char,
1741 Array => sym::array,
1742 Pat => sym::pat,
1743 Slice => sym::slice,
1744 Tuple => sym::tuple,
1745 Unit => sym::unit,
1746 RawPointer => sym::pointer,
1747 Reference => sym::reference,
1748 Fn => kw::Fn,
1749 Never => sym::never,
1750 }
1751 }
1752
1753 pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxIndexMap<PrimitiveType, DefId> {
1765 static PRIMITIVE_LOCATIONS: OnceCell<FxIndexMap<PrimitiveType, DefId>> = OnceCell::new();
1766 PRIMITIVE_LOCATIONS.get_or_init(|| {
1767 let mut primitive_locations = FxIndexMap::default();
1768 for &crate_num in tcx.crates(()) {
1771 let e = ExternalCrate { crate_num };
1772 let crate_name = e.name(tcx);
1773 debug!(?crate_num, ?crate_name);
1774 for (def_id, prim) in e.primitives(tcx) {
1775 if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1777 continue;
1778 }
1779 primitive_locations.insert(prim, def_id);
1780 }
1781 }
1782 let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1783 for (def_id, prim) in local_primitives {
1784 primitive_locations.insert(prim, def_id);
1785 }
1786 primitive_locations
1787 })
1788 }
1789}
1790
1791impl From<ty::IntTy> for PrimitiveType {
1792 fn from(int_ty: ty::IntTy) -> PrimitiveType {
1793 match int_ty {
1794 ty::IntTy::Isize => PrimitiveType::Isize,
1795 ty::IntTy::I8 => PrimitiveType::I8,
1796 ty::IntTy::I16 => PrimitiveType::I16,
1797 ty::IntTy::I32 => PrimitiveType::I32,
1798 ty::IntTy::I64 => PrimitiveType::I64,
1799 ty::IntTy::I128 => PrimitiveType::I128,
1800 }
1801 }
1802}
1803
1804impl From<ty::UintTy> for PrimitiveType {
1805 fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1806 match uint_ty {
1807 ty::UintTy::Usize => PrimitiveType::Usize,
1808 ty::UintTy::U8 => PrimitiveType::U8,
1809 ty::UintTy::U16 => PrimitiveType::U16,
1810 ty::UintTy::U32 => PrimitiveType::U32,
1811 ty::UintTy::U64 => PrimitiveType::U64,
1812 ty::UintTy::U128 => PrimitiveType::U128,
1813 }
1814 }
1815}
1816
1817impl From<ty::FloatTy> for PrimitiveType {
1818 fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1819 match float_ty {
1820 ty::FloatTy::F16 => PrimitiveType::F16,
1821 ty::FloatTy::F32 => PrimitiveType::F32,
1822 ty::FloatTy::F64 => PrimitiveType::F64,
1823 ty::FloatTy::F128 => PrimitiveType::F128,
1824 }
1825 }
1826}
1827
1828impl From<hir::PrimTy> for PrimitiveType {
1829 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1830 match prim_ty {
1831 hir::PrimTy::Int(int_ty) => int_ty.into(),
1832 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1833 hir::PrimTy::Float(float_ty) => float_ty.into(),
1834 hir::PrimTy::Str => PrimitiveType::Str,
1835 hir::PrimTy::Bool => PrimitiveType::Bool,
1836 hir::PrimTy::Char => PrimitiveType::Char,
1837 }
1838 }
1839}
1840
1841#[derive(Clone, Debug)]
1842pub(crate) struct Struct {
1843 pub(crate) ctor_kind: Option<CtorKind>,
1844 pub(crate) generics: Generics,
1845 pub(crate) fields: ThinVec<Item>,
1846}
1847
1848impl Struct {
1849 pub(crate) fn has_stripped_entries(&self) -> bool {
1850 self.fields.iter().any(|f| f.is_stripped())
1851 }
1852}
1853
1854#[derive(Clone, Debug)]
1855pub(crate) struct Union {
1856 pub(crate) generics: Generics,
1857 pub(crate) fields: Vec<Item>,
1858}
1859
1860impl Union {
1861 pub(crate) fn has_stripped_entries(&self) -> bool {
1862 self.fields.iter().any(|f| f.is_stripped())
1863 }
1864}
1865
1866#[derive(Clone, Debug)]
1870pub(crate) struct VariantStruct {
1871 pub(crate) fields: ThinVec<Item>,
1872}
1873
1874impl VariantStruct {
1875 pub(crate) fn has_stripped_entries(&self) -> bool {
1876 self.fields.iter().any(|f| f.is_stripped())
1877 }
1878}
1879
1880#[derive(Clone, Debug)]
1881pub(crate) struct Enum {
1882 pub(crate) variants: IndexVec<VariantIdx, Item>,
1883 pub(crate) generics: Generics,
1884}
1885
1886impl Enum {
1887 pub(crate) fn has_stripped_entries(&self) -> bool {
1888 self.variants.iter().any(|f| f.is_stripped())
1889 }
1890
1891 pub(crate) fn non_stripped_variants(&self) -> impl Iterator<Item = &Item> {
1892 self.variants.iter().filter(|v| !v.is_stripped())
1893 }
1894}
1895
1896#[derive(Clone, Debug)]
1897pub(crate) struct Variant {
1898 pub kind: VariantKind,
1899 pub discriminant: Option<Discriminant>,
1900}
1901
1902#[derive(Clone, Debug)]
1903pub(crate) enum VariantKind {
1904 CLike,
1905 Tuple(ThinVec<Item>),
1906 Struct(VariantStruct),
1907}
1908
1909impl Variant {
1910 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
1911 match &self.kind {
1912 VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()),
1913 VariantKind::CLike | VariantKind::Tuple(_) => None,
1914 }
1915 }
1916}
1917
1918#[derive(Clone, Debug)]
1919pub(crate) struct Discriminant {
1920 pub(super) expr: Option<BodyId>,
1923 pub(super) value: DefId,
1924}
1925
1926impl Discriminant {
1927 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
1930 self.expr
1931 .map(|body| rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body)))
1932 }
1933 pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String {
1934 print_evaluated_const(tcx, self.value, with_underscores, false).unwrap()
1935 }
1936}
1937
1938#[derive(Copy, Clone, Debug)]
1941pub(crate) struct Span(rustc_span::Span);
1942
1943impl Span {
1944 pub(crate) fn new(sp: rustc_span::Span) -> Self {
1949 Self(sp.source_callsite())
1950 }
1951
1952 pub(crate) fn inner(&self) -> rustc_span::Span {
1953 self.0
1954 }
1955
1956 pub(crate) fn filename(&self, sess: &Session) -> FileName {
1957 sess.source_map().span_to_filename(self.0)
1958 }
1959
1960 pub(crate) fn lo(&self, sess: &Session) -> Loc {
1961 sess.source_map().lookup_char_pos(self.0.lo())
1962 }
1963
1964 pub(crate) fn hi(&self, sess: &Session) -> Loc {
1965 sess.source_map().lookup_char_pos(self.0.hi())
1966 }
1967
1968 pub(crate) fn cnum(&self, sess: &Session) -> CrateNum {
1969 self.lo(sess).file.cnum
1971 }
1972}
1973
1974#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1975pub(crate) struct Path {
1976 pub(crate) res: Res,
1977 pub(crate) segments: ThinVec<PathSegment>,
1978}
1979
1980impl Path {
1981 pub(crate) fn def_id(&self) -> DefId {
1982 self.res.def_id()
1983 }
1984
1985 pub(crate) fn last_opt(&self) -> Option<Symbol> {
1986 self.segments.last().map(|s| s.name)
1987 }
1988
1989 pub(crate) fn last(&self) -> Symbol {
1990 self.last_opt().expect("segments were empty")
1991 }
1992
1993 pub(crate) fn whole_name(&self) -> String {
1994 self.segments
1995 .iter()
1996 .map(|s| if s.name == kw::PathRoot { "" } else { s.name.as_str() })
1997 .intersperse("::")
1998 .collect()
1999 }
2000
2001 pub(crate) fn is_assoc_ty(&self) -> bool {
2003 match self.res {
2004 Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _)
2005 if self.segments.len() != 1 =>
2006 {
2007 true
2008 }
2009 Res::Def(DefKind::AssocTy, _) => true,
2010 _ => false,
2011 }
2012 }
2013
2014 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
2015 self.segments.last().map(|seg| &seg.args)
2016 }
2017
2018 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
2019 self.segments.last().and_then(|seg| {
2020 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2021 Some(args.iter().filter_map(|arg| match arg {
2022 GenericArg::Type(ty) => Some(ty),
2023 _ => None,
2024 }))
2025 } else {
2026 None
2027 }
2028 })
2029 }
2030}
2031
2032#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2033pub(crate) enum GenericArg {
2034 Lifetime(Lifetime),
2035 Type(Type),
2036 Const(Box<ConstantKind>),
2037 Infer,
2038}
2039
2040impl GenericArg {
2041 pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
2042 if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2043 }
2044
2045 pub(crate) fn as_ty(&self) -> Option<&Type> {
2046 if let Self::Type(ty) = self { Some(ty) } else { None }
2047 }
2048}
2049
2050#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2051pub(crate) enum GenericArgs {
2052 AngleBracketed { args: ThinVec<GenericArg>, constraints: ThinVec<AssocItemConstraint> },
2054 Parenthesized { inputs: ThinVec<Type>, output: Option<Box<Type>> },
2056 ReturnTypeNotation,
2058}
2059
2060impl GenericArgs {
2061 pub(crate) fn is_empty(&self) -> bool {
2062 match self {
2063 GenericArgs::AngleBracketed { args, constraints } => {
2064 args.is_empty() && constraints.is_empty()
2065 }
2066 GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
2067 GenericArgs::ReturnTypeNotation => false,
2068 }
2069 }
2070 pub(crate) fn constraints(&self) -> Box<dyn Iterator<Item = AssocItemConstraint> + '_> {
2071 match self {
2072 GenericArgs::AngleBracketed { constraints, .. } => {
2073 Box::new(constraints.iter().cloned())
2074 }
2075 GenericArgs::Parenthesized { output, .. } => Box::new(
2076 output
2077 .as_ref()
2078 .map(|ty| AssocItemConstraint {
2079 assoc: PathSegment {
2080 name: sym::Output,
2081 args: GenericArgs::AngleBracketed {
2082 args: ThinVec::new(),
2083 constraints: ThinVec::new(),
2084 },
2085 },
2086 kind: AssocItemConstraintKind::Equality {
2087 term: Term::Type((**ty).clone()),
2088 },
2089 })
2090 .into_iter(),
2091 ),
2092 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2093 }
2094 }
2095}
2096
2097impl<'a> IntoIterator for &'a GenericArgs {
2098 type IntoIter = Box<dyn Iterator<Item = GenericArg> + 'a>;
2099 type Item = GenericArg;
2100 fn into_iter(self) -> Self::IntoIter {
2101 match self {
2102 GenericArgs::AngleBracketed { args, .. } => Box::new(args.iter().cloned()),
2103 GenericArgs::Parenthesized { inputs, .. } => {
2104 Box::new(inputs.iter().cloned().map(GenericArg::Type))
2106 }
2107 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2108 }
2109 }
2110}
2111
2112#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2113pub(crate) struct PathSegment {
2114 pub(crate) name: Symbol,
2115 pub(crate) args: GenericArgs,
2116}
2117
2118#[derive(Clone, Debug)]
2119pub(crate) enum TypeAliasInnerType {
2120 Enum { variants: IndexVec<VariantIdx, Item>, is_non_exhaustive: bool },
2121 Union { fields: Vec<Item> },
2122 Struct { ctor_kind: Option<CtorKind>, fields: Vec<Item> },
2123}
2124
2125impl TypeAliasInnerType {
2126 fn has_stripped_entries(&self) -> Option<bool> {
2127 Some(match self {
2128 Self::Enum { variants, .. } => variants.iter().any(|v| v.is_stripped()),
2129 Self::Union { fields } | Self::Struct { fields, .. } => {
2130 fields.iter().any(|f| f.is_stripped())
2131 }
2132 })
2133 }
2134}
2135
2136#[derive(Clone, Debug)]
2137pub(crate) struct TypeAlias {
2138 pub(crate) type_: Type,
2139 pub(crate) generics: Generics,
2140 pub(crate) inner_type: Option<TypeAliasInnerType>,
2143 pub(crate) item_type: Option<Type>,
2150}
2151
2152#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2153pub(crate) struct BareFunctionDecl {
2154 pub(crate) safety: hir::Safety,
2155 pub(crate) generic_params: Vec<GenericParamDef>,
2156 pub(crate) decl: FnDecl,
2157 pub(crate) abi: ExternAbi,
2158}
2159
2160#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2161pub(crate) struct UnsafeBinderTy {
2162 pub(crate) generic_params: Vec<GenericParamDef>,
2163 pub(crate) ty: Type,
2164}
2165
2166#[derive(Clone, Debug)]
2167pub(crate) struct Static {
2168 pub(crate) type_: Box<Type>,
2169 pub(crate) mutability: Mutability,
2170 pub(crate) expr: Option<BodyId>,
2171}
2172
2173#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2174pub(crate) struct Constant {
2175 pub(crate) generics: Generics,
2176 pub(crate) kind: ConstantKind,
2177 pub(crate) type_: Type,
2178}
2179
2180#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2181pub(crate) enum Term {
2182 Type(Type),
2183 Constant(ConstantKind),
2184}
2185
2186impl Term {
2187 pub(crate) fn ty(&self) -> Option<&Type> {
2188 if let Term::Type(ty) = self { Some(ty) } else { None }
2189 }
2190}
2191
2192impl From<Type> for Term {
2193 fn from(ty: Type) -> Self {
2194 Term::Type(ty)
2195 }
2196}
2197
2198#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2199pub(crate) enum ConstantKind {
2200 TyConst { expr: Box<str> },
2206 Path { path: Box<str> },
2209 Anonymous { body: BodyId },
2213 Extern { def_id: DefId },
2215 Local { def_id: DefId, body: BodyId },
2217 Infer,
2219}
2220
2221impl ConstantKind {
2222 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2223 match *self {
2224 ConstantKind::TyConst { ref expr } => expr.to_string(),
2225 ConstantKind::Path { ref path } => path.to_string(),
2226 ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2227 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2228 rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body))
2229 }
2230 ConstantKind::Infer => "_".to_string(),
2231 }
2232 }
2233
2234 pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2235 match *self {
2236 ConstantKind::TyConst { .. }
2237 | ConstantKind::Path { .. }
2238 | ConstantKind::Anonymous { .. }
2239 | ConstantKind::Infer => None,
2240 ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2241 print_evaluated_const(tcx, def_id, true, true)
2242 }
2243 }
2244 }
2245
2246 pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2247 match *self {
2248 ConstantKind::TyConst { .. }
2249 | ConstantKind::Extern { .. }
2250 | ConstantKind::Path { .. }
2251 | ConstantKind::Infer => false,
2252 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2253 is_literal_expr(tcx, body.hir_id)
2254 }
2255 }
2256 }
2257}
2258
2259#[derive(Clone, Debug)]
2260pub(crate) struct Impl {
2261 pub(crate) safety: hir::Safety,
2262 pub(crate) generics: Generics,
2263 pub(crate) trait_: Option<Path>,
2264 pub(crate) for_: Type,
2265 pub(crate) items: Vec<Item>,
2266 pub(crate) polarity: ty::ImplPolarity,
2267 pub(crate) kind: ImplKind,
2268 pub(crate) is_deprecated: bool,
2269}
2270
2271impl Impl {
2272 pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxIndexSet<Symbol> {
2273 self.trait_
2274 .as_ref()
2275 .map(|t| t.def_id())
2276 .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name()).collect())
2277 .unwrap_or_default()
2278 }
2279
2280 pub(crate) fn is_negative_trait_impl(&self) -> bool {
2281 matches!(self.polarity, ty::ImplPolarity::Negative)
2282 }
2283}
2284
2285#[derive(Clone, Debug)]
2286pub(crate) enum ImplKind {
2287 Normal,
2288 Auto,
2289 FakeVariadic,
2290 Blanket(Box<Type>),
2291}
2292
2293impl ImplKind {
2294 pub(crate) fn is_auto(&self) -> bool {
2295 matches!(self, ImplKind::Auto)
2296 }
2297
2298 pub(crate) fn is_blanket(&self) -> bool {
2299 matches!(self, ImplKind::Blanket(_))
2300 }
2301
2302 pub(crate) fn is_fake_variadic(&self) -> bool {
2303 matches!(self, ImplKind::FakeVariadic)
2304 }
2305
2306 pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
2307 match self {
2308 ImplKind::Blanket(ty) => Some(ty),
2309 _ => None,
2310 }
2311 }
2312}
2313
2314#[derive(Clone, Debug)]
2315pub(crate) struct Import {
2316 pub(crate) kind: ImportKind,
2317 pub(crate) source: ImportSource,
2319 pub(crate) should_be_displayed: bool,
2320}
2321
2322impl Import {
2323 pub(crate) fn new_simple(
2324 name: Symbol,
2325 source: ImportSource,
2326 should_be_displayed: bool,
2327 ) -> Self {
2328 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2329 }
2330
2331 pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2332 Self { kind: ImportKind::Glob, source, should_be_displayed }
2333 }
2334
2335 pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool {
2336 self.source.did.is_some_and(|did| tcx.is_doc_hidden(did))
2337 }
2338}
2339
2340#[derive(Clone, Debug)]
2341pub(crate) enum ImportKind {
2342 Simple(Symbol),
2344 Glob,
2346}
2347
2348#[derive(Clone, Debug)]
2349pub(crate) struct ImportSource {
2350 pub(crate) path: Path,
2351 pub(crate) did: Option<DefId>,
2352}
2353
2354#[derive(Clone, Debug)]
2355pub(crate) struct Macro {
2356 pub(crate) source: String,
2357 pub(crate) macro_rules: bool,
2359}
2360
2361#[derive(Clone, Debug)]
2362pub(crate) struct ProcMacro {
2363 pub(crate) kind: MacroKind,
2364 pub(crate) helpers: Vec<Symbol>,
2365}
2366
2367#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2378pub(crate) struct AssocItemConstraint {
2379 pub(crate) assoc: PathSegment,
2380 pub(crate) kind: AssocItemConstraintKind,
2381}
2382
2383#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2385pub(crate) enum AssocItemConstraintKind {
2386 Equality { term: Term },
2387 Bound { bounds: Vec<GenericBound> },
2388}
2389
2390#[cfg(target_pointer_width = "64")]
2392mod size_asserts {
2393 use rustc_data_structures::static_assert_size;
2394
2395 use super::*;
2396 static_assert_size!(Crate, 16); static_assert_size!(DocFragment, 48);
2399 static_assert_size!(GenericArg, 32);
2400 static_assert_size!(GenericArgs, 24);
2401 static_assert_size!(GenericParamDef, 40);
2402 static_assert_size!(Generics, 16);
2403 static_assert_size!(Item, 8);
2404 static_assert_size!(ItemInner, 144);
2405 static_assert_size!(ItemKind, 48);
2406 static_assert_size!(PathSegment, 32);
2407 static_assert_size!(Type, 32);
2408 }