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 is_exported_macro(&self) -> bool {
457 match self.kind {
458 ItemKind::MacroItem(..) => find_attr!(&self.attrs.other_attrs, MacroExport { .. }),
459 _ => false,
460 }
461 }
462
463 pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
464 self.item_id
465 .as_def_id()
466 .map(|did| {
467 inner_docs(
468 #[allow(deprecated)]
469 tcx.get_all_attrs(did),
470 )
471 })
472 .unwrap_or(false)
473 }
474
475 pub(crate) fn has_self_param(&self) -> bool {
477 if let ItemKind::MethodItem(box Function { decl, .. }, _) = &self.inner.kind {
478 decl.receiver_type().is_some()
479 } else {
480 false
481 }
482 }
483
484 pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option<Span> {
485 let kind = match &self.kind {
486 ItemKind::StrippedItem(k) => k,
487 _ => &self.kind,
488 };
489 match kind {
490 ItemKind::ModuleItem(Module { span, .. }) => Some(*span),
491 ItemKind::ImplItem(box Impl { kind: ImplKind::Auto, .. }) => None,
492 ItemKind::ImplItem(box Impl { kind: ImplKind::Blanket(_), .. }) => {
493 if let ItemId::Blanket { impl_id, .. } = self.item_id {
494 Some(rustc_span(impl_id, tcx))
495 } else {
496 panic!("blanket impl item has non-blanket ID")
497 }
498 }
499 _ => self.def_id().map(|did| rustc_span(did, tcx)),
500 }
501 }
502
503 pub(crate) fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
504 let deprecation_notes = self
505 .attrs
506 .other_attrs
507 .iter()
508 .filter_map(|attr| attr.deprecation_note().map(|note| note.span));
509
510 span_of_fragments(&self.attrs.doc_strings)
511 .into_iter()
512 .chain(deprecation_notes)
513 .reduce(|a, b| a.to(b))
514 .unwrap_or_else(|| self.span(tcx).map_or(DUMMY_SP, |span| span.inner()))
515 }
516
517 pub(crate) fn doc_value(&self) -> String {
519 self.attrs.doc_value()
520 }
521
522 pub(crate) fn opt_doc_value(&self) -> Option<String> {
526 self.attrs.opt_doc_value()
527 }
528
529 pub(crate) fn from_def_id_and_parts(
530 def_id: DefId,
531 name: Option<Symbol>,
532 kind: ItemKind,
533 tcx: TyCtxt<'_>,
534 ) -> Item {
535 #[allow(deprecated)]
536 let hir_attrs = tcx.get_all_attrs(def_id);
537
538 Self::from_def_id_and_attrs_and_parts(
539 def_id,
540 name,
541 kind,
542 Attributes::from_hir(hir_attrs),
543 None,
544 )
545 }
546
547 pub(crate) fn from_def_id_and_attrs_and_parts(
548 def_id: DefId,
549 name: Option<Symbol>,
550 kind: ItemKind,
551 attrs: Attributes,
552 cfg: Option<Arc<Cfg>>,
553 ) -> Item {
554 trace!("name={name:?}, def_id={def_id:?} cfg={cfg:?}");
555
556 Item {
557 inner: Box::new(ItemInner {
558 item_id: def_id.into(),
559 kind,
560 attrs,
561 stability: None,
562 name,
563 cfg,
564 inline_stmt_id: None,
565 }),
566 }
567 }
568
569 pub(crate) fn item_or_reexport_id(&self) -> ItemId {
575 self.attrs
577 .doc_strings
578 .first()
579 .map(|x| x.item_id)
580 .flatten()
581 .map(ItemId::from)
582 .unwrap_or(self.item_id)
583 }
584
585 pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
586 use crate::html::format::{href, link_tooltip};
587
588 let Some(links) = cx.cache().intra_doc_links.get(&self.item_or_reexport_id()) else {
589 return vec![];
590 };
591 links
592 .iter()
593 .filter_map(|ItemLink { link: s, link_text, page_id: id, fragment }| {
594 debug!(?id);
595 if let Ok(HrefInfo { mut url, .. }) = href(*id, cx) {
596 debug!(?url);
597 match fragment {
598 Some(UrlFragment::Item(def_id)) => {
599 write!(url, "{}", crate::html::format::fragment(*def_id, cx.tcx()))
600 .unwrap();
601 }
602 Some(UrlFragment::UserWritten(raw)) => {
603 url.push('#');
604 url.push_str(raw);
605 }
606 None => {}
607 }
608 Some(RenderedLink {
609 original_text: s.clone(),
610 new_text: link_text.clone(),
611 tooltip: link_tooltip(*id, fragment, cx).to_string(),
612 href: url,
613 })
614 } else {
615 None
616 }
617 })
618 .collect()
619 }
620
621 pub(crate) fn link_names(&self, cache: &Cache) -> Vec<RenderedLink> {
627 let Some(links) = cache.intra_doc_links.get(&self.item_id) else {
628 return vec![];
629 };
630 links
631 .iter()
632 .map(|ItemLink { link: s, link_text, .. }| RenderedLink {
633 original_text: s.clone(),
634 new_text: link_text.clone(),
635 href: String::new(),
636 tooltip: String::new(),
637 })
638 .collect()
639 }
640
641 pub(crate) fn is_crate(&self) -> bool {
642 self.is_mod() && self.def_id().is_some_and(|did| did.is_crate_root())
643 }
644 pub(crate) fn is_mod(&self) -> bool {
645 self.type_() == ItemType::Module
646 }
647 pub(crate) fn is_struct(&self) -> bool {
648 self.type_() == ItemType::Struct
649 }
650 pub(crate) fn is_enum(&self) -> bool {
651 self.type_() == ItemType::Enum
652 }
653 pub(crate) fn is_variant(&self) -> bool {
654 self.type_() == ItemType::Variant
655 }
656 pub(crate) fn is_associated_type(&self) -> bool {
657 matches!(self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..)))
658 }
659 pub(crate) fn is_required_associated_type(&self) -> bool {
660 matches!(self.kind, RequiredAssocTypeItem(..) | StrippedItem(box RequiredAssocTypeItem(..)))
661 }
662 pub(crate) fn is_associated_const(&self) -> bool {
663 matches!(self.kind, ProvidedAssocConstItem(..) | ImplAssocConstItem(..) | StrippedItem(box (ProvidedAssocConstItem(..) | ImplAssocConstItem(..))))
664 }
665 pub(crate) fn is_required_associated_const(&self) -> bool {
666 matches!(self.kind, RequiredAssocConstItem(..) | StrippedItem(box RequiredAssocConstItem(..)))
667 }
668 pub(crate) fn is_method(&self) -> bool {
669 self.type_() == ItemType::Method
670 }
671 pub(crate) fn is_ty_method(&self) -> bool {
672 self.type_() == ItemType::TyMethod
673 }
674 pub(crate) fn is_primitive(&self) -> bool {
675 self.type_() == ItemType::Primitive
676 }
677 pub(crate) fn is_union(&self) -> bool {
678 self.type_() == ItemType::Union
679 }
680 pub(crate) fn is_import(&self) -> bool {
681 self.type_() == ItemType::Import
682 }
683 pub(crate) fn is_extern_crate(&self) -> bool {
684 self.type_() == ItemType::ExternCrate
685 }
686 pub(crate) fn is_keyword(&self) -> bool {
687 self.type_() == ItemType::Keyword
688 }
689 pub(crate) fn is_attribute(&self) -> bool {
690 self.type_() == ItemType::Attribute
691 }
692 pub(crate) fn is_fake_item(&self) -> bool {
701 matches!(self.type_(), ItemType::Primitive | ItemType::Keyword | ItemType::Attribute)
702 }
703 pub(crate) fn is_stripped(&self) -> bool {
704 match self.kind {
705 StrippedItem(..) => true,
706 ImportItem(ref i) => !i.should_be_displayed,
707 _ => false,
708 }
709 }
710 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
711 match self.kind {
712 StructItem(ref struct_) => Some(struct_.has_stripped_entries()),
713 UnionItem(ref union_) => Some(union_.has_stripped_entries()),
714 EnumItem(ref enum_) => Some(enum_.has_stripped_entries()),
715 VariantItem(ref v) => v.has_stripped_entries(),
716 TypeAliasItem(ref type_alias) => {
717 type_alias.inner_type.as_ref().and_then(|t| t.has_stripped_entries())
718 }
719 _ => None,
720 }
721 }
722
723 pub(crate) fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
724 self.stability(tcx).as_ref().and_then(|s| {
725 let mut classes = Vec::with_capacity(2);
726
727 if s.is_unstable() {
728 classes.push("unstable");
729 }
730
731 if self.deprecation(tcx).is_some() {
733 classes.push("deprecated");
734 }
735
736 if !classes.is_empty() { Some(classes.join(" ")) } else { None }
737 })
738 }
739
740 pub(crate) fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<StableSince> {
741 self.stability(tcx).and_then(|stability| stability.stable_since())
742 }
743
744 pub(crate) fn is_non_exhaustive(&self) -> bool {
745 find_attr!(&self.attrs.other_attrs, NonExhaustive(..))
746 }
747
748 pub(crate) fn type_(&self) -> ItemType {
750 ItemType::from(self)
751 }
752
753 pub(crate) fn defaultness(&self) -> Option<Defaultness> {
754 match self.kind {
755 ItemKind::MethodItem(_, defaultness) | ItemKind::RequiredMethodItem(_, defaultness) => {
756 Some(defaultness)
757 }
758 _ => None,
759 }
760 }
761
762 pub(crate) fn fn_header(&self, tcx: TyCtxt<'_>) -> Option<hir::FnHeader> {
764 fn build_fn_header(
765 def_id: DefId,
766 tcx: TyCtxt<'_>,
767 asyncness: ty::Asyncness,
768 ) -> hir::FnHeader {
769 let sig = tcx.fn_sig(def_id).skip_binder();
770 let constness = if tcx.is_const_fn(def_id) {
771 if let Some(assoc) = tcx.opt_associated_item(def_id)
775 && let ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) =
776 assoc.container
777 {
778 hir::Constness::NotConst
779 } else {
780 hir::Constness::Const
781 }
782 } else {
783 hir::Constness::NotConst
784 };
785 let asyncness = match asyncness {
786 ty::Asyncness::Yes => hir::IsAsync::Async(DUMMY_SP),
787 ty::Asyncness::No => hir::IsAsync::NotAsync,
788 };
789 hir::FnHeader {
790 safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
791 hir::HeaderSafety::SafeTargetFeatures
792 } else {
793 sig.safety().into()
794 },
795 abi: sig.abi(),
796 constness,
797 asyncness,
798 }
799 }
800 let header = match self.kind {
801 ItemKind::ForeignFunctionItem(_, safety) => {
802 let def_id = self.def_id().unwrap();
803 let abi = tcx.fn_sig(def_id).skip_binder().abi();
804 hir::FnHeader {
805 safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
806 hir::HeaderSafety::SafeTargetFeatures
807 } else {
808 safety.into()
809 },
810 abi,
811 constness: if tcx.is_const_fn(def_id) {
812 hir::Constness::Const
813 } else {
814 hir::Constness::NotConst
815 },
816 asyncness: hir::IsAsync::NotAsync,
817 }
818 }
819 ItemKind::FunctionItem(_)
820 | ItemKind::MethodItem(..)
821 | ItemKind::RequiredMethodItem(..) => {
822 let def_id = self.def_id().unwrap();
823 build_fn_header(def_id, tcx, tcx.asyncness(def_id))
824 }
825 _ => return None,
826 };
827 Some(header)
828 }
829
830 pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option<Visibility<DefId>> {
833 let def_id = match self.item_id {
834 ItemId::Auto { .. } | ItemId::Blanket { .. } => return None,
836 ItemId::DefId(def_id) => def_id,
837 };
838
839 match self.kind {
840 ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) | ItemKind::AttributeItem => {
844 return Some(Visibility::Public);
845 }
846 StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => {
848 return None;
849 }
850 VariantItem(..) | ImplItem(..) => return None,
852 RequiredAssocConstItem(..)
854 | ProvidedAssocConstItem(..)
855 | ImplAssocConstItem(..)
856 | AssocTypeItem(..)
857 | RequiredAssocTypeItem(..)
858 | RequiredMethodItem(..)
859 | MethodItem(..) => {
860 match tcx.associated_item(def_id).container {
861 ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) => {
864 return None;
865 }
866 ty::AssocContainer::InherentImpl => {}
867 }
868 }
869 _ => {}
870 }
871 let def_id = match self.inline_stmt_id {
872 Some(inlined) => inlined.to_def_id(),
873 None => def_id,
874 };
875 Some(tcx.visibility(def_id))
876 }
877
878 pub fn is_doc_hidden(&self) -> bool {
879 self.attrs.is_doc_hidden()
880 }
881
882 pub fn def_id(&self) -> Option<DefId> {
883 self.item_id.as_def_id()
884 }
885}
886
887#[derive(Clone, Debug)]
888pub(crate) enum ItemKind {
889 ExternCrateItem {
890 src: Option<Symbol>,
892 },
893 ImportItem(Import),
894 StructItem(Struct),
895 UnionItem(Union),
896 EnumItem(Enum),
897 FunctionItem(Box<Function>),
898 ModuleItem(Module),
899 TypeAliasItem(Box<TypeAlias>),
900 StaticItem(Static),
901 TraitItem(Box<Trait>),
902 TraitAliasItem(TraitAlias),
903 ImplItem(Box<Impl>),
904 PlaceholderImplItem,
907 RequiredMethodItem(Box<Function>, Defaultness),
909 MethodItem(Box<Function>, Defaultness),
913 StructFieldItem(Type),
914 VariantItem(Variant),
915 ForeignFunctionItem(Box<Function>, hir::Safety),
917 ForeignStaticItem(Static, hir::Safety),
919 ForeignTypeItem,
921 MacroItem(Macro),
922 ProcMacroItem(ProcMacro),
923 PrimitiveItem(PrimitiveType),
924 RequiredAssocConstItem(Generics, Box<Type>),
926 ConstantItem(Box<Constant>),
927 ProvidedAssocConstItem(Box<Constant>),
929 ImplAssocConstItem(Box<Constant>),
931 RequiredAssocTypeItem(Generics, Vec<GenericBound>),
935 AssocTypeItem(Box<TypeAlias>, Vec<GenericBound>),
937 StrippedItem(Box<ItemKind>),
939 KeywordItem,
942 AttributeItem,
945}
946
947impl ItemKind {
948 pub(crate) fn inner_items(&self) -> impl Iterator<Item = &Item> {
951 match self {
952 StructItem(s) => s.fields.iter(),
953 UnionItem(u) => u.fields.iter(),
954 VariantItem(v) => match &v.kind {
955 VariantKind::CLike => [].iter(),
956 VariantKind::Tuple(t) => t.iter(),
957 VariantKind::Struct(s) => s.fields.iter(),
958 },
959 EnumItem(e) => e.variants.iter(),
960 TraitItem(t) => t.items.iter(),
961 ImplItem(i) => i.items.iter(),
962 ModuleItem(m) => m.items.iter(),
963 ExternCrateItem { .. }
964 | ImportItem(_)
965 | FunctionItem(_)
966 | TypeAliasItem(_)
967 | StaticItem(_)
968 | ConstantItem(_)
969 | TraitAliasItem(_)
970 | RequiredMethodItem(..)
971 | MethodItem(..)
972 | StructFieldItem(_)
973 | ForeignFunctionItem(_, _)
974 | ForeignStaticItem(_, _)
975 | ForeignTypeItem
976 | MacroItem(_)
977 | ProcMacroItem(_)
978 | PrimitiveItem(_)
979 | RequiredAssocConstItem(..)
980 | ProvidedAssocConstItem(..)
981 | ImplAssocConstItem(..)
982 | RequiredAssocTypeItem(..)
983 | AssocTypeItem(..)
984 | StrippedItem(_)
985 | KeywordItem
986 | AttributeItem
987 | PlaceholderImplItem => [].iter(),
988 }
989 }
990}
991
992#[derive(Clone, Debug)]
993pub(crate) struct Module {
994 pub(crate) items: Vec<Item>,
995 pub(crate) span: Span,
996}
997
998#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1002pub(crate) struct ItemLink {
1003 pub(crate) link: Box<str>,
1005 pub(crate) link_text: Box<str>,
1010 pub(crate) page_id: DefId,
1014 pub(crate) fragment: Option<UrlFragment>,
1016}
1017
1018pub struct RenderedLink {
1019 pub(crate) original_text: Box<str>,
1023 pub(crate) new_text: Box<str>,
1025 pub(crate) href: String,
1027 pub(crate) tooltip: String,
1029}
1030
1031#[derive(Clone, Debug, Default)]
1034pub(crate) struct Attributes {
1035 pub(crate) doc_strings: Vec<DocFragment>,
1036 pub(crate) other_attrs: ThinVec<hir::Attribute>,
1037}
1038
1039impl Attributes {
1040 pub(crate) fn has_doc_flag<F: Fn(&DocAttribute) -> bool>(&self, callback: F) -> bool {
1041 find_attr!(&self.other_attrs, Doc(d) if callback(d))
1042 }
1043
1044 pub(crate) fn is_doc_hidden(&self) -> bool {
1045 find_attr!(&self.other_attrs, Doc(d) if d.hidden.is_some())
1046 }
1047
1048 pub(crate) fn from_hir(attrs: &[hir::Attribute]) -> Attributes {
1049 Attributes::from_hir_iter(attrs.iter().map(|attr| (attr, None)), false)
1050 }
1051
1052 pub(crate) fn from_hir_with_additional(
1053 attrs: &[hir::Attribute],
1054 (additional_attrs, def_id): (&[hir::Attribute], DefId),
1055 ) -> Attributes {
1056 let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id)));
1058 let attrs2 = attrs.iter().map(|attr| (attr, None));
1059 Attributes::from_hir_iter(attrs1.chain(attrs2), false)
1060 }
1061
1062 pub(crate) fn from_hir_iter<'a>(
1063 attrs: impl Iterator<Item = (&'a hir::Attribute, Option<DefId>)>,
1064 doc_only: bool,
1065 ) -> Attributes {
1066 let (doc_strings, other_attrs) = attrs_to_doc_fragments(attrs, doc_only);
1067 Attributes { doc_strings, other_attrs }
1068 }
1069
1070 pub(crate) fn doc_value(&self) -> String {
1072 self.opt_doc_value().unwrap_or_default()
1073 }
1074
1075 pub(crate) fn opt_doc_value(&self) -> Option<String> {
1079 (!self.doc_strings.is_empty()).then(|| {
1080 let mut res = String::new();
1081 for frag in &self.doc_strings {
1082 add_doc_fragment(&mut res, frag);
1083 }
1084 res.pop();
1085 res
1086 })
1087 }
1088
1089 pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> {
1090 let mut aliases = FxIndexSet::default();
1091
1092 for attr in &self.other_attrs {
1093 if let Attribute::Parsed(AttributeKind::Doc(d)) = attr {
1094 for (alias, _) in &d.aliases {
1095 aliases.insert(*alias);
1096 }
1097 }
1098 }
1099 aliases.into_iter().collect::<Vec<_>>().into()
1100 }
1101}
1102
1103#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1104pub(crate) enum GenericBound {
1105 TraitBound(PolyTrait, hir::TraitBoundModifiers),
1106 Outlives(Lifetime),
1107 Use(Vec<PreciseCapturingArg>),
1109}
1110
1111impl GenericBound {
1112 pub(crate) fn sized(cx: &mut DocContext<'_>) -> GenericBound {
1113 Self::sized_with(cx, hir::TraitBoundModifiers::NONE)
1114 }
1115
1116 pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1117 Self::sized_with(
1118 cx,
1119 hir::TraitBoundModifiers {
1120 polarity: hir::BoundPolarity::Maybe(DUMMY_SP),
1121 constness: hir::BoundConstness::Never,
1122 },
1123 )
1124 }
1125
1126 fn sized_with(cx: &mut DocContext<'_>, modifiers: hir::TraitBoundModifiers) -> GenericBound {
1127 let did = cx.tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
1128 let empty = ty::Binder::dummy(ty::GenericArgs::empty());
1129 let path = clean_middle_path(cx, did, false, ThinVec::new(), empty);
1130 inline::record_extern_fqn(cx, did, ItemType::Trait);
1131 GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifiers)
1132 }
1133
1134 pub(crate) fn is_trait_bound(&self) -> bool {
1135 matches!(self, Self::TraitBound(..))
1136 }
1137
1138 pub(crate) fn is_sized_bound(&self, tcx: TyCtxt<'_>) -> bool {
1139 self.is_bounded_by_lang_item(tcx, LangItem::Sized)
1140 }
1141
1142 pub(crate) fn is_meta_sized_bound(&self, tcx: TyCtxt<'_>) -> bool {
1143 self.is_bounded_by_lang_item(tcx, LangItem::MetaSized)
1144 }
1145
1146 fn is_bounded_by_lang_item(&self, tcx: TyCtxt<'_>, lang_item: LangItem) -> bool {
1147 if let GenericBound::TraitBound(
1148 PolyTrait { ref trait_, .. },
1149 rustc_hir::TraitBoundModifiers::NONE,
1150 ) = *self
1151 && tcx.is_lang_item(trait_.def_id(), lang_item)
1152 {
1153 return true;
1154 }
1155 false
1156 }
1157
1158 pub(crate) fn get_trait_path(&self) -> Option<Path> {
1159 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1160 Some(trait_.clone())
1161 } else {
1162 None
1163 }
1164 }
1165}
1166
1167#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1168pub(crate) struct Lifetime(pub Symbol);
1169
1170impl Lifetime {
1171 pub(crate) fn statik() -> Lifetime {
1172 Lifetime(kw::StaticLifetime)
1173 }
1174
1175 pub(crate) fn elided() -> Lifetime {
1176 Lifetime(kw::UnderscoreLifetime)
1177 }
1178}
1179
1180#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1181pub(crate) enum PreciseCapturingArg {
1182 Lifetime(Lifetime),
1183 Param(Symbol),
1184}
1185
1186impl PreciseCapturingArg {
1187 pub(crate) fn name(self) -> Symbol {
1188 match self {
1189 PreciseCapturingArg::Lifetime(lt) => lt.0,
1190 PreciseCapturingArg::Param(param) => param,
1191 }
1192 }
1193}
1194
1195#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1196pub(crate) enum WherePredicate {
1197 BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
1198 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1199 EqPredicate { lhs: QPathData, rhs: Term },
1200}
1201
1202impl WherePredicate {
1203 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1204 match self {
1205 WherePredicate::BoundPredicate { bounds, .. } => Some(bounds),
1206 WherePredicate::RegionPredicate { bounds, .. } => Some(bounds),
1207 _ => None,
1208 }
1209 }
1210}
1211
1212#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1213pub(crate) enum GenericParamDefKind {
1214 Lifetime { outlives: ThinVec<Lifetime> },
1215 Type { bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
1216 Const { ty: Box<Type>, default: Option<Box<String>> },
1218}
1219
1220impl GenericParamDefKind {
1221 pub(crate) fn is_type(&self) -> bool {
1222 matches!(self, GenericParamDefKind::Type { .. })
1223 }
1224}
1225
1226#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1227pub(crate) struct GenericParamDef {
1228 pub(crate) name: Symbol,
1229 pub(crate) def_id: DefId,
1230 pub(crate) kind: GenericParamDefKind,
1231}
1232
1233impl GenericParamDef {
1234 pub(crate) fn lifetime(def_id: DefId, name: Symbol) -> Self {
1235 Self { name, def_id, kind: GenericParamDefKind::Lifetime { outlives: ThinVec::new() } }
1236 }
1237
1238 pub(crate) fn is_synthetic_param(&self) -> bool {
1239 match self.kind {
1240 GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
1241 GenericParamDefKind::Type { synthetic, .. } => synthetic,
1242 }
1243 }
1244
1245 pub(crate) fn is_type(&self) -> bool {
1246 self.kind.is_type()
1247 }
1248
1249 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1250 match self.kind {
1251 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1252 _ => None,
1253 }
1254 }
1255}
1256
1257#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
1259pub(crate) struct Generics {
1260 pub(crate) params: ThinVec<GenericParamDef>,
1261 pub(crate) where_predicates: ThinVec<WherePredicate>,
1262}
1263
1264impl Generics {
1265 pub(crate) fn is_empty(&self) -> bool {
1266 self.params.is_empty() && self.where_predicates.is_empty()
1267 }
1268}
1269
1270#[derive(Clone, Debug)]
1271pub(crate) struct Function {
1272 pub(crate) decl: FnDecl,
1273 pub(crate) generics: Generics,
1274}
1275
1276#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1277pub(crate) struct FnDecl {
1278 pub(crate) inputs: Vec<Parameter>,
1279 pub(crate) output: Type,
1280 pub(crate) c_variadic: bool,
1281}
1282
1283impl FnDecl {
1284 pub(crate) fn receiver_type(&self) -> Option<&Type> {
1285 self.inputs.first().and_then(|v| v.to_receiver())
1286 }
1287}
1288
1289#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1291pub(crate) struct Parameter {
1292 pub(crate) name: Option<Symbol>,
1293 pub(crate) type_: Type,
1294 pub(crate) is_const: bool,
1297}
1298
1299impl Parameter {
1300 pub(crate) fn to_receiver(&self) -> Option<&Type> {
1301 if self.name == Some(kw::SelfLower) { Some(&self.type_) } else { None }
1302 }
1303}
1304
1305#[derive(Clone, Debug)]
1306pub(crate) struct Trait {
1307 pub(crate) def_id: DefId,
1308 pub(crate) items: Vec<Item>,
1309 pub(crate) generics: Generics,
1310 pub(crate) bounds: Vec<GenericBound>,
1311}
1312
1313impl Trait {
1314 pub(crate) fn is_auto(&self, tcx: TyCtxt<'_>) -> bool {
1315 tcx.trait_is_auto(self.def_id)
1316 }
1317 pub(crate) fn is_notable_trait(&self, tcx: TyCtxt<'_>) -> bool {
1318 tcx.is_doc_notable_trait(self.def_id)
1319 }
1320 pub(crate) fn safety(&self, tcx: TyCtxt<'_>) -> hir::Safety {
1321 tcx.trait_def(self.def_id).safety
1322 }
1323 pub(crate) fn is_dyn_compatible(&self, tcx: TyCtxt<'_>) -> bool {
1324 tcx.is_dyn_compatible(self.def_id)
1325 }
1326 pub(crate) fn is_deprecated(&self, tcx: TyCtxt<'_>) -> bool {
1327 tcx.lookup_deprecation(self.def_id).is_some_and(|deprecation| deprecation.is_in_effect())
1328 }
1329}
1330
1331#[derive(Clone, Debug)]
1332pub(crate) struct TraitAlias {
1333 pub(crate) generics: Generics,
1334 pub(crate) bounds: Vec<GenericBound>,
1335}
1336
1337#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1339pub(crate) struct PolyTrait {
1340 pub(crate) trait_: Path,
1341 pub(crate) generic_params: Vec<GenericParamDef>,
1342}
1343
1344#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1346pub(crate) enum Type {
1347 Path {
1352 path: Path,
1353 },
1354 DynTrait(Vec<PolyTrait>, Option<Lifetime>),
1356 Generic(Symbol),
1358 SelfTy,
1360 Primitive(PrimitiveType),
1362 BareFunction(Box<BareFunctionDecl>),
1364 Tuple(Vec<Type>),
1366 Slice(Box<Type>),
1368 Array(Box<Type>, Box<str>),
1372 Pat(Box<Type>, Box<str>),
1373 FieldOf(Box<Type>, Box<str>),
1374 RawPointer(Mutability, Box<Type>),
1376 BorrowedRef {
1378 lifetime: Option<Lifetime>,
1379 mutability: Mutability,
1380 type_: Box<Type>,
1381 },
1382
1383 QPath(Box<QPathData>),
1385
1386 Infer,
1388
1389 ImplTrait(Vec<GenericBound>),
1391
1392 UnsafeBinder(Box<UnsafeBinderTy>),
1393}
1394
1395impl Type {
1396 pub(crate) fn without_borrowed_ref(&self) -> &Type {
1398 let mut result = self;
1399 while let Type::BorrowedRef { type_, .. } = result {
1400 result = type_;
1401 }
1402 result
1403 }
1404
1405 pub(crate) fn is_borrowed_ref(&self) -> bool {
1406 matches!(self, Type::BorrowedRef { .. })
1407 }
1408
1409 fn is_type_alias(&self) -> bool {
1410 matches!(self, Type::Path { path: Path { res: Res::Def(DefKind::TyAlias, _), .. } })
1411 }
1412
1413 pub(crate) fn is_doc_subtype_of(&self, other: &Self, cache: &Cache) -> bool {
1434 let (self_cleared, other_cleared) = if !self.is_borrowed_ref() || !other.is_borrowed_ref() {
1437 (self.without_borrowed_ref(), other.without_borrowed_ref())
1438 } else {
1439 (self, other)
1440 };
1441
1442 if self_cleared.is_type_alias() || other_cleared.is_type_alias() {
1448 return true;
1449 }
1450
1451 match (self_cleared, other_cleared) {
1452 (Type::Tuple(a), Type::Tuple(b)) => {
1454 a.iter().eq_by(b, |a, b| a.is_doc_subtype_of(b, cache))
1455 }
1456 (Type::Slice(a), Type::Slice(b)) => a.is_doc_subtype_of(b, cache),
1457 (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_doc_subtype_of(b, cache),
1458 (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
1459 mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache)
1460 }
1461 (
1462 Type::BorrowedRef { mutability, type_, .. },
1463 Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
1464 ) => mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache),
1465 (Type::Infer, _) | (_, Type::Infer) => true,
1467 (_, Type::Generic(_)) => true,
1470 (Type::Generic(_), _) => false,
1471 (Type::SelfTy, Type::SelfTy) => true,
1473 (Type::Path { path: a }, Type::Path { path: b }) => {
1475 a.def_id() == b.def_id()
1476 && a.generics()
1477 .zip(b.generics())
1478 .map(|(ag, bg)| ag.zip(bg).all(|(at, bt)| at.is_doc_subtype_of(bt, cache)))
1479 .unwrap_or(true)
1480 }
1481 (a, b) => a
1483 .def_id(cache)
1484 .and_then(|a| Some((a, b.def_id(cache)?)))
1485 .map(|(a, b)| a == b)
1486 .unwrap_or(false),
1487 }
1488 }
1489
1490 pub(crate) fn primitive_type(&self) -> Option<PrimitiveType> {
1491 match *self {
1492 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1493 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1494 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1495 Tuple(ref tys) => {
1496 if tys.is_empty() {
1497 Some(PrimitiveType::Unit)
1498 } else {
1499 Some(PrimitiveType::Tuple)
1500 }
1501 }
1502 RawPointer(..) => Some(PrimitiveType::RawPointer),
1503 BareFunction(..) => Some(PrimitiveType::Fn),
1504 _ => None,
1505 }
1506 }
1507
1508 pub(crate) fn sugared_async_return_type(self) -> Type {
1518 if let Type::ImplTrait(mut v) = self
1519 && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = v.pop()
1520 && let Some(segment) = trait_.segments.pop()
1521 && let GenericArgs::AngleBracketed { mut constraints, .. } = segment.args
1522 && let Some(constraint) = constraints.pop()
1523 && let AssocItemConstraintKind::Equality { term } = constraint.kind
1524 && let Term::Type(ty) = term
1525 {
1526 ty
1527 } else {
1528 panic!("unexpected async fn return type")
1529 }
1530 }
1531
1532 pub(crate) fn is_assoc_ty(&self) -> bool {
1534 match self {
1535 Type::Path { path, .. } => path.is_assoc_ty(),
1536 _ => false,
1537 }
1538 }
1539
1540 pub(crate) fn is_self_type(&self) -> bool {
1541 matches!(*self, Type::SelfTy)
1542 }
1543
1544 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
1545 match self {
1546 Type::Path { path, .. } => path.generic_args(),
1547 _ => None,
1548 }
1549 }
1550
1551 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
1552 match self {
1553 Type::Path { path, .. } => path.generics(),
1554 _ => None,
1555 }
1556 }
1557
1558 pub(crate) fn is_full_generic(&self) -> bool {
1559 matches!(self, Type::Generic(_))
1560 }
1561
1562 pub(crate) fn is_unit(&self) -> bool {
1563 matches!(self, Type::Tuple(v) if v.is_empty())
1564 }
1565
1566 pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
1570 let t: PrimitiveType = match self {
1571 Type::Path { path } => return Some(path.def_id()),
1572 DynTrait(bounds, _) => return bounds.first().map(|b| b.trait_.def_id()),
1573 Primitive(p) => return cache.primitive_locations.get(p).cloned(),
1574 BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
1575 BorrowedRef { type_, .. } => return type_.def_id(cache),
1576 Tuple(tys) => {
1577 if tys.is_empty() {
1578 PrimitiveType::Unit
1579 } else {
1580 PrimitiveType::Tuple
1581 }
1582 }
1583 BareFunction(..) => PrimitiveType::Fn,
1584 Slice(..) => PrimitiveType::Slice,
1585 Array(..) => PrimitiveType::Array,
1586 Type::Pat(..) => PrimitiveType::Pat,
1587 Type::FieldOf(..) => PrimitiveType::FieldOf,
1588 RawPointer(..) => PrimitiveType::RawPointer,
1589 QPath(box QPathData { self_type, .. }) => return self_type.def_id(cache),
1590 Generic(_) | SelfTy | Infer | ImplTrait(_) | UnsafeBinder(_) => return None,
1591 };
1592 Primitive(t).def_id(cache)
1593 }
1594}
1595
1596#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1597pub(crate) struct QPathData {
1598 pub assoc: PathSegment,
1599 pub self_type: Type,
1600 pub should_fully_qualify: bool,
1602 pub trait_: Option<Path>,
1603}
1604
1605#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1612pub(crate) enum PrimitiveType {
1613 Isize,
1614 I8,
1615 I16,
1616 I32,
1617 I64,
1618 I128,
1619 Usize,
1620 U8,
1621 U16,
1622 U32,
1623 U64,
1624 U128,
1625 F16,
1626 F32,
1627 F64,
1628 F128,
1629 Char,
1630 Bool,
1631 Str,
1632 Slice,
1633 Array,
1634 Pat,
1635 FieldOf,
1636 Tuple,
1637 Unit,
1638 RawPointer,
1639 Reference,
1640 Fn,
1641 Never,
1642}
1643
1644type SimplifiedTypes = FxIndexMap<PrimitiveType, ArrayVec<SimplifiedType, 3>>;
1645impl PrimitiveType {
1646 pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1647 use ast::{FloatTy, IntTy, UintTy};
1648 match prim {
1649 hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1650 hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1651 hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1652 hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1653 hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1654 hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1655 hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1656 hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1657 hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1658 hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1659 hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1660 hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1661 hir::PrimTy::Float(FloatTy::F16) => PrimitiveType::F16,
1662 hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1663 hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1664 hir::PrimTy::Float(FloatTy::F128) => PrimitiveType::F128,
1665 hir::PrimTy::Str => PrimitiveType::Str,
1666 hir::PrimTy::Bool => PrimitiveType::Bool,
1667 hir::PrimTy::Char => PrimitiveType::Char,
1668 }
1669 }
1670
1671 pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1672 match s {
1673 sym::isize => Some(PrimitiveType::Isize),
1674 sym::i8 => Some(PrimitiveType::I8),
1675 sym::i16 => Some(PrimitiveType::I16),
1676 sym::i32 => Some(PrimitiveType::I32),
1677 sym::i64 => Some(PrimitiveType::I64),
1678 sym::i128 => Some(PrimitiveType::I128),
1679 sym::usize => Some(PrimitiveType::Usize),
1680 sym::u8 => Some(PrimitiveType::U8),
1681 sym::u16 => Some(PrimitiveType::U16),
1682 sym::u32 => Some(PrimitiveType::U32),
1683 sym::u64 => Some(PrimitiveType::U64),
1684 sym::u128 => Some(PrimitiveType::U128),
1685 sym::bool => Some(PrimitiveType::Bool),
1686 sym::char => Some(PrimitiveType::Char),
1687 sym::str => Some(PrimitiveType::Str),
1688 sym::f16 => Some(PrimitiveType::F16),
1689 sym::f32 => Some(PrimitiveType::F32),
1690 sym::f64 => Some(PrimitiveType::F64),
1691 sym::f128 => Some(PrimitiveType::F128),
1692 sym::array => Some(PrimitiveType::Array),
1693 sym::slice => Some(PrimitiveType::Slice),
1694 sym::tuple => Some(PrimitiveType::Tuple),
1695 sym::unit => Some(PrimitiveType::Unit),
1696 sym::pointer => Some(PrimitiveType::RawPointer),
1697 sym::reference => Some(PrimitiveType::Reference),
1698 kw::Fn => Some(PrimitiveType::Fn),
1699 sym::never => Some(PrimitiveType::Never),
1700 _ => None,
1701 }
1702 }
1703
1704 pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
1705 use PrimitiveType::*;
1706 use ty::{FloatTy, IntTy, UintTy};
1707 static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
1708
1709 let single = |x| iter::once(x).collect();
1710 CELL.get_or_init(move || {
1711 map! {
1712 Isize => single(SimplifiedType::Int(IntTy::Isize)),
1713 I8 => single(SimplifiedType::Int(IntTy::I8)),
1714 I16 => single(SimplifiedType::Int(IntTy::I16)),
1715 I32 => single(SimplifiedType::Int(IntTy::I32)),
1716 I64 => single(SimplifiedType::Int(IntTy::I64)),
1717 I128 => single(SimplifiedType::Int(IntTy::I128)),
1718 Usize => single(SimplifiedType::Uint(UintTy::Usize)),
1719 U8 => single(SimplifiedType::Uint(UintTy::U8)),
1720 U16 => single(SimplifiedType::Uint(UintTy::U16)),
1721 U32 => single(SimplifiedType::Uint(UintTy::U32)),
1722 U64 => single(SimplifiedType::Uint(UintTy::U64)),
1723 U128 => single(SimplifiedType::Uint(UintTy::U128)),
1724 F16 => single(SimplifiedType::Float(FloatTy::F16)),
1725 F32 => single(SimplifiedType::Float(FloatTy::F32)),
1726 F64 => single(SimplifiedType::Float(FloatTy::F64)),
1727 F128 => single(SimplifiedType::Float(FloatTy::F128)),
1728 Str => single(SimplifiedType::Str),
1729 Bool => single(SimplifiedType::Bool),
1730 Char => single(SimplifiedType::Char),
1731 Array => single(SimplifiedType::Array),
1732 Slice => single(SimplifiedType::Slice),
1733 Tuple => [SimplifiedType::Tuple(1), SimplifiedType::Tuple(2), SimplifiedType::Tuple(3)].into(),
1739 Unit => single(SimplifiedType::Tuple(0)),
1740 RawPointer => [SimplifiedType::Ptr(Mutability::Not), SimplifiedType::Ptr(Mutability::Mut)].into_iter().collect(),
1741 Reference => [SimplifiedType::Ref(Mutability::Not), SimplifiedType::Ref(Mutability::Mut)].into_iter().collect(),
1742 Fn => single(SimplifiedType::Function(1)),
1745 Never => single(SimplifiedType::Never),
1746 }
1747 })
1748 }
1749
1750 pub(crate) fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = DefId> + 'tcx {
1751 Self::simplified_types()
1752 .get(self)
1753 .into_iter()
1754 .flatten()
1755 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1756 .copied()
1757 }
1758
1759 pub(crate) fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> {
1760 Self::simplified_types()
1761 .values()
1762 .flatten()
1763 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1764 .copied()
1765 }
1766
1767 pub(crate) fn as_sym(&self) -> Symbol {
1768 use PrimitiveType::*;
1769 match self {
1770 Isize => sym::isize,
1771 I8 => sym::i8,
1772 I16 => sym::i16,
1773 I32 => sym::i32,
1774 I64 => sym::i64,
1775 I128 => sym::i128,
1776 Usize => sym::usize,
1777 U8 => sym::u8,
1778 U16 => sym::u16,
1779 U32 => sym::u32,
1780 U64 => sym::u64,
1781 U128 => sym::u128,
1782 F16 => sym::f16,
1783 F32 => sym::f32,
1784 F64 => sym::f64,
1785 F128 => sym::f128,
1786 Str => sym::str,
1787 Bool => sym::bool,
1788 Char => sym::char,
1789 Array => sym::array,
1790 Pat => sym::pat,
1791 FieldOf => sym::field_of,
1792 Slice => sym::slice,
1793 Tuple => sym::tuple,
1794 Unit => sym::unit,
1795 RawPointer => sym::pointer,
1796 Reference => sym::reference,
1797 Fn => kw::Fn,
1798 Never => sym::never,
1799 }
1800 }
1801
1802 pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxIndexMap<PrimitiveType, DefId> {
1814 static PRIMITIVE_LOCATIONS: OnceCell<FxIndexMap<PrimitiveType, DefId>> = OnceCell::new();
1815 PRIMITIVE_LOCATIONS.get_or_init(|| {
1816 let mut primitive_locations = FxIndexMap::default();
1817 for &crate_num in tcx.crates(()) {
1820 let e = ExternalCrate { crate_num };
1821 let crate_name = e.name(tcx);
1822 debug!(?crate_num, ?crate_name);
1823 for (def_id, prim) in e.primitives(tcx) {
1824 if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1826 continue;
1827 }
1828 primitive_locations.insert(prim, def_id);
1829 }
1830 }
1831 let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1832 for (def_id, prim) in local_primitives {
1833 primitive_locations.insert(prim, def_id);
1834 }
1835 primitive_locations
1836 })
1837 }
1838}
1839
1840impl From<ty::IntTy> for PrimitiveType {
1841 fn from(int_ty: ty::IntTy) -> PrimitiveType {
1842 match int_ty {
1843 ty::IntTy::Isize => PrimitiveType::Isize,
1844 ty::IntTy::I8 => PrimitiveType::I8,
1845 ty::IntTy::I16 => PrimitiveType::I16,
1846 ty::IntTy::I32 => PrimitiveType::I32,
1847 ty::IntTy::I64 => PrimitiveType::I64,
1848 ty::IntTy::I128 => PrimitiveType::I128,
1849 }
1850 }
1851}
1852
1853impl From<ty::UintTy> for PrimitiveType {
1854 fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1855 match uint_ty {
1856 ty::UintTy::Usize => PrimitiveType::Usize,
1857 ty::UintTy::U8 => PrimitiveType::U8,
1858 ty::UintTy::U16 => PrimitiveType::U16,
1859 ty::UintTy::U32 => PrimitiveType::U32,
1860 ty::UintTy::U64 => PrimitiveType::U64,
1861 ty::UintTy::U128 => PrimitiveType::U128,
1862 }
1863 }
1864}
1865
1866impl From<ty::FloatTy> for PrimitiveType {
1867 fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1868 match float_ty {
1869 ty::FloatTy::F16 => PrimitiveType::F16,
1870 ty::FloatTy::F32 => PrimitiveType::F32,
1871 ty::FloatTy::F64 => PrimitiveType::F64,
1872 ty::FloatTy::F128 => PrimitiveType::F128,
1873 }
1874 }
1875}
1876
1877impl From<hir::PrimTy> for PrimitiveType {
1878 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1879 match prim_ty {
1880 hir::PrimTy::Int(int_ty) => int_ty.into(),
1881 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1882 hir::PrimTy::Float(float_ty) => float_ty.into(),
1883 hir::PrimTy::Str => PrimitiveType::Str,
1884 hir::PrimTy::Bool => PrimitiveType::Bool,
1885 hir::PrimTy::Char => PrimitiveType::Char,
1886 }
1887 }
1888}
1889
1890#[derive(Clone, Debug)]
1891pub(crate) struct Struct {
1892 pub(crate) ctor_kind: Option<CtorKind>,
1893 pub(crate) generics: Generics,
1894 pub(crate) fields: ThinVec<Item>,
1895}
1896
1897impl Struct {
1898 pub(crate) fn has_stripped_entries(&self) -> bool {
1899 self.fields.iter().any(|f| f.is_stripped())
1900 }
1901}
1902
1903#[derive(Clone, Debug)]
1904pub(crate) struct Union {
1905 pub(crate) generics: Generics,
1906 pub(crate) fields: Vec<Item>,
1907}
1908
1909impl Union {
1910 pub(crate) fn has_stripped_entries(&self) -> bool {
1911 self.fields.iter().any(|f| f.is_stripped())
1912 }
1913}
1914
1915#[derive(Clone, Debug)]
1919pub(crate) struct VariantStruct {
1920 pub(crate) fields: ThinVec<Item>,
1921}
1922
1923impl VariantStruct {
1924 pub(crate) fn has_stripped_entries(&self) -> bool {
1925 self.fields.iter().any(|f| f.is_stripped())
1926 }
1927}
1928
1929#[derive(Clone, Debug)]
1930pub(crate) struct Enum {
1931 pub(crate) variants: IndexVec<VariantIdx, Item>,
1932 pub(crate) generics: Generics,
1933}
1934
1935impl Enum {
1936 pub(crate) fn has_stripped_entries(&self) -> bool {
1937 self.variants.iter().any(|f| f.is_stripped())
1938 }
1939
1940 pub(crate) fn non_stripped_variants(&self) -> impl Iterator<Item = &Item> {
1941 self.variants.iter().filter(|v| !v.is_stripped())
1942 }
1943}
1944
1945#[derive(Clone, Debug)]
1946pub(crate) struct Variant {
1947 pub kind: VariantKind,
1948 pub discriminant: Option<Discriminant>,
1949}
1950
1951#[derive(Clone, Debug)]
1952pub(crate) enum VariantKind {
1953 CLike,
1954 Tuple(ThinVec<Item>),
1955 Struct(VariantStruct),
1956}
1957
1958impl Variant {
1959 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
1960 match &self.kind {
1961 VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()),
1962 VariantKind::CLike | VariantKind::Tuple(_) => None,
1963 }
1964 }
1965}
1966
1967#[derive(Clone, Debug)]
1968pub(crate) struct Discriminant {
1969 pub(super) expr: Option<BodyId>,
1972 pub(super) value: DefId,
1973}
1974
1975impl Discriminant {
1976 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
1979 self.expr
1980 .map(|body| rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body)))
1981 }
1982 pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String {
1983 print_evaluated_const(tcx, self.value, with_underscores, false).unwrap()
1984 }
1985}
1986
1987#[derive(Copy, Clone, Debug)]
1990pub(crate) struct Span(rustc_span::Span);
1991
1992impl Span {
1993 pub(crate) fn new(sp: rustc_span::Span) -> Self {
1998 Self(sp.source_callsite())
1999 }
2000
2001 pub(crate) fn inner(&self) -> rustc_span::Span {
2002 self.0
2003 }
2004
2005 pub(crate) fn filename(&self, sess: &Session) -> FileName {
2006 sess.source_map().span_to_filename(self.0)
2007 }
2008
2009 pub(crate) fn lo(&self, sess: &Session) -> Loc {
2010 sess.source_map().lookup_char_pos(self.0.lo())
2011 }
2012
2013 pub(crate) fn hi(&self, sess: &Session) -> Loc {
2014 sess.source_map().lookup_char_pos(self.0.hi())
2015 }
2016
2017 pub(crate) fn cnum(&self, sess: &Session) -> CrateNum {
2018 self.lo(sess).file.cnum
2020 }
2021}
2022
2023#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2024pub(crate) struct Path {
2025 pub(crate) res: Res,
2026 pub(crate) segments: ThinVec<PathSegment>,
2027}
2028
2029impl Path {
2030 pub(crate) fn def_id(&self) -> DefId {
2031 self.res.def_id()
2032 }
2033
2034 pub(crate) fn last_opt(&self) -> Option<Symbol> {
2035 self.segments.last().map(|s| s.name)
2036 }
2037
2038 pub(crate) fn last(&self) -> Symbol {
2039 self.last_opt().expect("segments were empty")
2040 }
2041
2042 pub(crate) fn whole_name(&self) -> String {
2043 self.segments
2044 .iter()
2045 .map(|s| if s.name == kw::PathRoot { "" } else { s.name.as_str() })
2046 .intersperse("::")
2047 .collect()
2048 }
2049
2050 pub(crate) fn is_assoc_ty(&self) -> bool {
2052 match self.res {
2053 Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _)
2054 if self.segments.len() != 1 =>
2055 {
2056 true
2057 }
2058 Res::Def(DefKind::AssocTy, _) => true,
2059 _ => false,
2060 }
2061 }
2062
2063 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
2064 self.segments.last().map(|seg| &seg.args)
2065 }
2066
2067 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
2068 self.segments.last().and_then(|seg| {
2069 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2070 Some(args.iter().filter_map(|arg| match arg {
2071 GenericArg::Type(ty) => Some(ty),
2072 _ => None,
2073 }))
2074 } else {
2075 None
2076 }
2077 })
2078 }
2079}
2080
2081#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2082pub(crate) enum GenericArg {
2083 Lifetime(Lifetime),
2084 Type(Type),
2085 Const(Box<ConstantKind>),
2086 Infer,
2087}
2088
2089impl GenericArg {
2090 pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
2091 if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2092 }
2093
2094 pub(crate) fn as_ty(&self) -> Option<&Type> {
2095 if let Self::Type(ty) = self { Some(ty) } else { None }
2096 }
2097}
2098
2099#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2100pub(crate) enum GenericArgs {
2101 AngleBracketed { args: ThinVec<GenericArg>, constraints: ThinVec<AssocItemConstraint> },
2103 Parenthesized { inputs: ThinVec<Type>, output: Option<Box<Type>> },
2105 ReturnTypeNotation,
2107}
2108
2109impl GenericArgs {
2110 pub(crate) fn is_empty(&self) -> bool {
2111 match self {
2112 GenericArgs::AngleBracketed { args, constraints } => {
2113 args.is_empty() && constraints.is_empty()
2114 }
2115 GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
2116 GenericArgs::ReturnTypeNotation => false,
2117 }
2118 }
2119 pub(crate) fn constraints(&self) -> Box<dyn Iterator<Item = AssocItemConstraint> + '_> {
2120 match self {
2121 GenericArgs::AngleBracketed { constraints, .. } => {
2122 Box::new(constraints.iter().cloned())
2123 }
2124 GenericArgs::Parenthesized { output, .. } => Box::new(
2125 output
2126 .as_ref()
2127 .map(|ty| AssocItemConstraint {
2128 assoc: PathSegment {
2129 name: sym::Output,
2130 args: GenericArgs::AngleBracketed {
2131 args: ThinVec::new(),
2132 constraints: ThinVec::new(),
2133 },
2134 },
2135 kind: AssocItemConstraintKind::Equality {
2136 term: Term::Type((**ty).clone()),
2137 },
2138 })
2139 .into_iter(),
2140 ),
2141 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2142 }
2143 }
2144}
2145
2146impl<'a> IntoIterator for &'a GenericArgs {
2147 type IntoIter = Box<dyn Iterator<Item = GenericArg> + 'a>;
2148 type Item = GenericArg;
2149 fn into_iter(self) -> Self::IntoIter {
2150 match self {
2151 GenericArgs::AngleBracketed { args, .. } => Box::new(args.iter().cloned()),
2152 GenericArgs::Parenthesized { inputs, .. } => {
2153 Box::new(inputs.iter().cloned().map(GenericArg::Type))
2155 }
2156 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2157 }
2158 }
2159}
2160
2161#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2162pub(crate) struct PathSegment {
2163 pub(crate) name: Symbol,
2164 pub(crate) args: GenericArgs,
2165}
2166
2167#[derive(Clone, Debug)]
2168pub(crate) enum TypeAliasInnerType {
2169 Enum { variants: IndexVec<VariantIdx, Item>, is_non_exhaustive: bool },
2170 Union { fields: Vec<Item> },
2171 Struct { ctor_kind: Option<CtorKind>, fields: Vec<Item> },
2172}
2173
2174impl TypeAliasInnerType {
2175 fn has_stripped_entries(&self) -> Option<bool> {
2176 Some(match self {
2177 Self::Enum { variants, .. } => variants.iter().any(|v| v.is_stripped()),
2178 Self::Union { fields } | Self::Struct { fields, .. } => {
2179 fields.iter().any(|f| f.is_stripped())
2180 }
2181 })
2182 }
2183}
2184
2185#[derive(Clone, Debug)]
2186pub(crate) struct TypeAlias {
2187 pub(crate) type_: Type,
2188 pub(crate) generics: Generics,
2189 pub(crate) inner_type: Option<TypeAliasInnerType>,
2192 pub(crate) item_type: Option<Type>,
2199}
2200
2201#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2202pub(crate) struct BareFunctionDecl {
2203 pub(crate) safety: hir::Safety,
2204 pub(crate) generic_params: Vec<GenericParamDef>,
2205 pub(crate) decl: FnDecl,
2206 pub(crate) abi: ExternAbi,
2207}
2208
2209#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2210pub(crate) struct UnsafeBinderTy {
2211 pub(crate) generic_params: Vec<GenericParamDef>,
2212 pub(crate) ty: Type,
2213}
2214
2215#[derive(Clone, Debug)]
2216pub(crate) struct Static {
2217 pub(crate) type_: Box<Type>,
2218 pub(crate) mutability: Mutability,
2219 pub(crate) expr: Option<BodyId>,
2220}
2221
2222#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2223pub(crate) struct Constant {
2224 pub(crate) generics: Generics,
2225 pub(crate) kind: ConstantKind,
2226 pub(crate) type_: Type,
2227}
2228
2229#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2230pub(crate) enum Term {
2231 Type(Type),
2232 Constant(ConstantKind),
2233}
2234
2235impl Term {
2236 pub(crate) fn ty(&self) -> Option<&Type> {
2237 if let Term::Type(ty) = self { Some(ty) } else { None }
2238 }
2239}
2240
2241impl From<Type> for Term {
2242 fn from(ty: Type) -> Self {
2243 Term::Type(ty)
2244 }
2245}
2246
2247#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2248pub(crate) enum ConstantKind {
2249 TyConst { expr: Box<str> },
2255 Path { path: Box<str> },
2258 Anonymous { body: BodyId },
2262 Extern { def_id: DefId },
2264 Local { def_id: DefId, body: BodyId },
2266 Infer,
2268}
2269
2270impl ConstantKind {
2271 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2272 match *self {
2273 ConstantKind::TyConst { ref expr } => expr.to_string(),
2274 ConstantKind::Path { ref path } => path.to_string(),
2275 ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2276 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2277 rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body))
2278 }
2279 ConstantKind::Infer => "_".to_string(),
2280 }
2281 }
2282
2283 pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2284 match *self {
2285 ConstantKind::TyConst { .. }
2286 | ConstantKind::Path { .. }
2287 | ConstantKind::Anonymous { .. }
2288 | ConstantKind::Infer => None,
2289 ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2290 print_evaluated_const(tcx, def_id, true, true)
2291 }
2292 }
2293 }
2294
2295 pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2296 match *self {
2297 ConstantKind::TyConst { .. }
2298 | ConstantKind::Extern { .. }
2299 | ConstantKind::Path { .. }
2300 | ConstantKind::Infer => false,
2301 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2302 is_literal_expr(tcx, body.hir_id)
2303 }
2304 }
2305 }
2306}
2307
2308#[derive(Clone, Debug)]
2309pub(crate) struct Impl {
2310 pub(crate) safety: hir::Safety,
2311 pub(crate) generics: Generics,
2312 pub(crate) trait_: Option<Path>,
2313 pub(crate) for_: Type,
2314 pub(crate) items: Vec<Item>,
2315 pub(crate) polarity: ty::ImplPolarity,
2316 pub(crate) kind: ImplKind,
2317 pub(crate) is_deprecated: bool,
2318}
2319
2320impl Impl {
2321 pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxIndexSet<Symbol> {
2322 self.trait_
2323 .as_ref()
2324 .map(|t| t.def_id())
2325 .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name()).collect())
2326 .unwrap_or_default()
2327 }
2328
2329 pub(crate) fn is_negative_trait_impl(&self) -> bool {
2330 matches!(self.polarity, ty::ImplPolarity::Negative)
2331 }
2332}
2333
2334#[derive(Clone, Debug)]
2335pub(crate) enum ImplKind {
2336 Normal,
2337 Auto,
2338 FakeVariadic,
2339 Blanket(Box<Type>),
2340}
2341
2342impl ImplKind {
2343 pub(crate) fn is_auto(&self) -> bool {
2344 matches!(self, ImplKind::Auto)
2345 }
2346
2347 pub(crate) fn is_blanket(&self) -> bool {
2348 matches!(self, ImplKind::Blanket(_))
2349 }
2350
2351 pub(crate) fn is_fake_variadic(&self) -> bool {
2352 matches!(self, ImplKind::FakeVariadic)
2353 }
2354
2355 pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
2356 match self {
2357 ImplKind::Blanket(ty) => Some(ty),
2358 _ => None,
2359 }
2360 }
2361}
2362
2363#[derive(Clone, Debug)]
2364pub(crate) struct Import {
2365 pub(crate) kind: ImportKind,
2366 pub(crate) source: ImportSource,
2368 pub(crate) should_be_displayed: bool,
2369}
2370
2371impl Import {
2372 pub(crate) fn new_simple(
2373 name: Symbol,
2374 source: ImportSource,
2375 should_be_displayed: bool,
2376 ) -> Self {
2377 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2378 }
2379
2380 pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2381 Self { kind: ImportKind::Glob, source, should_be_displayed }
2382 }
2383
2384 pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool {
2385 self.source.did.is_some_and(|did| tcx.is_doc_hidden(did))
2386 }
2387}
2388
2389#[derive(Clone, Debug)]
2390pub(crate) enum ImportKind {
2391 Simple(Symbol),
2393 Glob,
2395}
2396
2397#[derive(Clone, Debug)]
2398pub(crate) struct ImportSource {
2399 pub(crate) path: Path,
2400 pub(crate) did: Option<DefId>,
2401}
2402
2403#[derive(Clone, Debug)]
2404pub(crate) struct Macro {
2405 pub(crate) source: String,
2406 pub(crate) macro_rules: bool,
2408}
2409
2410#[derive(Clone, Debug)]
2411pub(crate) struct ProcMacro {
2412 pub(crate) kind: MacroKind,
2413 pub(crate) helpers: Vec<Symbol>,
2414}
2415
2416#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2427pub(crate) struct AssocItemConstraint {
2428 pub(crate) assoc: PathSegment,
2429 pub(crate) kind: AssocItemConstraintKind,
2430}
2431
2432#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2434pub(crate) enum AssocItemConstraintKind {
2435 Equality { term: Term },
2436 Bound { bounds: Vec<GenericBound> },
2437}
2438
2439#[cfg(target_pointer_width = "64")]
2441mod size_asserts {
2442 use rustc_data_structures::static_assert_size;
2443
2444 use super::*;
2445 static_assert_size!(Crate, 16); static_assert_size!(DocFragment, 48);
2448 static_assert_size!(GenericArg, 32);
2449 static_assert_size!(GenericArgs, 24);
2450 static_assert_size!(GenericParamDef, 40);
2451 static_assert_size!(Generics, 16);
2452 static_assert_size!(Item, 8);
2453 static_assert_size!(ItemInner, 136);
2454 static_assert_size!(ItemKind, 48);
2455 static_assert_size!(PathSegment, 32);
2456 static_assert_size!(Type, 32);
2457 }