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