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