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