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 PlaceholderImplItem,
891 RequiredMethodItem(Box<Function>, Defaultness),
893 MethodItem(Box<Function>, Defaultness),
897 StructFieldItem(Type),
898 VariantItem(Variant),
899 ForeignFunctionItem(Box<Function>, hir::Safety),
901 ForeignStaticItem(Static, hir::Safety),
903 ForeignTypeItem,
905 MacroItem(Macro),
906 ProcMacroItem(ProcMacro),
907 PrimitiveItem(PrimitiveType),
908 RequiredAssocConstItem(Generics, Box<Type>),
910 ConstantItem(Box<Constant>),
911 ProvidedAssocConstItem(Box<Constant>),
913 ImplAssocConstItem(Box<Constant>),
915 RequiredAssocTypeItem(Generics, Vec<GenericBound>),
919 AssocTypeItem(Box<TypeAlias>, Vec<GenericBound>),
921 StrippedItem(Box<ItemKind>),
923 KeywordItem,
926 AttributeItem,
929}
930
931impl ItemKind {
932 pub(crate) fn inner_items(&self) -> impl Iterator<Item = &Item> {
935 match self {
936 StructItem(s) => s.fields.iter(),
937 UnionItem(u) => u.fields.iter(),
938 VariantItem(v) => match &v.kind {
939 VariantKind::CLike => [].iter(),
940 VariantKind::Tuple(t) => t.iter(),
941 VariantKind::Struct(s) => s.fields.iter(),
942 },
943 EnumItem(e) => e.variants.iter(),
944 TraitItem(t) => t.items.iter(),
945 ImplItem(i) => i.items.iter(),
946 ModuleItem(m) => m.items.iter(),
947 ExternCrateItem { .. }
948 | ImportItem(_)
949 | FunctionItem(_)
950 | TypeAliasItem(_)
951 | StaticItem(_)
952 | ConstantItem(_)
953 | TraitAliasItem(_)
954 | RequiredMethodItem(..)
955 | MethodItem(..)
956 | StructFieldItem(_)
957 | ForeignFunctionItem(_, _)
958 | ForeignStaticItem(_, _)
959 | ForeignTypeItem
960 | MacroItem(_)
961 | ProcMacroItem(_)
962 | PrimitiveItem(_)
963 | RequiredAssocConstItem(..)
964 | ProvidedAssocConstItem(..)
965 | ImplAssocConstItem(..)
966 | RequiredAssocTypeItem(..)
967 | AssocTypeItem(..)
968 | StrippedItem(_)
969 | KeywordItem
970 | AttributeItem
971 | PlaceholderImplItem => [].iter(),
972 }
973 }
974}
975
976#[derive(Clone, Debug)]
977pub(crate) struct Module {
978 pub(crate) items: Vec<Item>,
979 pub(crate) span: Span,
980}
981
982#[derive(Clone, Debug, PartialEq, Eq, Hash)]
986pub(crate) struct ItemLink {
987 pub(crate) link: Box<str>,
989 pub(crate) link_text: Box<str>,
994 pub(crate) page_id: DefId,
998 pub(crate) fragment: Option<UrlFragment>,
1000}
1001
1002pub struct RenderedLink {
1003 pub(crate) original_text: Box<str>,
1007 pub(crate) new_text: Box<str>,
1009 pub(crate) href: String,
1011 pub(crate) tooltip: String,
1013}
1014
1015#[derive(Clone, Debug, Default)]
1018pub(crate) struct Attributes {
1019 pub(crate) doc_strings: Vec<DocFragment>,
1020 pub(crate) other_attrs: ThinVec<hir::Attribute>,
1021}
1022
1023impl Attributes {
1024 pub(crate) fn has_doc_flag<F: Fn(&DocAttribute) -> bool>(&self, callback: F) -> bool {
1025 find_attr!(&self.other_attrs, Doc(d) if callback(d))
1026 }
1027
1028 pub(crate) fn is_doc_hidden(&self) -> bool {
1029 find_attr!(&self.other_attrs, Doc(d) if d.hidden.is_some())
1030 }
1031
1032 pub(crate) fn from_hir(attrs: &[hir::Attribute]) -> Attributes {
1033 Attributes::from_hir_iter(attrs.iter().map(|attr| (attr, None)), false)
1034 }
1035
1036 pub(crate) fn from_hir_with_additional(
1037 attrs: &[hir::Attribute],
1038 (additional_attrs, def_id): (&[hir::Attribute], DefId),
1039 ) -> Attributes {
1040 let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id)));
1042 let attrs2 = attrs.iter().map(|attr| (attr, None));
1043 Attributes::from_hir_iter(attrs1.chain(attrs2), false)
1044 }
1045
1046 pub(crate) fn from_hir_iter<'a>(
1047 attrs: impl Iterator<Item = (&'a hir::Attribute, Option<DefId>)>,
1048 doc_only: bool,
1049 ) -> Attributes {
1050 let (doc_strings, other_attrs) = attrs_to_doc_fragments(attrs, doc_only);
1051 Attributes { doc_strings, other_attrs }
1052 }
1053
1054 pub(crate) fn doc_value(&self) -> String {
1056 self.opt_doc_value().unwrap_or_default()
1057 }
1058
1059 pub(crate) fn opt_doc_value(&self) -> Option<String> {
1063 (!self.doc_strings.is_empty()).then(|| {
1064 let mut res = String::new();
1065 for frag in &self.doc_strings {
1066 add_doc_fragment(&mut res, frag);
1067 }
1068 res.pop();
1069 res
1070 })
1071 }
1072
1073 pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> {
1074 let mut aliases = FxIndexSet::default();
1075
1076 for attr in &self.other_attrs {
1077 if let Attribute::Parsed(AttributeKind::Doc(d)) = attr {
1078 for (alias, _) in &d.aliases {
1079 aliases.insert(*alias);
1080 }
1081 }
1082 }
1083 aliases.into_iter().collect::<Vec<_>>().into()
1084 }
1085}
1086
1087#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1088pub(crate) enum GenericBound {
1089 TraitBound(PolyTrait, hir::TraitBoundModifiers),
1090 Outlives(Lifetime),
1091 Use(Vec<PreciseCapturingArg>),
1093}
1094
1095impl GenericBound {
1096 pub(crate) fn sized(cx: &mut DocContext<'_>) -> GenericBound {
1097 Self::sized_with(cx, hir::TraitBoundModifiers::NONE)
1098 }
1099
1100 pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1101 Self::sized_with(
1102 cx,
1103 hir::TraitBoundModifiers {
1104 polarity: hir::BoundPolarity::Maybe(DUMMY_SP),
1105 constness: hir::BoundConstness::Never,
1106 },
1107 )
1108 }
1109
1110 fn sized_with(cx: &mut DocContext<'_>, modifiers: hir::TraitBoundModifiers) -> GenericBound {
1111 let did = cx.tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
1112 let empty = ty::Binder::dummy(ty::GenericArgs::empty());
1113 let path = clean_middle_path(cx, did, false, ThinVec::new(), empty);
1114 inline::record_extern_fqn(cx, did, ItemType::Trait);
1115 GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifiers)
1116 }
1117
1118 pub(crate) fn is_trait_bound(&self) -> bool {
1119 matches!(self, Self::TraitBound(..))
1120 }
1121
1122 pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1123 self.is_bounded_by_lang_item(cx, LangItem::Sized)
1124 }
1125
1126 pub(crate) fn is_meta_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1127 self.is_bounded_by_lang_item(cx, LangItem::MetaSized)
1128 }
1129
1130 fn is_bounded_by_lang_item(&self, cx: &DocContext<'_>, lang_item: LangItem) -> bool {
1131 if let GenericBound::TraitBound(
1132 PolyTrait { ref trait_, .. },
1133 rustc_hir::TraitBoundModifiers::NONE,
1134 ) = *self
1135 && cx.tcx.is_lang_item(trait_.def_id(), lang_item)
1136 {
1137 return true;
1138 }
1139 false
1140 }
1141
1142 pub(crate) fn get_trait_path(&self) -> Option<Path> {
1143 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1144 Some(trait_.clone())
1145 } else {
1146 None
1147 }
1148 }
1149}
1150
1151#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1152pub(crate) struct Lifetime(pub Symbol);
1153
1154impl Lifetime {
1155 pub(crate) fn statik() -> Lifetime {
1156 Lifetime(kw::StaticLifetime)
1157 }
1158
1159 pub(crate) fn elided() -> Lifetime {
1160 Lifetime(kw::UnderscoreLifetime)
1161 }
1162}
1163
1164#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1165pub(crate) enum PreciseCapturingArg {
1166 Lifetime(Lifetime),
1167 Param(Symbol),
1168}
1169
1170impl PreciseCapturingArg {
1171 pub(crate) fn name(self) -> Symbol {
1172 match self {
1173 PreciseCapturingArg::Lifetime(lt) => lt.0,
1174 PreciseCapturingArg::Param(param) => param,
1175 }
1176 }
1177}
1178
1179#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1180pub(crate) enum WherePredicate {
1181 BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
1182 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1183 EqPredicate { lhs: QPathData, rhs: Term },
1184}
1185
1186impl WherePredicate {
1187 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1188 match self {
1189 WherePredicate::BoundPredicate { bounds, .. } => Some(bounds),
1190 WherePredicate::RegionPredicate { bounds, .. } => Some(bounds),
1191 _ => None,
1192 }
1193 }
1194}
1195
1196#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1197pub(crate) enum GenericParamDefKind {
1198 Lifetime { outlives: ThinVec<Lifetime> },
1199 Type { bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
1200 Const { ty: Box<Type>, default: Option<Box<String>> },
1202}
1203
1204impl GenericParamDefKind {
1205 pub(crate) fn is_type(&self) -> bool {
1206 matches!(self, GenericParamDefKind::Type { .. })
1207 }
1208}
1209
1210#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1211pub(crate) struct GenericParamDef {
1212 pub(crate) name: Symbol,
1213 pub(crate) def_id: DefId,
1214 pub(crate) kind: GenericParamDefKind,
1215}
1216
1217impl GenericParamDef {
1218 pub(crate) fn lifetime(def_id: DefId, name: Symbol) -> Self {
1219 Self { name, def_id, kind: GenericParamDefKind::Lifetime { outlives: ThinVec::new() } }
1220 }
1221
1222 pub(crate) fn is_synthetic_param(&self) -> bool {
1223 match self.kind {
1224 GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
1225 GenericParamDefKind::Type { synthetic, .. } => synthetic,
1226 }
1227 }
1228
1229 pub(crate) fn is_type(&self) -> bool {
1230 self.kind.is_type()
1231 }
1232
1233 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1234 match self.kind {
1235 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1236 _ => None,
1237 }
1238 }
1239}
1240
1241#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
1243pub(crate) struct Generics {
1244 pub(crate) params: ThinVec<GenericParamDef>,
1245 pub(crate) where_predicates: ThinVec<WherePredicate>,
1246}
1247
1248impl Generics {
1249 pub(crate) fn is_empty(&self) -> bool {
1250 self.params.is_empty() && self.where_predicates.is_empty()
1251 }
1252}
1253
1254#[derive(Clone, Debug)]
1255pub(crate) struct Function {
1256 pub(crate) decl: FnDecl,
1257 pub(crate) generics: Generics,
1258}
1259
1260#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1261pub(crate) struct FnDecl {
1262 pub(crate) inputs: Vec<Parameter>,
1263 pub(crate) output: Type,
1264 pub(crate) c_variadic: bool,
1265}
1266
1267impl FnDecl {
1268 pub(crate) fn receiver_type(&self) -> Option<&Type> {
1269 self.inputs.first().and_then(|v| v.to_receiver())
1270 }
1271}
1272
1273#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1275pub(crate) struct Parameter {
1276 pub(crate) name: Option<Symbol>,
1277 pub(crate) type_: Type,
1278 pub(crate) is_const: bool,
1281}
1282
1283impl Parameter {
1284 pub(crate) fn to_receiver(&self) -> Option<&Type> {
1285 if self.name == Some(kw::SelfLower) { Some(&self.type_) } else { None }
1286 }
1287}
1288
1289#[derive(Clone, Debug)]
1290pub(crate) struct Trait {
1291 pub(crate) def_id: DefId,
1292 pub(crate) items: Vec<Item>,
1293 pub(crate) generics: Generics,
1294 pub(crate) bounds: Vec<GenericBound>,
1295}
1296
1297impl Trait {
1298 pub(crate) fn is_auto(&self, tcx: TyCtxt<'_>) -> bool {
1299 tcx.trait_is_auto(self.def_id)
1300 }
1301 pub(crate) fn is_notable_trait(&self, tcx: TyCtxt<'_>) -> bool {
1302 tcx.is_doc_notable_trait(self.def_id)
1303 }
1304 pub(crate) fn safety(&self, tcx: TyCtxt<'_>) -> hir::Safety {
1305 tcx.trait_def(self.def_id).safety
1306 }
1307 pub(crate) fn is_dyn_compatible(&self, tcx: TyCtxt<'_>) -> bool {
1308 tcx.is_dyn_compatible(self.def_id)
1309 }
1310 pub(crate) fn is_deprecated(&self, tcx: TyCtxt<'_>) -> bool {
1311 tcx.lookup_deprecation(self.def_id).is_some_and(|deprecation| deprecation.is_in_effect())
1312 }
1313}
1314
1315#[derive(Clone, Debug)]
1316pub(crate) struct TraitAlias {
1317 pub(crate) generics: Generics,
1318 pub(crate) bounds: Vec<GenericBound>,
1319}
1320
1321#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1323pub(crate) struct PolyTrait {
1324 pub(crate) trait_: Path,
1325 pub(crate) generic_params: Vec<GenericParamDef>,
1326}
1327
1328#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1330pub(crate) enum Type {
1331 Path {
1336 path: Path,
1337 },
1338 DynTrait(Vec<PolyTrait>, Option<Lifetime>),
1340 Generic(Symbol),
1342 SelfTy,
1344 Primitive(PrimitiveType),
1346 BareFunction(Box<BareFunctionDecl>),
1348 Tuple(Vec<Type>),
1350 Slice(Box<Type>),
1352 Array(Box<Type>, Box<str>),
1356 Pat(Box<Type>, Box<str>),
1357 FieldOf(Box<Type>, Box<str>),
1358 RawPointer(Mutability, Box<Type>),
1360 BorrowedRef {
1362 lifetime: Option<Lifetime>,
1363 mutability: Mutability,
1364 type_: Box<Type>,
1365 },
1366
1367 QPath(Box<QPathData>),
1369
1370 Infer,
1372
1373 ImplTrait(Vec<GenericBound>),
1375
1376 UnsafeBinder(Box<UnsafeBinderTy>),
1377}
1378
1379impl Type {
1380 pub(crate) fn without_borrowed_ref(&self) -> &Type {
1382 let mut result = self;
1383 while let Type::BorrowedRef { type_, .. } = result {
1384 result = type_;
1385 }
1386 result
1387 }
1388
1389 pub(crate) fn is_borrowed_ref(&self) -> bool {
1390 matches!(self, Type::BorrowedRef { .. })
1391 }
1392
1393 fn is_type_alias(&self) -> bool {
1394 matches!(self, Type::Path { path: Path { res: Res::Def(DefKind::TyAlias, _), .. } })
1395 }
1396
1397 pub(crate) fn is_doc_subtype_of(&self, other: &Self, cache: &Cache) -> bool {
1418 let (self_cleared, other_cleared) = if !self.is_borrowed_ref() || !other.is_borrowed_ref() {
1421 (self.without_borrowed_ref(), other.without_borrowed_ref())
1422 } else {
1423 (self, other)
1424 };
1425
1426 if self_cleared.is_type_alias() || other_cleared.is_type_alias() {
1432 return true;
1433 }
1434
1435 match (self_cleared, other_cleared) {
1436 (Type::Tuple(a), Type::Tuple(b)) => {
1438 a.iter().eq_by(b, |a, b| a.is_doc_subtype_of(b, cache))
1439 }
1440 (Type::Slice(a), Type::Slice(b)) => a.is_doc_subtype_of(b, cache),
1441 (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_doc_subtype_of(b, cache),
1442 (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
1443 mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache)
1444 }
1445 (
1446 Type::BorrowedRef { mutability, type_, .. },
1447 Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
1448 ) => mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache),
1449 (Type::Infer, _) | (_, Type::Infer) => true,
1451 (_, Type::Generic(_)) => true,
1454 (Type::Generic(_), _) => false,
1455 (Type::SelfTy, Type::SelfTy) => true,
1457 (Type::Path { path: a }, Type::Path { path: b }) => {
1459 a.def_id() == b.def_id()
1460 && a.generics()
1461 .zip(b.generics())
1462 .map(|(ag, bg)| ag.zip(bg).all(|(at, bt)| at.is_doc_subtype_of(bt, cache)))
1463 .unwrap_or(true)
1464 }
1465 (a, b) => a
1467 .def_id(cache)
1468 .and_then(|a| Some((a, b.def_id(cache)?)))
1469 .map(|(a, b)| a == b)
1470 .unwrap_or(false),
1471 }
1472 }
1473
1474 pub(crate) fn primitive_type(&self) -> Option<PrimitiveType> {
1475 match *self {
1476 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1477 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1478 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1479 Tuple(ref tys) => {
1480 if tys.is_empty() {
1481 Some(PrimitiveType::Unit)
1482 } else {
1483 Some(PrimitiveType::Tuple)
1484 }
1485 }
1486 RawPointer(..) => Some(PrimitiveType::RawPointer),
1487 BareFunction(..) => Some(PrimitiveType::Fn),
1488 _ => None,
1489 }
1490 }
1491
1492 pub(crate) fn sugared_async_return_type(self) -> Type {
1502 if let Type::ImplTrait(mut v) = self
1503 && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = v.pop()
1504 && let Some(segment) = trait_.segments.pop()
1505 && let GenericArgs::AngleBracketed { mut constraints, .. } = segment.args
1506 && let Some(constraint) = constraints.pop()
1507 && let AssocItemConstraintKind::Equality { term } = constraint.kind
1508 && let Term::Type(ty) = term
1509 {
1510 ty
1511 } else {
1512 panic!("unexpected async fn return type")
1513 }
1514 }
1515
1516 pub(crate) fn is_assoc_ty(&self) -> bool {
1518 match self {
1519 Type::Path { path, .. } => path.is_assoc_ty(),
1520 _ => false,
1521 }
1522 }
1523
1524 pub(crate) fn is_self_type(&self) -> bool {
1525 matches!(*self, Type::SelfTy)
1526 }
1527
1528 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
1529 match self {
1530 Type::Path { path, .. } => path.generic_args(),
1531 _ => None,
1532 }
1533 }
1534
1535 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
1536 match self {
1537 Type::Path { path, .. } => path.generics(),
1538 _ => None,
1539 }
1540 }
1541
1542 pub(crate) fn is_full_generic(&self) -> bool {
1543 matches!(self, Type::Generic(_))
1544 }
1545
1546 pub(crate) fn is_unit(&self) -> bool {
1547 matches!(self, Type::Tuple(v) if v.is_empty())
1548 }
1549
1550 pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
1554 let t: PrimitiveType = match self {
1555 Type::Path { path } => return Some(path.def_id()),
1556 DynTrait(bounds, _) => return bounds.first().map(|b| b.trait_.def_id()),
1557 Primitive(p) => return cache.primitive_locations.get(p).cloned(),
1558 BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
1559 BorrowedRef { type_, .. } => return type_.def_id(cache),
1560 Tuple(tys) => {
1561 if tys.is_empty() {
1562 PrimitiveType::Unit
1563 } else {
1564 PrimitiveType::Tuple
1565 }
1566 }
1567 BareFunction(..) => PrimitiveType::Fn,
1568 Slice(..) => PrimitiveType::Slice,
1569 Array(..) => PrimitiveType::Array,
1570 Type::Pat(..) => PrimitiveType::Pat,
1571 Type::FieldOf(..) => PrimitiveType::FieldOf,
1572 RawPointer(..) => PrimitiveType::RawPointer,
1573 QPath(box QPathData { self_type, .. }) => return self_type.def_id(cache),
1574 Generic(_) | SelfTy | Infer | ImplTrait(_) | UnsafeBinder(_) => return None,
1575 };
1576 Primitive(t).def_id(cache)
1577 }
1578}
1579
1580#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1581pub(crate) struct QPathData {
1582 pub assoc: PathSegment,
1583 pub self_type: Type,
1584 pub should_fully_qualify: bool,
1586 pub trait_: Option<Path>,
1587}
1588
1589#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1596pub(crate) enum PrimitiveType {
1597 Isize,
1598 I8,
1599 I16,
1600 I32,
1601 I64,
1602 I128,
1603 Usize,
1604 U8,
1605 U16,
1606 U32,
1607 U64,
1608 U128,
1609 F16,
1610 F32,
1611 F64,
1612 F128,
1613 Char,
1614 Bool,
1615 Str,
1616 Slice,
1617 Array,
1618 Pat,
1619 FieldOf,
1620 Tuple,
1621 Unit,
1622 RawPointer,
1623 Reference,
1624 Fn,
1625 Never,
1626}
1627
1628type SimplifiedTypes = FxIndexMap<PrimitiveType, ArrayVec<SimplifiedType, 3>>;
1629impl PrimitiveType {
1630 pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1631 use ast::{FloatTy, IntTy, UintTy};
1632 match prim {
1633 hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1634 hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1635 hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1636 hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1637 hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1638 hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1639 hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1640 hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1641 hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1642 hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1643 hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1644 hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1645 hir::PrimTy::Float(FloatTy::F16) => PrimitiveType::F16,
1646 hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1647 hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1648 hir::PrimTy::Float(FloatTy::F128) => PrimitiveType::F128,
1649 hir::PrimTy::Str => PrimitiveType::Str,
1650 hir::PrimTy::Bool => PrimitiveType::Bool,
1651 hir::PrimTy::Char => PrimitiveType::Char,
1652 }
1653 }
1654
1655 pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1656 match s {
1657 sym::isize => Some(PrimitiveType::Isize),
1658 sym::i8 => Some(PrimitiveType::I8),
1659 sym::i16 => Some(PrimitiveType::I16),
1660 sym::i32 => Some(PrimitiveType::I32),
1661 sym::i64 => Some(PrimitiveType::I64),
1662 sym::i128 => Some(PrimitiveType::I128),
1663 sym::usize => Some(PrimitiveType::Usize),
1664 sym::u8 => Some(PrimitiveType::U8),
1665 sym::u16 => Some(PrimitiveType::U16),
1666 sym::u32 => Some(PrimitiveType::U32),
1667 sym::u64 => Some(PrimitiveType::U64),
1668 sym::u128 => Some(PrimitiveType::U128),
1669 sym::bool => Some(PrimitiveType::Bool),
1670 sym::char => Some(PrimitiveType::Char),
1671 sym::str => Some(PrimitiveType::Str),
1672 sym::f16 => Some(PrimitiveType::F16),
1673 sym::f32 => Some(PrimitiveType::F32),
1674 sym::f64 => Some(PrimitiveType::F64),
1675 sym::f128 => Some(PrimitiveType::F128),
1676 sym::array => Some(PrimitiveType::Array),
1677 sym::slice => Some(PrimitiveType::Slice),
1678 sym::tuple => Some(PrimitiveType::Tuple),
1679 sym::unit => Some(PrimitiveType::Unit),
1680 sym::pointer => Some(PrimitiveType::RawPointer),
1681 sym::reference => Some(PrimitiveType::Reference),
1682 kw::Fn => Some(PrimitiveType::Fn),
1683 sym::never => Some(PrimitiveType::Never),
1684 _ => None,
1685 }
1686 }
1687
1688 pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
1689 use PrimitiveType::*;
1690 use ty::{FloatTy, IntTy, UintTy};
1691 static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
1692
1693 let single = |x| iter::once(x).collect();
1694 CELL.get_or_init(move || {
1695 map! {
1696 Isize => single(SimplifiedType::Int(IntTy::Isize)),
1697 I8 => single(SimplifiedType::Int(IntTy::I8)),
1698 I16 => single(SimplifiedType::Int(IntTy::I16)),
1699 I32 => single(SimplifiedType::Int(IntTy::I32)),
1700 I64 => single(SimplifiedType::Int(IntTy::I64)),
1701 I128 => single(SimplifiedType::Int(IntTy::I128)),
1702 Usize => single(SimplifiedType::Uint(UintTy::Usize)),
1703 U8 => single(SimplifiedType::Uint(UintTy::U8)),
1704 U16 => single(SimplifiedType::Uint(UintTy::U16)),
1705 U32 => single(SimplifiedType::Uint(UintTy::U32)),
1706 U64 => single(SimplifiedType::Uint(UintTy::U64)),
1707 U128 => single(SimplifiedType::Uint(UintTy::U128)),
1708 F16 => single(SimplifiedType::Float(FloatTy::F16)),
1709 F32 => single(SimplifiedType::Float(FloatTy::F32)),
1710 F64 => single(SimplifiedType::Float(FloatTy::F64)),
1711 F128 => single(SimplifiedType::Float(FloatTy::F128)),
1712 Str => single(SimplifiedType::Str),
1713 Bool => single(SimplifiedType::Bool),
1714 Char => single(SimplifiedType::Char),
1715 Array => single(SimplifiedType::Array),
1716 Slice => single(SimplifiedType::Slice),
1717 Tuple => [SimplifiedType::Tuple(1), SimplifiedType::Tuple(2), SimplifiedType::Tuple(3)].into(),
1723 Unit => single(SimplifiedType::Tuple(0)),
1724 RawPointer => [SimplifiedType::Ptr(Mutability::Not), SimplifiedType::Ptr(Mutability::Mut)].into_iter().collect(),
1725 Reference => [SimplifiedType::Ref(Mutability::Not), SimplifiedType::Ref(Mutability::Mut)].into_iter().collect(),
1726 Fn => single(SimplifiedType::Function(1)),
1729 Never => single(SimplifiedType::Never),
1730 }
1731 })
1732 }
1733
1734 pub(crate) fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = DefId> + 'tcx {
1735 Self::simplified_types()
1736 .get(self)
1737 .into_iter()
1738 .flatten()
1739 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1740 .copied()
1741 }
1742
1743 pub(crate) fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> {
1744 Self::simplified_types()
1745 .values()
1746 .flatten()
1747 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1748 .copied()
1749 }
1750
1751 pub(crate) fn as_sym(&self) -> Symbol {
1752 use PrimitiveType::*;
1753 match self {
1754 Isize => sym::isize,
1755 I8 => sym::i8,
1756 I16 => sym::i16,
1757 I32 => sym::i32,
1758 I64 => sym::i64,
1759 I128 => sym::i128,
1760 Usize => sym::usize,
1761 U8 => sym::u8,
1762 U16 => sym::u16,
1763 U32 => sym::u32,
1764 U64 => sym::u64,
1765 U128 => sym::u128,
1766 F16 => sym::f16,
1767 F32 => sym::f32,
1768 F64 => sym::f64,
1769 F128 => sym::f128,
1770 Str => sym::str,
1771 Bool => sym::bool,
1772 Char => sym::char,
1773 Array => sym::array,
1774 Pat => sym::pat,
1775 FieldOf => sym::field_of,
1776 Slice => sym::slice,
1777 Tuple => sym::tuple,
1778 Unit => sym::unit,
1779 RawPointer => sym::pointer,
1780 Reference => sym::reference,
1781 Fn => kw::Fn,
1782 Never => sym::never,
1783 }
1784 }
1785
1786 pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxIndexMap<PrimitiveType, DefId> {
1798 static PRIMITIVE_LOCATIONS: OnceCell<FxIndexMap<PrimitiveType, DefId>> = OnceCell::new();
1799 PRIMITIVE_LOCATIONS.get_or_init(|| {
1800 let mut primitive_locations = FxIndexMap::default();
1801 for &crate_num in tcx.crates(()) {
1804 let e = ExternalCrate { crate_num };
1805 let crate_name = e.name(tcx);
1806 debug!(?crate_num, ?crate_name);
1807 for (def_id, prim) in e.primitives(tcx) {
1808 if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1810 continue;
1811 }
1812 primitive_locations.insert(prim, def_id);
1813 }
1814 }
1815 let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1816 for (def_id, prim) in local_primitives {
1817 primitive_locations.insert(prim, def_id);
1818 }
1819 primitive_locations
1820 })
1821 }
1822}
1823
1824impl From<ty::IntTy> for PrimitiveType {
1825 fn from(int_ty: ty::IntTy) -> PrimitiveType {
1826 match int_ty {
1827 ty::IntTy::Isize => PrimitiveType::Isize,
1828 ty::IntTy::I8 => PrimitiveType::I8,
1829 ty::IntTy::I16 => PrimitiveType::I16,
1830 ty::IntTy::I32 => PrimitiveType::I32,
1831 ty::IntTy::I64 => PrimitiveType::I64,
1832 ty::IntTy::I128 => PrimitiveType::I128,
1833 }
1834 }
1835}
1836
1837impl From<ty::UintTy> for PrimitiveType {
1838 fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1839 match uint_ty {
1840 ty::UintTy::Usize => PrimitiveType::Usize,
1841 ty::UintTy::U8 => PrimitiveType::U8,
1842 ty::UintTy::U16 => PrimitiveType::U16,
1843 ty::UintTy::U32 => PrimitiveType::U32,
1844 ty::UintTy::U64 => PrimitiveType::U64,
1845 ty::UintTy::U128 => PrimitiveType::U128,
1846 }
1847 }
1848}
1849
1850impl From<ty::FloatTy> for PrimitiveType {
1851 fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1852 match float_ty {
1853 ty::FloatTy::F16 => PrimitiveType::F16,
1854 ty::FloatTy::F32 => PrimitiveType::F32,
1855 ty::FloatTy::F64 => PrimitiveType::F64,
1856 ty::FloatTy::F128 => PrimitiveType::F128,
1857 }
1858 }
1859}
1860
1861impl From<hir::PrimTy> for PrimitiveType {
1862 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1863 match prim_ty {
1864 hir::PrimTy::Int(int_ty) => int_ty.into(),
1865 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1866 hir::PrimTy::Float(float_ty) => float_ty.into(),
1867 hir::PrimTy::Str => PrimitiveType::Str,
1868 hir::PrimTy::Bool => PrimitiveType::Bool,
1869 hir::PrimTy::Char => PrimitiveType::Char,
1870 }
1871 }
1872}
1873
1874#[derive(Clone, Debug)]
1875pub(crate) struct Struct {
1876 pub(crate) ctor_kind: Option<CtorKind>,
1877 pub(crate) generics: Generics,
1878 pub(crate) fields: ThinVec<Item>,
1879}
1880
1881impl Struct {
1882 pub(crate) fn has_stripped_entries(&self) -> bool {
1883 self.fields.iter().any(|f| f.is_stripped())
1884 }
1885}
1886
1887#[derive(Clone, Debug)]
1888pub(crate) struct Union {
1889 pub(crate) generics: Generics,
1890 pub(crate) fields: Vec<Item>,
1891}
1892
1893impl Union {
1894 pub(crate) fn has_stripped_entries(&self) -> bool {
1895 self.fields.iter().any(|f| f.is_stripped())
1896 }
1897}
1898
1899#[derive(Clone, Debug)]
1903pub(crate) struct VariantStruct {
1904 pub(crate) fields: ThinVec<Item>,
1905}
1906
1907impl VariantStruct {
1908 pub(crate) fn has_stripped_entries(&self) -> bool {
1909 self.fields.iter().any(|f| f.is_stripped())
1910 }
1911}
1912
1913#[derive(Clone, Debug)]
1914pub(crate) struct Enum {
1915 pub(crate) variants: IndexVec<VariantIdx, Item>,
1916 pub(crate) generics: Generics,
1917}
1918
1919impl Enum {
1920 pub(crate) fn has_stripped_entries(&self) -> bool {
1921 self.variants.iter().any(|f| f.is_stripped())
1922 }
1923
1924 pub(crate) fn non_stripped_variants(&self) -> impl Iterator<Item = &Item> {
1925 self.variants.iter().filter(|v| !v.is_stripped())
1926 }
1927}
1928
1929#[derive(Clone, Debug)]
1930pub(crate) struct Variant {
1931 pub kind: VariantKind,
1932 pub discriminant: Option<Discriminant>,
1933}
1934
1935#[derive(Clone, Debug)]
1936pub(crate) enum VariantKind {
1937 CLike,
1938 Tuple(ThinVec<Item>),
1939 Struct(VariantStruct),
1940}
1941
1942impl Variant {
1943 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
1944 match &self.kind {
1945 VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()),
1946 VariantKind::CLike | VariantKind::Tuple(_) => None,
1947 }
1948 }
1949}
1950
1951#[derive(Clone, Debug)]
1952pub(crate) struct Discriminant {
1953 pub(super) expr: Option<BodyId>,
1956 pub(super) value: DefId,
1957}
1958
1959impl Discriminant {
1960 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
1963 self.expr
1964 .map(|body| rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body)))
1965 }
1966 pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String {
1967 print_evaluated_const(tcx, self.value, with_underscores, false).unwrap()
1968 }
1969}
1970
1971#[derive(Copy, Clone, Debug)]
1974pub(crate) struct Span(rustc_span::Span);
1975
1976impl Span {
1977 pub(crate) fn new(sp: rustc_span::Span) -> Self {
1982 Self(sp.source_callsite())
1983 }
1984
1985 pub(crate) fn inner(&self) -> rustc_span::Span {
1986 self.0
1987 }
1988
1989 pub(crate) fn filename(&self, sess: &Session) -> FileName {
1990 sess.source_map().span_to_filename(self.0)
1991 }
1992
1993 pub(crate) fn lo(&self, sess: &Session) -> Loc {
1994 sess.source_map().lookup_char_pos(self.0.lo())
1995 }
1996
1997 pub(crate) fn hi(&self, sess: &Session) -> Loc {
1998 sess.source_map().lookup_char_pos(self.0.hi())
1999 }
2000
2001 pub(crate) fn cnum(&self, sess: &Session) -> CrateNum {
2002 self.lo(sess).file.cnum
2004 }
2005}
2006
2007#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2008pub(crate) struct Path {
2009 pub(crate) res: Res,
2010 pub(crate) segments: ThinVec<PathSegment>,
2011}
2012
2013impl Path {
2014 pub(crate) fn def_id(&self) -> DefId {
2015 self.res.def_id()
2016 }
2017
2018 pub(crate) fn last_opt(&self) -> Option<Symbol> {
2019 self.segments.last().map(|s| s.name)
2020 }
2021
2022 pub(crate) fn last(&self) -> Symbol {
2023 self.last_opt().expect("segments were empty")
2024 }
2025
2026 pub(crate) fn whole_name(&self) -> String {
2027 self.segments
2028 .iter()
2029 .map(|s| if s.name == kw::PathRoot { "" } else { s.name.as_str() })
2030 .intersperse("::")
2031 .collect()
2032 }
2033
2034 pub(crate) fn is_assoc_ty(&self) -> bool {
2036 match self.res {
2037 Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _)
2038 if self.segments.len() != 1 =>
2039 {
2040 true
2041 }
2042 Res::Def(DefKind::AssocTy, _) => true,
2043 _ => false,
2044 }
2045 }
2046
2047 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
2048 self.segments.last().map(|seg| &seg.args)
2049 }
2050
2051 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
2052 self.segments.last().and_then(|seg| {
2053 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2054 Some(args.iter().filter_map(|arg| match arg {
2055 GenericArg::Type(ty) => Some(ty),
2056 _ => None,
2057 }))
2058 } else {
2059 None
2060 }
2061 })
2062 }
2063}
2064
2065#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2066pub(crate) enum GenericArg {
2067 Lifetime(Lifetime),
2068 Type(Type),
2069 Const(Box<ConstantKind>),
2070 Infer,
2071}
2072
2073impl GenericArg {
2074 pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
2075 if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2076 }
2077
2078 pub(crate) fn as_ty(&self) -> Option<&Type> {
2079 if let Self::Type(ty) = self { Some(ty) } else { None }
2080 }
2081}
2082
2083#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2084pub(crate) enum GenericArgs {
2085 AngleBracketed { args: ThinVec<GenericArg>, constraints: ThinVec<AssocItemConstraint> },
2087 Parenthesized { inputs: ThinVec<Type>, output: Option<Box<Type>> },
2089 ReturnTypeNotation,
2091}
2092
2093impl GenericArgs {
2094 pub(crate) fn is_empty(&self) -> bool {
2095 match self {
2096 GenericArgs::AngleBracketed { args, constraints } => {
2097 args.is_empty() && constraints.is_empty()
2098 }
2099 GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
2100 GenericArgs::ReturnTypeNotation => false,
2101 }
2102 }
2103 pub(crate) fn constraints(&self) -> Box<dyn Iterator<Item = AssocItemConstraint> + '_> {
2104 match self {
2105 GenericArgs::AngleBracketed { constraints, .. } => {
2106 Box::new(constraints.iter().cloned())
2107 }
2108 GenericArgs::Parenthesized { output, .. } => Box::new(
2109 output
2110 .as_ref()
2111 .map(|ty| AssocItemConstraint {
2112 assoc: PathSegment {
2113 name: sym::Output,
2114 args: GenericArgs::AngleBracketed {
2115 args: ThinVec::new(),
2116 constraints: ThinVec::new(),
2117 },
2118 },
2119 kind: AssocItemConstraintKind::Equality {
2120 term: Term::Type((**ty).clone()),
2121 },
2122 })
2123 .into_iter(),
2124 ),
2125 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2126 }
2127 }
2128}
2129
2130impl<'a> IntoIterator for &'a GenericArgs {
2131 type IntoIter = Box<dyn Iterator<Item = GenericArg> + 'a>;
2132 type Item = GenericArg;
2133 fn into_iter(self) -> Self::IntoIter {
2134 match self {
2135 GenericArgs::AngleBracketed { args, .. } => Box::new(args.iter().cloned()),
2136 GenericArgs::Parenthesized { inputs, .. } => {
2137 Box::new(inputs.iter().cloned().map(GenericArg::Type))
2139 }
2140 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2141 }
2142 }
2143}
2144
2145#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2146pub(crate) struct PathSegment {
2147 pub(crate) name: Symbol,
2148 pub(crate) args: GenericArgs,
2149}
2150
2151#[derive(Clone, Debug)]
2152pub(crate) enum TypeAliasInnerType {
2153 Enum { variants: IndexVec<VariantIdx, Item>, is_non_exhaustive: bool },
2154 Union { fields: Vec<Item> },
2155 Struct { ctor_kind: Option<CtorKind>, fields: Vec<Item> },
2156}
2157
2158impl TypeAliasInnerType {
2159 fn has_stripped_entries(&self) -> Option<bool> {
2160 Some(match self {
2161 Self::Enum { variants, .. } => variants.iter().any(|v| v.is_stripped()),
2162 Self::Union { fields } | Self::Struct { fields, .. } => {
2163 fields.iter().any(|f| f.is_stripped())
2164 }
2165 })
2166 }
2167}
2168
2169#[derive(Clone, Debug)]
2170pub(crate) struct TypeAlias {
2171 pub(crate) type_: Type,
2172 pub(crate) generics: Generics,
2173 pub(crate) inner_type: Option<TypeAliasInnerType>,
2176 pub(crate) item_type: Option<Type>,
2183}
2184
2185#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2186pub(crate) struct BareFunctionDecl {
2187 pub(crate) safety: hir::Safety,
2188 pub(crate) generic_params: Vec<GenericParamDef>,
2189 pub(crate) decl: FnDecl,
2190 pub(crate) abi: ExternAbi,
2191}
2192
2193#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2194pub(crate) struct UnsafeBinderTy {
2195 pub(crate) generic_params: Vec<GenericParamDef>,
2196 pub(crate) ty: Type,
2197}
2198
2199#[derive(Clone, Debug)]
2200pub(crate) struct Static {
2201 pub(crate) type_: Box<Type>,
2202 pub(crate) mutability: Mutability,
2203 pub(crate) expr: Option<BodyId>,
2204}
2205
2206#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2207pub(crate) struct Constant {
2208 pub(crate) generics: Generics,
2209 pub(crate) kind: ConstantKind,
2210 pub(crate) type_: Type,
2211}
2212
2213#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2214pub(crate) enum Term {
2215 Type(Type),
2216 Constant(ConstantKind),
2217}
2218
2219impl Term {
2220 pub(crate) fn ty(&self) -> Option<&Type> {
2221 if let Term::Type(ty) = self { Some(ty) } else { None }
2222 }
2223}
2224
2225impl From<Type> for Term {
2226 fn from(ty: Type) -> Self {
2227 Term::Type(ty)
2228 }
2229}
2230
2231#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2232pub(crate) enum ConstantKind {
2233 TyConst { expr: Box<str> },
2239 Path { path: Box<str> },
2242 Anonymous { body: BodyId },
2246 Extern { def_id: DefId },
2248 Local { def_id: DefId, body: BodyId },
2250 Infer,
2252}
2253
2254impl ConstantKind {
2255 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2256 match *self {
2257 ConstantKind::TyConst { ref expr } => expr.to_string(),
2258 ConstantKind::Path { ref path } => path.to_string(),
2259 ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2260 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2261 rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body))
2262 }
2263 ConstantKind::Infer => "_".to_string(),
2264 }
2265 }
2266
2267 pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2268 match *self {
2269 ConstantKind::TyConst { .. }
2270 | ConstantKind::Path { .. }
2271 | ConstantKind::Anonymous { .. }
2272 | ConstantKind::Infer => None,
2273 ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2274 print_evaluated_const(tcx, def_id, true, true)
2275 }
2276 }
2277 }
2278
2279 pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2280 match *self {
2281 ConstantKind::TyConst { .. }
2282 | ConstantKind::Extern { .. }
2283 | ConstantKind::Path { .. }
2284 | ConstantKind::Infer => false,
2285 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2286 is_literal_expr(tcx, body.hir_id)
2287 }
2288 }
2289 }
2290}
2291
2292#[derive(Clone, Debug)]
2293pub(crate) struct Impl {
2294 pub(crate) safety: hir::Safety,
2295 pub(crate) generics: Generics,
2296 pub(crate) trait_: Option<Path>,
2297 pub(crate) for_: Type,
2298 pub(crate) items: Vec<Item>,
2299 pub(crate) polarity: ty::ImplPolarity,
2300 pub(crate) kind: ImplKind,
2301 pub(crate) is_deprecated: bool,
2302}
2303
2304impl Impl {
2305 pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxIndexSet<Symbol> {
2306 self.trait_
2307 .as_ref()
2308 .map(|t| t.def_id())
2309 .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name()).collect())
2310 .unwrap_or_default()
2311 }
2312
2313 pub(crate) fn is_negative_trait_impl(&self) -> bool {
2314 matches!(self.polarity, ty::ImplPolarity::Negative)
2315 }
2316}
2317
2318#[derive(Clone, Debug)]
2319pub(crate) enum ImplKind {
2320 Normal,
2321 Auto,
2322 FakeVariadic,
2323 Blanket(Box<Type>),
2324}
2325
2326impl ImplKind {
2327 pub(crate) fn is_auto(&self) -> bool {
2328 matches!(self, ImplKind::Auto)
2329 }
2330
2331 pub(crate) fn is_blanket(&self) -> bool {
2332 matches!(self, ImplKind::Blanket(_))
2333 }
2334
2335 pub(crate) fn is_fake_variadic(&self) -> bool {
2336 matches!(self, ImplKind::FakeVariadic)
2337 }
2338
2339 pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
2340 match self {
2341 ImplKind::Blanket(ty) => Some(ty),
2342 _ => None,
2343 }
2344 }
2345}
2346
2347#[derive(Clone, Debug)]
2348pub(crate) struct Import {
2349 pub(crate) kind: ImportKind,
2350 pub(crate) source: ImportSource,
2352 pub(crate) should_be_displayed: bool,
2353}
2354
2355impl Import {
2356 pub(crate) fn new_simple(
2357 name: Symbol,
2358 source: ImportSource,
2359 should_be_displayed: bool,
2360 ) -> Self {
2361 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2362 }
2363
2364 pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2365 Self { kind: ImportKind::Glob, source, should_be_displayed }
2366 }
2367
2368 pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool {
2369 self.source.did.is_some_and(|did| tcx.is_doc_hidden(did))
2370 }
2371}
2372
2373#[derive(Clone, Debug)]
2374pub(crate) enum ImportKind {
2375 Simple(Symbol),
2377 Glob,
2379}
2380
2381#[derive(Clone, Debug)]
2382pub(crate) struct ImportSource {
2383 pub(crate) path: Path,
2384 pub(crate) did: Option<DefId>,
2385}
2386
2387#[derive(Clone, Debug)]
2388pub(crate) struct Macro {
2389 pub(crate) source: String,
2390 pub(crate) macro_rules: bool,
2392}
2393
2394#[derive(Clone, Debug)]
2395pub(crate) struct ProcMacro {
2396 pub(crate) kind: MacroKind,
2397 pub(crate) helpers: Vec<Symbol>,
2398}
2399
2400#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2411pub(crate) struct AssocItemConstraint {
2412 pub(crate) assoc: PathSegment,
2413 pub(crate) kind: AssocItemConstraintKind,
2414}
2415
2416#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2418pub(crate) enum AssocItemConstraintKind {
2419 Equality { term: Term },
2420 Bound { bounds: Vec<GenericBound> },
2421}
2422
2423#[cfg(target_pointer_width = "64")]
2425mod size_asserts {
2426 use rustc_data_structures::static_assert_size;
2427
2428 use super::*;
2429 static_assert_size!(Crate, 16); static_assert_size!(DocFragment, 48);
2432 static_assert_size!(GenericArg, 32);
2433 static_assert_size!(GenericArgs, 24);
2434 static_assert_size!(GenericParamDef, 40);
2435 static_assert_size!(Generics, 16);
2436 static_assert_size!(Item, 8);
2437 static_assert_size!(ItemInner, 136);
2438 static_assert_size!(ItemKind, 48);
2439 static_assert_size!(PathSegment, 32);
2440 static_assert_size!(Type, 32);
2441 }