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