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