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 RawPointer(Mutability, Box<Type>),
1354 BorrowedRef {
1356 lifetime: Option<Lifetime>,
1357 mutability: Mutability,
1358 type_: Box<Type>,
1359 },
1360
1361 QPath(Box<QPathData>),
1363
1364 Infer,
1366
1367 ImplTrait(Vec<GenericBound>),
1369
1370 UnsafeBinder(Box<UnsafeBinderTy>),
1371}
1372
1373impl Type {
1374 pub(crate) fn without_borrowed_ref(&self) -> &Type {
1376 let mut result = self;
1377 while let Type::BorrowedRef { type_, .. } = result {
1378 result = type_;
1379 }
1380 result
1381 }
1382
1383 pub(crate) fn is_borrowed_ref(&self) -> bool {
1384 matches!(self, Type::BorrowedRef { .. })
1385 }
1386
1387 fn is_type_alias(&self) -> bool {
1388 matches!(self, Type::Path { path: Path { res: Res::Def(DefKind::TyAlias, _), .. } })
1389 }
1390
1391 pub(crate) fn is_doc_subtype_of(&self, other: &Self, cache: &Cache) -> bool {
1412 let (self_cleared, other_cleared) = if !self.is_borrowed_ref() || !other.is_borrowed_ref() {
1415 (self.without_borrowed_ref(), other.without_borrowed_ref())
1416 } else {
1417 (self, other)
1418 };
1419
1420 if self_cleared.is_type_alias() || other_cleared.is_type_alias() {
1426 return true;
1427 }
1428
1429 match (self_cleared, other_cleared) {
1430 (Type::Tuple(a), Type::Tuple(b)) => {
1432 a.iter().eq_by(b, |a, b| a.is_doc_subtype_of(b, cache))
1433 }
1434 (Type::Slice(a), Type::Slice(b)) => a.is_doc_subtype_of(b, cache),
1435 (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_doc_subtype_of(b, cache),
1436 (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
1437 mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache)
1438 }
1439 (
1440 Type::BorrowedRef { mutability, type_, .. },
1441 Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
1442 ) => mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache),
1443 (Type::Infer, _) | (_, Type::Infer) => true,
1445 (_, Type::Generic(_)) => true,
1448 (Type::Generic(_), _) => false,
1449 (Type::SelfTy, Type::SelfTy) => true,
1451 (Type::Path { path: a }, Type::Path { path: b }) => {
1453 a.def_id() == b.def_id()
1454 && a.generics()
1455 .zip(b.generics())
1456 .map(|(ag, bg)| ag.zip(bg).all(|(at, bt)| at.is_doc_subtype_of(bt, cache)))
1457 .unwrap_or(true)
1458 }
1459 (a, b) => a
1461 .def_id(cache)
1462 .and_then(|a| Some((a, b.def_id(cache)?)))
1463 .map(|(a, b)| a == b)
1464 .unwrap_or(false),
1465 }
1466 }
1467
1468 pub(crate) fn primitive_type(&self) -> Option<PrimitiveType> {
1469 match *self {
1470 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1471 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1472 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1473 Tuple(ref tys) => {
1474 if tys.is_empty() {
1475 Some(PrimitiveType::Unit)
1476 } else {
1477 Some(PrimitiveType::Tuple)
1478 }
1479 }
1480 RawPointer(..) => Some(PrimitiveType::RawPointer),
1481 BareFunction(..) => Some(PrimitiveType::Fn),
1482 _ => None,
1483 }
1484 }
1485
1486 pub(crate) fn sugared_async_return_type(self) -> Type {
1496 if let Type::ImplTrait(mut v) = self
1497 && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = v.pop()
1498 && let Some(segment) = trait_.segments.pop()
1499 && let GenericArgs::AngleBracketed { mut constraints, .. } = segment.args
1500 && let Some(constraint) = constraints.pop()
1501 && let AssocItemConstraintKind::Equality { term } = constraint.kind
1502 && let Term::Type(ty) = term
1503 {
1504 ty
1505 } else {
1506 panic!("unexpected async fn return type")
1507 }
1508 }
1509
1510 pub(crate) fn is_assoc_ty(&self) -> bool {
1512 match self {
1513 Type::Path { path, .. } => path.is_assoc_ty(),
1514 _ => false,
1515 }
1516 }
1517
1518 pub(crate) fn is_self_type(&self) -> bool {
1519 matches!(*self, Type::SelfTy)
1520 }
1521
1522 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
1523 match self {
1524 Type::Path { path, .. } => path.generic_args(),
1525 _ => None,
1526 }
1527 }
1528
1529 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
1530 match self {
1531 Type::Path { path, .. } => path.generics(),
1532 _ => None,
1533 }
1534 }
1535
1536 pub(crate) fn is_full_generic(&self) -> bool {
1537 matches!(self, Type::Generic(_))
1538 }
1539
1540 pub(crate) fn is_unit(&self) -> bool {
1541 matches!(self, Type::Tuple(v) if v.is_empty())
1542 }
1543
1544 pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
1548 let t: PrimitiveType = match self {
1549 Type::Path { path } => return Some(path.def_id()),
1550 DynTrait(bounds, _) => return bounds.first().map(|b| b.trait_.def_id()),
1551 Primitive(p) => return cache.primitive_locations.get(p).cloned(),
1552 BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
1553 BorrowedRef { type_, .. } => return type_.def_id(cache),
1554 Tuple(tys) => {
1555 if tys.is_empty() {
1556 PrimitiveType::Unit
1557 } else {
1558 PrimitiveType::Tuple
1559 }
1560 }
1561 BareFunction(..) => PrimitiveType::Fn,
1562 Slice(..) => PrimitiveType::Slice,
1563 Array(..) => PrimitiveType::Array,
1564 Type::Pat(..) => PrimitiveType::Pat,
1565 RawPointer(..) => PrimitiveType::RawPointer,
1566 QPath(box QPathData { self_type, .. }) => return self_type.def_id(cache),
1567 Generic(_) | SelfTy | Infer | ImplTrait(_) | UnsafeBinder(_) => return None,
1568 };
1569 Primitive(t).def_id(cache)
1570 }
1571}
1572
1573#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1574pub(crate) struct QPathData {
1575 pub assoc: PathSegment,
1576 pub self_type: Type,
1577 pub should_fully_qualify: bool,
1579 pub trait_: Option<Path>,
1580}
1581
1582#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1589pub(crate) enum PrimitiveType {
1590 Isize,
1591 I8,
1592 I16,
1593 I32,
1594 I64,
1595 I128,
1596 Usize,
1597 U8,
1598 U16,
1599 U32,
1600 U64,
1601 U128,
1602 F16,
1603 F32,
1604 F64,
1605 F128,
1606 Char,
1607 Bool,
1608 Str,
1609 Slice,
1610 Array,
1611 Pat,
1612 Tuple,
1613 Unit,
1614 RawPointer,
1615 Reference,
1616 Fn,
1617 Never,
1618}
1619
1620type SimplifiedTypes = FxIndexMap<PrimitiveType, ArrayVec<SimplifiedType, 3>>;
1621impl PrimitiveType {
1622 pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1623 use ast::{FloatTy, IntTy, UintTy};
1624 match prim {
1625 hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1626 hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1627 hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1628 hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1629 hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1630 hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1631 hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1632 hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1633 hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1634 hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1635 hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1636 hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1637 hir::PrimTy::Float(FloatTy::F16) => PrimitiveType::F16,
1638 hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1639 hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1640 hir::PrimTy::Float(FloatTy::F128) => PrimitiveType::F128,
1641 hir::PrimTy::Str => PrimitiveType::Str,
1642 hir::PrimTy::Bool => PrimitiveType::Bool,
1643 hir::PrimTy::Char => PrimitiveType::Char,
1644 }
1645 }
1646
1647 pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1648 match s {
1649 sym::isize => Some(PrimitiveType::Isize),
1650 sym::i8 => Some(PrimitiveType::I8),
1651 sym::i16 => Some(PrimitiveType::I16),
1652 sym::i32 => Some(PrimitiveType::I32),
1653 sym::i64 => Some(PrimitiveType::I64),
1654 sym::i128 => Some(PrimitiveType::I128),
1655 sym::usize => Some(PrimitiveType::Usize),
1656 sym::u8 => Some(PrimitiveType::U8),
1657 sym::u16 => Some(PrimitiveType::U16),
1658 sym::u32 => Some(PrimitiveType::U32),
1659 sym::u64 => Some(PrimitiveType::U64),
1660 sym::u128 => Some(PrimitiveType::U128),
1661 sym::bool => Some(PrimitiveType::Bool),
1662 sym::char => Some(PrimitiveType::Char),
1663 sym::str => Some(PrimitiveType::Str),
1664 sym::f16 => Some(PrimitiveType::F16),
1665 sym::f32 => Some(PrimitiveType::F32),
1666 sym::f64 => Some(PrimitiveType::F64),
1667 sym::f128 => Some(PrimitiveType::F128),
1668 sym::array => Some(PrimitiveType::Array),
1669 sym::slice => Some(PrimitiveType::Slice),
1670 sym::tuple => Some(PrimitiveType::Tuple),
1671 sym::unit => Some(PrimitiveType::Unit),
1672 sym::pointer => Some(PrimitiveType::RawPointer),
1673 sym::reference => Some(PrimitiveType::Reference),
1674 kw::Fn => Some(PrimitiveType::Fn),
1675 sym::never => Some(PrimitiveType::Never),
1676 _ => None,
1677 }
1678 }
1679
1680 pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
1681 use PrimitiveType::*;
1682 use ty::{FloatTy, IntTy, UintTy};
1683 static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
1684
1685 let single = |x| iter::once(x).collect();
1686 CELL.get_or_init(move || {
1687 map! {
1688 Isize => single(SimplifiedType::Int(IntTy::Isize)),
1689 I8 => single(SimplifiedType::Int(IntTy::I8)),
1690 I16 => single(SimplifiedType::Int(IntTy::I16)),
1691 I32 => single(SimplifiedType::Int(IntTy::I32)),
1692 I64 => single(SimplifiedType::Int(IntTy::I64)),
1693 I128 => single(SimplifiedType::Int(IntTy::I128)),
1694 Usize => single(SimplifiedType::Uint(UintTy::Usize)),
1695 U8 => single(SimplifiedType::Uint(UintTy::U8)),
1696 U16 => single(SimplifiedType::Uint(UintTy::U16)),
1697 U32 => single(SimplifiedType::Uint(UintTy::U32)),
1698 U64 => single(SimplifiedType::Uint(UintTy::U64)),
1699 U128 => single(SimplifiedType::Uint(UintTy::U128)),
1700 F16 => single(SimplifiedType::Float(FloatTy::F16)),
1701 F32 => single(SimplifiedType::Float(FloatTy::F32)),
1702 F64 => single(SimplifiedType::Float(FloatTy::F64)),
1703 F128 => single(SimplifiedType::Float(FloatTy::F128)),
1704 Str => single(SimplifiedType::Str),
1705 Bool => single(SimplifiedType::Bool),
1706 Char => single(SimplifiedType::Char),
1707 Array => single(SimplifiedType::Array),
1708 Slice => single(SimplifiedType::Slice),
1709 Tuple => [SimplifiedType::Tuple(1), SimplifiedType::Tuple(2), SimplifiedType::Tuple(3)].into(),
1715 Unit => single(SimplifiedType::Tuple(0)),
1716 RawPointer => [SimplifiedType::Ptr(Mutability::Not), SimplifiedType::Ptr(Mutability::Mut)].into_iter().collect(),
1717 Reference => [SimplifiedType::Ref(Mutability::Not), SimplifiedType::Ref(Mutability::Mut)].into_iter().collect(),
1718 Fn => single(SimplifiedType::Function(1)),
1721 Never => single(SimplifiedType::Never),
1722 }
1723 })
1724 }
1725
1726 pub(crate) fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = DefId> + 'tcx {
1727 Self::simplified_types()
1728 .get(self)
1729 .into_iter()
1730 .flatten()
1731 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1732 .copied()
1733 }
1734
1735 pub(crate) fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> {
1736 Self::simplified_types()
1737 .values()
1738 .flatten()
1739 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1740 .copied()
1741 }
1742
1743 pub(crate) fn as_sym(&self) -> Symbol {
1744 use PrimitiveType::*;
1745 match self {
1746 Isize => sym::isize,
1747 I8 => sym::i8,
1748 I16 => sym::i16,
1749 I32 => sym::i32,
1750 I64 => sym::i64,
1751 I128 => sym::i128,
1752 Usize => sym::usize,
1753 U8 => sym::u8,
1754 U16 => sym::u16,
1755 U32 => sym::u32,
1756 U64 => sym::u64,
1757 U128 => sym::u128,
1758 F16 => sym::f16,
1759 F32 => sym::f32,
1760 F64 => sym::f64,
1761 F128 => sym::f128,
1762 Str => sym::str,
1763 Bool => sym::bool,
1764 Char => sym::char,
1765 Array => sym::array,
1766 Pat => sym::pat,
1767 Slice => sym::slice,
1768 Tuple => sym::tuple,
1769 Unit => sym::unit,
1770 RawPointer => sym::pointer,
1771 Reference => sym::reference,
1772 Fn => kw::Fn,
1773 Never => sym::never,
1774 }
1775 }
1776
1777 pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxIndexMap<PrimitiveType, DefId> {
1789 static PRIMITIVE_LOCATIONS: OnceCell<FxIndexMap<PrimitiveType, DefId>> = OnceCell::new();
1790 PRIMITIVE_LOCATIONS.get_or_init(|| {
1791 let mut primitive_locations = FxIndexMap::default();
1792 for &crate_num in tcx.crates(()) {
1795 let e = ExternalCrate { crate_num };
1796 let crate_name = e.name(tcx);
1797 debug!(?crate_num, ?crate_name);
1798 for (def_id, prim) in e.primitives(tcx) {
1799 if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1801 continue;
1802 }
1803 primitive_locations.insert(prim, def_id);
1804 }
1805 }
1806 let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1807 for (def_id, prim) in local_primitives {
1808 primitive_locations.insert(prim, def_id);
1809 }
1810 primitive_locations
1811 })
1812 }
1813}
1814
1815impl From<ty::IntTy> for PrimitiveType {
1816 fn from(int_ty: ty::IntTy) -> PrimitiveType {
1817 match int_ty {
1818 ty::IntTy::Isize => PrimitiveType::Isize,
1819 ty::IntTy::I8 => PrimitiveType::I8,
1820 ty::IntTy::I16 => PrimitiveType::I16,
1821 ty::IntTy::I32 => PrimitiveType::I32,
1822 ty::IntTy::I64 => PrimitiveType::I64,
1823 ty::IntTy::I128 => PrimitiveType::I128,
1824 }
1825 }
1826}
1827
1828impl From<ty::UintTy> for PrimitiveType {
1829 fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1830 match uint_ty {
1831 ty::UintTy::Usize => PrimitiveType::Usize,
1832 ty::UintTy::U8 => PrimitiveType::U8,
1833 ty::UintTy::U16 => PrimitiveType::U16,
1834 ty::UintTy::U32 => PrimitiveType::U32,
1835 ty::UintTy::U64 => PrimitiveType::U64,
1836 ty::UintTy::U128 => PrimitiveType::U128,
1837 }
1838 }
1839}
1840
1841impl From<ty::FloatTy> for PrimitiveType {
1842 fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1843 match float_ty {
1844 ty::FloatTy::F16 => PrimitiveType::F16,
1845 ty::FloatTy::F32 => PrimitiveType::F32,
1846 ty::FloatTy::F64 => PrimitiveType::F64,
1847 ty::FloatTy::F128 => PrimitiveType::F128,
1848 }
1849 }
1850}
1851
1852impl From<hir::PrimTy> for PrimitiveType {
1853 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1854 match prim_ty {
1855 hir::PrimTy::Int(int_ty) => int_ty.into(),
1856 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1857 hir::PrimTy::Float(float_ty) => float_ty.into(),
1858 hir::PrimTy::Str => PrimitiveType::Str,
1859 hir::PrimTy::Bool => PrimitiveType::Bool,
1860 hir::PrimTy::Char => PrimitiveType::Char,
1861 }
1862 }
1863}
1864
1865#[derive(Clone, Debug)]
1866pub(crate) struct Struct {
1867 pub(crate) ctor_kind: Option<CtorKind>,
1868 pub(crate) generics: Generics,
1869 pub(crate) fields: ThinVec<Item>,
1870}
1871
1872impl Struct {
1873 pub(crate) fn has_stripped_entries(&self) -> bool {
1874 self.fields.iter().any(|f| f.is_stripped())
1875 }
1876}
1877
1878#[derive(Clone, Debug)]
1879pub(crate) struct Union {
1880 pub(crate) generics: Generics,
1881 pub(crate) fields: Vec<Item>,
1882}
1883
1884impl Union {
1885 pub(crate) fn has_stripped_entries(&self) -> bool {
1886 self.fields.iter().any(|f| f.is_stripped())
1887 }
1888}
1889
1890#[derive(Clone, Debug)]
1894pub(crate) struct VariantStruct {
1895 pub(crate) fields: ThinVec<Item>,
1896}
1897
1898impl VariantStruct {
1899 pub(crate) fn has_stripped_entries(&self) -> bool {
1900 self.fields.iter().any(|f| f.is_stripped())
1901 }
1902}
1903
1904#[derive(Clone, Debug)]
1905pub(crate) struct Enum {
1906 pub(crate) variants: IndexVec<VariantIdx, Item>,
1907 pub(crate) generics: Generics,
1908}
1909
1910impl Enum {
1911 pub(crate) fn has_stripped_entries(&self) -> bool {
1912 self.variants.iter().any(|f| f.is_stripped())
1913 }
1914
1915 pub(crate) fn non_stripped_variants(&self) -> impl Iterator<Item = &Item> {
1916 self.variants.iter().filter(|v| !v.is_stripped())
1917 }
1918}
1919
1920#[derive(Clone, Debug)]
1921pub(crate) struct Variant {
1922 pub kind: VariantKind,
1923 pub discriminant: Option<Discriminant>,
1924}
1925
1926#[derive(Clone, Debug)]
1927pub(crate) enum VariantKind {
1928 CLike,
1929 Tuple(ThinVec<Item>),
1930 Struct(VariantStruct),
1931}
1932
1933impl Variant {
1934 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
1935 match &self.kind {
1936 VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()),
1937 VariantKind::CLike | VariantKind::Tuple(_) => None,
1938 }
1939 }
1940}
1941
1942#[derive(Clone, Debug)]
1943pub(crate) struct Discriminant {
1944 pub(super) expr: Option<BodyId>,
1947 pub(super) value: DefId,
1948}
1949
1950impl Discriminant {
1951 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
1954 self.expr
1955 .map(|body| rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body)))
1956 }
1957 pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String {
1958 print_evaluated_const(tcx, self.value, with_underscores, false).unwrap()
1959 }
1960}
1961
1962#[derive(Copy, Clone, Debug)]
1965pub(crate) struct Span(rustc_span::Span);
1966
1967impl Span {
1968 pub(crate) fn new(sp: rustc_span::Span) -> Self {
1973 Self(sp.source_callsite())
1974 }
1975
1976 pub(crate) fn inner(&self) -> rustc_span::Span {
1977 self.0
1978 }
1979
1980 pub(crate) fn filename(&self, sess: &Session) -> FileName {
1981 sess.source_map().span_to_filename(self.0)
1982 }
1983
1984 pub(crate) fn lo(&self, sess: &Session) -> Loc {
1985 sess.source_map().lookup_char_pos(self.0.lo())
1986 }
1987
1988 pub(crate) fn hi(&self, sess: &Session) -> Loc {
1989 sess.source_map().lookup_char_pos(self.0.hi())
1990 }
1991
1992 pub(crate) fn cnum(&self, sess: &Session) -> CrateNum {
1993 self.lo(sess).file.cnum
1995 }
1996}
1997
1998#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1999pub(crate) struct Path {
2000 pub(crate) res: Res,
2001 pub(crate) segments: ThinVec<PathSegment>,
2002}
2003
2004impl Path {
2005 pub(crate) fn def_id(&self) -> DefId {
2006 self.res.def_id()
2007 }
2008
2009 pub(crate) fn last_opt(&self) -> Option<Symbol> {
2010 self.segments.last().map(|s| s.name)
2011 }
2012
2013 pub(crate) fn last(&self) -> Symbol {
2014 self.last_opt().expect("segments were empty")
2015 }
2016
2017 pub(crate) fn whole_name(&self) -> String {
2018 self.segments
2019 .iter()
2020 .map(|s| if s.name == kw::PathRoot { "" } else { s.name.as_str() })
2021 .intersperse("::")
2022 .collect()
2023 }
2024
2025 pub(crate) fn is_assoc_ty(&self) -> bool {
2027 match self.res {
2028 Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _)
2029 if self.segments.len() != 1 =>
2030 {
2031 true
2032 }
2033 Res::Def(DefKind::AssocTy, _) => true,
2034 _ => false,
2035 }
2036 }
2037
2038 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
2039 self.segments.last().map(|seg| &seg.args)
2040 }
2041
2042 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
2043 self.segments.last().and_then(|seg| {
2044 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2045 Some(args.iter().filter_map(|arg| match arg {
2046 GenericArg::Type(ty) => Some(ty),
2047 _ => None,
2048 }))
2049 } else {
2050 None
2051 }
2052 })
2053 }
2054}
2055
2056#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2057pub(crate) enum GenericArg {
2058 Lifetime(Lifetime),
2059 Type(Type),
2060 Const(Box<ConstantKind>),
2061 Infer,
2062}
2063
2064impl GenericArg {
2065 pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
2066 if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2067 }
2068
2069 pub(crate) fn as_ty(&self) -> Option<&Type> {
2070 if let Self::Type(ty) = self { Some(ty) } else { None }
2071 }
2072}
2073
2074#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2075pub(crate) enum GenericArgs {
2076 AngleBracketed { args: ThinVec<GenericArg>, constraints: ThinVec<AssocItemConstraint> },
2078 Parenthesized { inputs: ThinVec<Type>, output: Option<Box<Type>> },
2080 ReturnTypeNotation,
2082}
2083
2084impl GenericArgs {
2085 pub(crate) fn is_empty(&self) -> bool {
2086 match self {
2087 GenericArgs::AngleBracketed { args, constraints } => {
2088 args.is_empty() && constraints.is_empty()
2089 }
2090 GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
2091 GenericArgs::ReturnTypeNotation => false,
2092 }
2093 }
2094 pub(crate) fn constraints(&self) -> Box<dyn Iterator<Item = AssocItemConstraint> + '_> {
2095 match self {
2096 GenericArgs::AngleBracketed { constraints, .. } => {
2097 Box::new(constraints.iter().cloned())
2098 }
2099 GenericArgs::Parenthesized { output, .. } => Box::new(
2100 output
2101 .as_ref()
2102 .map(|ty| AssocItemConstraint {
2103 assoc: PathSegment {
2104 name: sym::Output,
2105 args: GenericArgs::AngleBracketed {
2106 args: ThinVec::new(),
2107 constraints: ThinVec::new(),
2108 },
2109 },
2110 kind: AssocItemConstraintKind::Equality {
2111 term: Term::Type((**ty).clone()),
2112 },
2113 })
2114 .into_iter(),
2115 ),
2116 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2117 }
2118 }
2119}
2120
2121impl<'a> IntoIterator for &'a GenericArgs {
2122 type IntoIter = Box<dyn Iterator<Item = GenericArg> + 'a>;
2123 type Item = GenericArg;
2124 fn into_iter(self) -> Self::IntoIter {
2125 match self {
2126 GenericArgs::AngleBracketed { args, .. } => Box::new(args.iter().cloned()),
2127 GenericArgs::Parenthesized { inputs, .. } => {
2128 Box::new(inputs.iter().cloned().map(GenericArg::Type))
2130 }
2131 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2132 }
2133 }
2134}
2135
2136#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2137pub(crate) struct PathSegment {
2138 pub(crate) name: Symbol,
2139 pub(crate) args: GenericArgs,
2140}
2141
2142#[derive(Clone, Debug)]
2143pub(crate) enum TypeAliasInnerType {
2144 Enum { variants: IndexVec<VariantIdx, Item>, is_non_exhaustive: bool },
2145 Union { fields: Vec<Item> },
2146 Struct { ctor_kind: Option<CtorKind>, fields: Vec<Item> },
2147}
2148
2149impl TypeAliasInnerType {
2150 fn has_stripped_entries(&self) -> Option<bool> {
2151 Some(match self {
2152 Self::Enum { variants, .. } => variants.iter().any(|v| v.is_stripped()),
2153 Self::Union { fields } | Self::Struct { fields, .. } => {
2154 fields.iter().any(|f| f.is_stripped())
2155 }
2156 })
2157 }
2158}
2159
2160#[derive(Clone, Debug)]
2161pub(crate) struct TypeAlias {
2162 pub(crate) type_: Type,
2163 pub(crate) generics: Generics,
2164 pub(crate) inner_type: Option<TypeAliasInnerType>,
2167 pub(crate) item_type: Option<Type>,
2174}
2175
2176#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2177pub(crate) struct BareFunctionDecl {
2178 pub(crate) safety: hir::Safety,
2179 pub(crate) generic_params: Vec<GenericParamDef>,
2180 pub(crate) decl: FnDecl,
2181 pub(crate) abi: ExternAbi,
2182}
2183
2184#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2185pub(crate) struct UnsafeBinderTy {
2186 pub(crate) generic_params: Vec<GenericParamDef>,
2187 pub(crate) ty: Type,
2188}
2189
2190#[derive(Clone, Debug)]
2191pub(crate) struct Static {
2192 pub(crate) type_: Box<Type>,
2193 pub(crate) mutability: Mutability,
2194 pub(crate) expr: Option<BodyId>,
2195}
2196
2197#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2198pub(crate) struct Constant {
2199 pub(crate) generics: Generics,
2200 pub(crate) kind: ConstantKind,
2201 pub(crate) type_: Type,
2202}
2203
2204#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2205pub(crate) enum Term {
2206 Type(Type),
2207 Constant(ConstantKind),
2208}
2209
2210impl Term {
2211 pub(crate) fn ty(&self) -> Option<&Type> {
2212 if let Term::Type(ty) = self { Some(ty) } else { None }
2213 }
2214}
2215
2216impl From<Type> for Term {
2217 fn from(ty: Type) -> Self {
2218 Term::Type(ty)
2219 }
2220}
2221
2222#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2223pub(crate) enum ConstantKind {
2224 TyConst { expr: Box<str> },
2230 Path { path: Box<str> },
2233 Anonymous { body: BodyId },
2237 Extern { def_id: DefId },
2239 Local { def_id: DefId, body: BodyId },
2241 Infer,
2243}
2244
2245impl ConstantKind {
2246 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2247 match *self {
2248 ConstantKind::TyConst { ref expr } => expr.to_string(),
2249 ConstantKind::Path { ref path } => path.to_string(),
2250 ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2251 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2252 rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body))
2253 }
2254 ConstantKind::Infer => "_".to_string(),
2255 }
2256 }
2257
2258 pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2259 match *self {
2260 ConstantKind::TyConst { .. }
2261 | ConstantKind::Path { .. }
2262 | ConstantKind::Anonymous { .. }
2263 | ConstantKind::Infer => None,
2264 ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2265 print_evaluated_const(tcx, def_id, true, true)
2266 }
2267 }
2268 }
2269
2270 pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2271 match *self {
2272 ConstantKind::TyConst { .. }
2273 | ConstantKind::Extern { .. }
2274 | ConstantKind::Path { .. }
2275 | ConstantKind::Infer => false,
2276 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2277 is_literal_expr(tcx, body.hir_id)
2278 }
2279 }
2280 }
2281}
2282
2283#[derive(Clone, Debug)]
2284pub(crate) struct Impl {
2285 pub(crate) safety: hir::Safety,
2286 pub(crate) generics: Generics,
2287 pub(crate) trait_: Option<Path>,
2288 pub(crate) for_: Type,
2289 pub(crate) items: Vec<Item>,
2290 pub(crate) polarity: ty::ImplPolarity,
2291 pub(crate) kind: ImplKind,
2292 pub(crate) is_deprecated: bool,
2293}
2294
2295impl Impl {
2296 pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxIndexSet<Symbol> {
2297 self.trait_
2298 .as_ref()
2299 .map(|t| t.def_id())
2300 .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name()).collect())
2301 .unwrap_or_default()
2302 }
2303
2304 pub(crate) fn is_negative_trait_impl(&self) -> bool {
2305 matches!(self.polarity, ty::ImplPolarity::Negative)
2306 }
2307}
2308
2309#[derive(Clone, Debug)]
2310pub(crate) enum ImplKind {
2311 Normal,
2312 Auto,
2313 FakeVariadic,
2314 Blanket(Box<Type>),
2315}
2316
2317impl ImplKind {
2318 pub(crate) fn is_auto(&self) -> bool {
2319 matches!(self, ImplKind::Auto)
2320 }
2321
2322 pub(crate) fn is_blanket(&self) -> bool {
2323 matches!(self, ImplKind::Blanket(_))
2324 }
2325
2326 pub(crate) fn is_fake_variadic(&self) -> bool {
2327 matches!(self, ImplKind::FakeVariadic)
2328 }
2329
2330 pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
2331 match self {
2332 ImplKind::Blanket(ty) => Some(ty),
2333 _ => None,
2334 }
2335 }
2336}
2337
2338#[derive(Clone, Debug)]
2339pub(crate) struct Import {
2340 pub(crate) kind: ImportKind,
2341 pub(crate) source: ImportSource,
2343 pub(crate) should_be_displayed: bool,
2344}
2345
2346impl Import {
2347 pub(crate) fn new_simple(
2348 name: Symbol,
2349 source: ImportSource,
2350 should_be_displayed: bool,
2351 ) -> Self {
2352 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2353 }
2354
2355 pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2356 Self { kind: ImportKind::Glob, source, should_be_displayed }
2357 }
2358
2359 pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool {
2360 self.source.did.is_some_and(|did| tcx.is_doc_hidden(did))
2361 }
2362}
2363
2364#[derive(Clone, Debug)]
2365pub(crate) enum ImportKind {
2366 Simple(Symbol),
2368 Glob,
2370}
2371
2372#[derive(Clone, Debug)]
2373pub(crate) struct ImportSource {
2374 pub(crate) path: Path,
2375 pub(crate) did: Option<DefId>,
2376}
2377
2378#[derive(Clone, Debug)]
2379pub(crate) struct Macro {
2380 pub(crate) source: String,
2381 pub(crate) macro_rules: bool,
2383}
2384
2385#[derive(Clone, Debug)]
2386pub(crate) struct ProcMacro {
2387 pub(crate) kind: MacroKind,
2388 pub(crate) helpers: Vec<Symbol>,
2389}
2390
2391#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2402pub(crate) struct AssocItemConstraint {
2403 pub(crate) assoc: PathSegment,
2404 pub(crate) kind: AssocItemConstraintKind,
2405}
2406
2407#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2409pub(crate) enum AssocItemConstraintKind {
2410 Equality { term: Term },
2411 Bound { bounds: Vec<GenericBound> },
2412}
2413
2414#[cfg(target_pointer_width = "64")]
2416mod size_asserts {
2417 use rustc_data_structures::static_assert_size;
2418
2419 use super::*;
2420 static_assert_size!(Crate, 16); static_assert_size!(DocFragment, 48);
2423 static_assert_size!(GenericArg, 32);
2424 static_assert_size!(GenericArgs, 24);
2425 static_assert_size!(GenericParamDef, 40);
2426 static_assert_size!(Generics, 16);
2427 static_assert_size!(Item, 8);
2428 static_assert_size!(ItemInner, 144);
2429 static_assert_size!(ItemKind, 48);
2430 static_assert_size!(PathSegment, 32);
2431 static_assert_size!(Type, 32);
2432 }