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