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, MacroKinds, 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, Ty, 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, ModId};
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(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(Impl { kind: ImplKind::Auto, .. }) => None,
509 ItemKind::ImplItem(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(AssocTypeItem(..)))
671 }
672 pub(crate) fn is_required_associated_type(&self) -> bool {
673 matches!(self.kind, RequiredAssocTypeItem(..) | StrippedItem(RequiredAssocTypeItem(..)))
674 }
675 pub(crate) fn is_associated_const(&self) -> bool {
676 matches!(
677 self.kind,
678 ProvidedAssocConstItem(..)
679 | ImplAssocConstItem(..)
680 | StrippedItem(ProvidedAssocConstItem(..) | ImplAssocConstItem(..))
681 )
682 }
683 pub(crate) fn is_required_associated_const(&self) -> bool {
684 matches!(self.kind, RequiredAssocConstItem(..) | StrippedItem(RequiredAssocConstItem(..)))
685 }
686 pub(crate) fn is_method(&self) -> bool {
687 self.type_() == ItemType::Method
688 }
689 pub(crate) fn is_ty_method(&self) -> bool {
690 self.type_() == ItemType::TyMethod
691 }
692 pub(crate) fn is_primitive(&self) -> bool {
693 self.type_() == ItemType::Primitive
694 }
695 pub(crate) fn is_union(&self) -> bool {
696 self.type_() == ItemType::Union
697 }
698 pub(crate) fn is_import(&self) -> bool {
699 self.type_() == ItemType::Import
700 }
701 pub(crate) fn is_extern_crate(&self) -> bool {
702 self.type_() == ItemType::ExternCrate
703 }
704 pub(crate) fn is_keyword(&self) -> bool {
705 self.type_() == ItemType::Keyword
706 }
707 pub(crate) fn is_attribute(&self) -> bool {
708 self.type_() == ItemType::Attribute
709 }
710 pub(crate) fn is_fake_item(&self) -> bool {
719 matches!(self.type_(), ItemType::Primitive | ItemType::Keyword | ItemType::Attribute)
720 }
721 pub(crate) fn is_stripped(&self) -> bool {
722 match self.kind {
723 StrippedItem(..) => true,
724 ImportItem(ref i) => !i.should_be_displayed,
725 _ => false,
726 }
727 }
728 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
729 match self.kind {
730 StructItem(ref struct_) => Some(struct_.has_stripped_entries()),
731 UnionItem(ref union_) => Some(union_.has_stripped_entries()),
732 EnumItem(ref enum_) => Some(enum_.has_stripped_entries()),
733 VariantItem(ref v) => v.has_stripped_entries(),
734 TypeAliasItem(ref type_alias) => {
735 type_alias.inner_type.as_ref().and_then(|t| t.has_stripped_entries())
736 }
737 _ => None,
738 }
739 }
740
741 pub(crate) fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
742 self.stability(tcx).as_ref().and_then(|s| {
743 let mut classes = Vec::with_capacity(2);
744
745 if s.is_unstable() {
746 classes.push("unstable");
747 }
748
749 if self.deprecation(tcx).is_some() {
751 classes.push("deprecated");
752 }
753
754 if !classes.is_empty() { Some(classes.join(" ")) } else { None }
755 })
756 }
757
758 pub(crate) fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<StableSince> {
759 self.stability(tcx).and_then(|stability| stability.stable_since())
760 }
761
762 pub(crate) fn is_non_exhaustive(&self) -> bool {
763 find_attr!(&self.attrs.other_attrs, NonExhaustive(..))
764 }
765
766 pub(crate) fn type_(&self) -> ItemType {
770 ItemType::from(self)
771 }
772
773 pub(crate) fn types(&self) -> impl Iterator<Item = ItemType> {
776 if let ItemKind::MacroItem(_, macro_kinds) = self.kind {
777 Either::Right(macro_kinds.iter().map(|kind| match kind {
778 MacroKinds::ATTR => ItemType::DeclMacroAttribute,
779 MacroKinds::DERIVE => ItemType::DeclMacroDerive,
780 MacroKinds::BANG => ItemType::Macro,
781 _ => panic!("unsupported macro kind {kind:?}"),
782 }))
783 } else {
784 Either::Left(std::iter::once(self.type_()))
785 }
786 }
787
788 pub(crate) fn is_decl_macro(&self) -> bool {
790 matches!(self.kind, ItemKind::MacroItem(..))
791 }
792
793 pub(crate) fn defaultness(&self) -> Option<Defaultness> {
794 match self.kind {
795 ItemKind::MethodItem(_, defaultness) | ItemKind::RequiredMethodItem(_, defaultness) => {
796 Some(defaultness)
797 }
798 _ => None,
799 }
800 }
801
802 pub(crate) fn html_filename(&self) -> String {
804 format!("{type_}.{name}.html", type_ = self.type_(), name = self.name.unwrap())
805 }
806
807 pub(crate) fn fn_header(&self, tcx: TyCtxt<'_>) -> Option<hir::FnHeader> {
809 fn build_fn_header(
810 def_id: DefId,
811 tcx: TyCtxt<'_>,
812 asyncness: ty::Asyncness,
813 ) -> hir::FnHeader {
814 let sig = tcx.fn_sig(def_id).skip_binder();
815 let constness = if tcx.is_const_fn(def_id) {
816 if let Some(assoc) = tcx.opt_associated_item(def_id)
820 && let ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) =
821 assoc.container
822 {
823 hir::Constness::NotConst
824 } else {
825 hir::Constness::Const { always: false }
826 }
827 } else {
828 hir::Constness::NotConst
829 };
830 let asyncness = match asyncness {
831 ty::Asyncness::Yes => hir::IsAsync::Async(DUMMY_SP),
832 ty::Asyncness::No => hir::IsAsync::NotAsync,
833 };
834 hir::FnHeader {
835 safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
836 hir::HeaderSafety::SafeTargetFeatures
837 } else {
838 sig.safety().into()
839 },
840 abi: sig.abi(),
841 constness,
842 asyncness,
843 }
844 }
845 let header = match self.kind {
846 ItemKind::ForeignFunctionItem(_, safety) => {
847 let def_id = self.def_id().unwrap();
848 let abi = tcx.fn_sig(def_id).skip_binder().abi();
849 hir::FnHeader {
850 safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
851 hir::HeaderSafety::SafeTargetFeatures
852 } else {
853 safety.into()
854 },
855 abi,
856 constness: hir::Constness::NotConst,
858 asyncness: hir::IsAsync::NotAsync,
859 }
860 }
861 ItemKind::FunctionItem(_)
862 | ItemKind::MethodItem(..)
863 | ItemKind::RequiredMethodItem(..) => {
864 let def_id = self.def_id().unwrap();
865 build_fn_header(def_id, tcx, tcx.asyncness(def_id))
866 }
867 _ => return None,
868 };
869 Some(header)
870 }
871
872 pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option<Visibility<ModId>> {
875 let def_id = match self.item_id {
876 ItemId::Auto { .. } | ItemId::Blanket { .. } => return None,
878 ItemId::DefId(def_id) => def_id,
879 };
880
881 match self.kind {
882 ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) | ItemKind::AttributeItem => {
886 return Some(Visibility::Public);
887 }
888 StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => {
890 return None;
891 }
892 VariantItem(..) | ImplItem(..) => return None,
894 RequiredAssocConstItem(..)
896 | ProvidedAssocConstItem(..)
897 | ImplAssocConstItem(..)
898 | AssocTypeItem(..)
899 | RequiredAssocTypeItem(..)
900 | RequiredMethodItem(..)
901 | MethodItem(..) => {
902 match tcx.associated_item(def_id).container {
903 ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) => {
906 return None;
907 }
908 ty::AssocContainer::InherentImpl => {}
909 }
910 }
911 _ => {}
912 }
913 let def_id = match self.inline_stmt_id {
914 Some(inlined) => inlined.to_def_id(),
915 None => def_id,
916 };
917 Some(tcx.visibility(def_id))
918 }
919
920 pub fn is_doc_hidden(&self) -> bool {
921 self.attrs.is_doc_hidden()
922 }
923
924 pub fn def_id(&self) -> Option<DefId> {
925 self.item_id.as_def_id()
926 }
927}
928
929#[derive(Clone, Debug)]
930pub(crate) enum ItemKind {
931 ExternCrateItem {
932 src: Option<Symbol>,
934 },
935 ImportItem(Import),
936 StructItem(Struct),
937 UnionItem(Union),
938 EnumItem(Enum),
939 FunctionItem(Box<Function>),
940 ModuleItem(Module),
941 TypeAliasItem(Box<TypeAlias>),
942 StaticItem(Static),
943 TraitItem(Box<Trait>),
944 TraitAliasItem(TraitAlias),
945 ImplItem(Box<Impl>),
946 PlaceholderImplItem,
949 RequiredMethodItem(Box<Function>, Defaultness),
951 MethodItem(Box<Function>, Defaultness),
955 StructFieldItem(Type),
956 VariantItem(Variant),
957 ForeignFunctionItem(Box<Function>, hir::Safety),
959 ForeignStaticItem(Static, hir::Safety),
961 ForeignTypeItem,
963 MacroItem(Macro, MacroKinds),
970 ProcMacroItem(ProcMacro),
971 PrimitiveItem(PrimitiveType),
972 RequiredAssocConstItem(Generics, Box<Type>),
974 ConstantItem(Box<Constant>),
975 ProvidedAssocConstItem(Box<Constant>),
977 ImplAssocConstItem(Box<Constant>),
979 RequiredAssocTypeItem(Generics, Vec<GenericBound>),
983 AssocTypeItem(Box<TypeAlias>, Vec<GenericBound>),
985 StrippedItem(Box<ItemKind>),
987 KeywordItem,
990 AttributeItem,
993}
994
995impl ItemKind {
996 pub(crate) fn inner_items(&self) -> impl Iterator<Item = &Item> {
999 match self {
1000 StructItem(s) => s.fields.iter(),
1001 UnionItem(u) => u.fields.iter(),
1002 VariantItem(v) => match &v.kind {
1003 VariantKind::CLike => [].iter(),
1004 VariantKind::Tuple(t) => t.iter(),
1005 VariantKind::Struct(s) => s.fields.iter(),
1006 },
1007 EnumItem(e) => e.variants.iter(),
1008 TraitItem(t) => t.items.iter(),
1009 ImplItem(i) => i.items.iter(),
1010 ModuleItem(m) => m.items.iter(),
1011 ExternCrateItem { .. }
1012 | ImportItem(_)
1013 | FunctionItem(_)
1014 | TypeAliasItem(_)
1015 | StaticItem(_)
1016 | ConstantItem(_)
1017 | TraitAliasItem(_)
1018 | RequiredMethodItem(..)
1019 | MethodItem(..)
1020 | StructFieldItem(_)
1021 | ForeignFunctionItem(_, _)
1022 | ForeignStaticItem(_, _)
1023 | ForeignTypeItem
1024 | MacroItem(..)
1025 | ProcMacroItem(_)
1026 | PrimitiveItem(_)
1027 | RequiredAssocConstItem(..)
1028 | ProvidedAssocConstItem(..)
1029 | ImplAssocConstItem(..)
1030 | RequiredAssocTypeItem(..)
1031 | AssocTypeItem(..)
1032 | StrippedItem(_)
1033 | KeywordItem
1034 | AttributeItem
1035 | PlaceholderImplItem => [].iter(),
1036 }
1037 }
1038}
1039
1040#[derive(Clone, Debug)]
1041pub(crate) struct Module {
1042 pub(crate) items: Vec<Item>,
1043 pub(crate) span: Span,
1044}
1045
1046#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1050pub(crate) struct ItemLink {
1051 pub(crate) link: Box<str>,
1053 pub(crate) link_text: Box<str>,
1058 pub(crate) page_id: DefId,
1062 pub(crate) fragment: Option<UrlFragment>,
1064}
1065
1066pub struct RenderedLink {
1067 pub(crate) original_text: Box<str>,
1071 pub(crate) new_text: Box<str>,
1073 pub(crate) href: String,
1075 pub(crate) tooltip: String,
1077}
1078
1079#[derive(Clone, Debug, Default)]
1082pub(crate) struct Attributes {
1083 pub(crate) doc_strings: Vec<DocFragment>,
1084 pub(crate) other_attrs: ThinVec<hir::Attribute>,
1085}
1086
1087impl Attributes {
1088 pub(crate) fn has_doc_flag<F: Fn(&DocAttribute) -> bool>(&self, callback: F) -> bool {
1089 find_attr!(&self.other_attrs, Doc(d) if callback(d))
1090 }
1091
1092 pub(crate) fn is_doc_hidden(&self) -> bool {
1093 find_attr!(&self.other_attrs, Doc(d) if d.hidden.is_some())
1094 }
1095
1096 pub(crate) fn from_hir(attrs: &[hir::Attribute]) -> Attributes {
1097 Attributes::from_hir_iter(attrs.iter().map(|attr| (attr, None)), false)
1098 }
1099
1100 pub(crate) fn from_hir_with_additional(
1101 attrs: &[hir::Attribute],
1102 (additional_attrs, def_id): (&[hir::Attribute], DefId),
1103 ) -> Attributes {
1104 let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id)));
1106 let attrs2 = attrs.iter().map(|attr| (attr, None));
1107 Attributes::from_hir_iter(attrs1.chain(attrs2), false)
1108 }
1109
1110 pub(crate) fn from_hir_iter<'a>(
1111 attrs: impl Iterator<Item = (&'a hir::Attribute, Option<DefId>)>,
1112 doc_only: bool,
1113 ) -> Attributes {
1114 let (doc_strings, other_attrs) = attrs_to_doc_fragments(attrs, doc_only);
1115 Attributes { doc_strings, other_attrs }
1116 }
1117
1118 pub(crate) fn doc_value(&self) -> String {
1120 self.opt_doc_value().unwrap_or_default()
1121 }
1122
1123 pub(crate) fn opt_doc_value(&self) -> Option<String> {
1127 (!self.doc_strings.is_empty()).then(|| {
1128 let mut res = String::new();
1129 for frag in &self.doc_strings {
1130 add_doc_fragment(&mut res, frag);
1131 }
1132 res.pop();
1133 res
1134 })
1135 }
1136
1137 pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> {
1138 let mut aliases = FxIndexSet::default();
1139
1140 for attr in &self.other_attrs {
1141 if let Attribute::Parsed(AttributeKind::Doc(d)) = attr {
1142 for (alias, _) in &d.aliases {
1143 aliases.insert(*alias);
1144 }
1145 }
1146 }
1147 aliases.into_iter().collect::<Vec<_>>().into()
1148 }
1149
1150 pub(crate) fn merge_with(&mut self, other: Self) {
1151 let Self { doc_strings, other_attrs } = other;
1152 self.doc_strings.extend(doc_strings);
1153 self.other_attrs.extend(other_attrs);
1154 }
1155}
1156
1157#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1158pub(crate) enum GenericBound {
1159 TraitBound(PolyTrait, hir::TraitBoundModifiers),
1160 Outlives(Lifetime),
1161 Use(Vec<PreciseCapturingArg>),
1163}
1164
1165impl GenericBound {
1166 pub(crate) fn sized(cx: &mut DocContext<'_>) -> GenericBound {
1167 Self::sized_with(cx, hir::TraitBoundModifiers::NONE)
1168 }
1169
1170 pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1171 Self::sized_with(
1172 cx,
1173 hir::TraitBoundModifiers {
1174 polarity: hir::BoundPolarity::Maybe(DUMMY_SP),
1175 constness: hir::BoundConstness::Never,
1176 },
1177 )
1178 }
1179
1180 fn sized_with(cx: &mut DocContext<'_>, modifiers: hir::TraitBoundModifiers) -> GenericBound {
1181 let did = cx.tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
1182 let empty = ty::Binder::dummy(ty::GenericArgs::empty());
1183 let path = clean_middle_path(cx, did, false, ThinVec::new(), empty);
1184 inline::record_extern_fqn(cx, did, ItemType::Trait);
1185 GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifiers)
1186 }
1187
1188 pub(crate) fn is_trait_bound(&self) -> bool {
1189 matches!(self, Self::TraitBound(..))
1190 }
1191
1192 pub(crate) fn is_sized_bound(&self, tcx: TyCtxt<'_>) -> bool {
1193 self.is_bounded_by_lang_item(tcx, LangItem::Sized)
1194 }
1195
1196 pub(crate) fn is_meta_sized_bound(&self, tcx: TyCtxt<'_>) -> bool {
1197 self.is_bounded_by_lang_item(tcx, LangItem::MetaSized)
1198 }
1199
1200 fn is_bounded_by_lang_item(&self, tcx: TyCtxt<'_>, lang_item: LangItem) -> bool {
1201 if let GenericBound::TraitBound(poly_trait_ref, rustc_hir::TraitBoundModifiers::NONE) = self
1202 && tcx.is_lang_item(poly_trait_ref.trait_.def_id(), lang_item)
1203 {
1204 return true;
1205 }
1206 false
1207 }
1208
1209 pub(crate) fn get_trait_path(&self) -> Option<Path> {
1210 if let GenericBound::TraitBound(poly_trait_ref, _) = self {
1211 Some(poly_trait_ref.trait_.clone())
1212 } else {
1213 None
1214 }
1215 }
1216}
1217
1218#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1219pub(crate) struct Lifetime(pub Symbol);
1220
1221impl Lifetime {
1222 pub(crate) fn statik() -> Lifetime {
1223 Lifetime(kw::StaticLifetime)
1224 }
1225
1226 pub(crate) fn elided() -> Lifetime {
1227 Lifetime(kw::UnderscoreLifetime)
1228 }
1229}
1230
1231#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1232pub(crate) enum PreciseCapturingArg {
1233 Lifetime(Lifetime),
1234 Param(Symbol),
1235}
1236
1237impl PreciseCapturingArg {
1238 pub(crate) fn name(self) -> Symbol {
1239 match self {
1240 PreciseCapturingArg::Lifetime(lt) => lt.0,
1241 PreciseCapturingArg::Param(param) => param,
1242 }
1243 }
1244}
1245
1246#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1247pub(crate) enum WherePredicate {
1248 BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
1249 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1250 ProjectionPredicate { lhs: QPathData, rhs: Term },
1251}
1252
1253impl WherePredicate {
1254 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1255 match self {
1256 WherePredicate::BoundPredicate { bounds, .. } => Some(bounds),
1257 WherePredicate::RegionPredicate { bounds, .. } => Some(bounds),
1258 _ => None,
1259 }
1260 }
1261}
1262
1263#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1264pub(crate) enum GenericParamDefKind {
1265 Lifetime { outlives: ThinVec<Lifetime> },
1266 Type { bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
1267 Const { ty: Box<Type>, default: Option<Box<String>> },
1269}
1270
1271impl GenericParamDefKind {
1272 pub(crate) fn is_type(&self) -> bool {
1273 matches!(self, GenericParamDefKind::Type { .. })
1274 }
1275}
1276
1277#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1278pub(crate) struct GenericParamDef {
1279 pub(crate) name: Symbol,
1280 pub(crate) def_id: DefId,
1281 pub(crate) kind: GenericParamDefKind,
1282}
1283
1284impl GenericParamDef {
1285 pub(crate) fn lifetime(def_id: DefId, name: Symbol) -> Self {
1286 Self { name, def_id, kind: GenericParamDefKind::Lifetime { outlives: ThinVec::new() } }
1287 }
1288
1289 pub(crate) fn is_synthetic_param(&self) -> bool {
1290 match self.kind {
1291 GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
1292 GenericParamDefKind::Type { synthetic, .. } => synthetic,
1293 }
1294 }
1295
1296 pub(crate) fn is_type(&self) -> bool {
1297 self.kind.is_type()
1298 }
1299
1300 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1301 match self.kind {
1302 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1303 _ => None,
1304 }
1305 }
1306}
1307
1308#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
1310pub(crate) struct Generics {
1311 pub(crate) params: ThinVec<GenericParamDef>,
1312 pub(crate) where_predicates: ThinVec<WherePredicate>,
1313}
1314
1315impl Generics {
1316 pub(crate) fn is_empty(&self) -> bool {
1317 self.params.is_empty() && self.where_predicates.is_empty()
1318 }
1319}
1320
1321#[derive(Clone, Debug)]
1322pub(crate) struct Function {
1323 pub(crate) decl: FnDecl,
1324 pub(crate) generics: Generics,
1325}
1326
1327#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1328pub(crate) struct FnDecl {
1329 pub(crate) inputs: Vec<Parameter>,
1330 pub(crate) output: Type,
1331 pub(crate) c_variadic: bool,
1332}
1333
1334impl FnDecl {
1335 pub(crate) fn receiver_type(&self) -> Option<&Type> {
1336 self.inputs.first().and_then(|v| v.to_receiver())
1337 }
1338}
1339
1340#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1342pub(crate) struct Parameter {
1343 pub(crate) name: Option<Symbol>,
1344 pub(crate) type_: Type,
1345 pub(crate) is_const: bool,
1348}
1349
1350impl Parameter {
1351 pub(crate) fn to_receiver(&self) -> Option<&Type> {
1352 if self.name == Some(kw::SelfLower) { Some(&self.type_) } else { None }
1353 }
1354}
1355
1356#[derive(Clone, Debug)]
1357pub(crate) struct Trait {
1358 pub(crate) def_id: DefId,
1359 pub(crate) items: Vec<Item>,
1360 pub(crate) generics: Generics,
1361 pub(crate) bounds: Vec<GenericBound>,
1362}
1363
1364impl Trait {
1365 pub(crate) fn is_auto(&self, tcx: TyCtxt<'_>) -> bool {
1366 tcx.trait_is_auto(self.def_id)
1367 }
1368 pub(crate) fn is_notable_trait(&self, tcx: TyCtxt<'_>) -> bool {
1369 tcx.is_doc_notable_trait(self.def_id)
1370 }
1371 pub(crate) fn safety(&self, tcx: TyCtxt<'_>) -> hir::Safety {
1372 tcx.trait_def(self.def_id).safety
1373 }
1374 pub(crate) fn is_dyn_compatible(&self, tcx: TyCtxt<'_>) -> bool {
1375 tcx.is_dyn_compatible(self.def_id)
1376 }
1377 pub(crate) fn is_deprecated(&self, tcx: TyCtxt<'_>) -> bool {
1378 tcx.lookup_deprecation(self.def_id).is_some_and(|deprecation| deprecation.is_in_effect())
1379 }
1380}
1381
1382#[derive(Clone, Debug)]
1383pub(crate) struct TraitAlias {
1384 pub(crate) generics: Generics,
1385 pub(crate) bounds: Vec<GenericBound>,
1386}
1387
1388#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1390pub(crate) struct PolyTrait {
1391 pub(crate) trait_: Path,
1392 pub(crate) generic_params: Vec<GenericParamDef>,
1393}
1394
1395#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1397pub(crate) enum Type {
1398 Path {
1403 path: Path,
1404 },
1405 DynTrait(Vec<PolyTrait>, Option<Lifetime>),
1407 Generic(Symbol),
1409 SelfTy,
1411 Primitive(PrimitiveType),
1413 BareFunction(Box<BareFunctionDecl>),
1415 Tuple(Vec<Type>),
1417 Slice(Box<Type>),
1419 Array(Box<Type>, Box<str>),
1423 Pat(Box<Type>, Box<str>),
1424 FieldOf(Box<Type>, Box<str>),
1425 RawPointer(Mutability, Box<Type>),
1427 BorrowedRef {
1429 lifetime: Option<Lifetime>,
1430 mutability: Mutability,
1431 type_: Box<Type>,
1432 },
1433
1434 QPath(Box<QPathData>),
1436
1437 Infer,
1439
1440 ImplTrait(Vec<GenericBound>),
1442
1443 UnsafeBinder(Box<UnsafeBinderTy>),
1444}
1445
1446impl Type {
1447 pub(crate) fn without_borrowed_ref(&self) -> &Type {
1449 let mut result = self;
1450 while let Type::BorrowedRef { type_, .. } = result {
1451 result = type_;
1452 }
1453 result
1454 }
1455
1456 pub(crate) fn is_borrowed_ref(&self) -> bool {
1457 matches!(self, Type::BorrowedRef { .. })
1458 }
1459
1460 fn is_type_alias(&self) -> bool {
1461 matches!(self, Type::Path { path: Path { res: Res::Def(DefKind::TyAlias, _), .. } })
1462 }
1463
1464 pub(crate) fn is_doc_subtype_of(&self, other: &Self, cache: &Cache) -> bool {
1485 let (self_cleared, other_cleared) = if !self.is_borrowed_ref() || !other.is_borrowed_ref() {
1488 (self.without_borrowed_ref(), other.without_borrowed_ref())
1489 } else {
1490 (self, other)
1491 };
1492
1493 if self_cleared.is_type_alias() || other_cleared.is_type_alias() {
1499 return true;
1500 }
1501
1502 match (self_cleared, other_cleared) {
1503 (Type::Tuple(a), Type::Tuple(b)) => {
1505 a.iter().eq_by(b, |a, b| a.is_doc_subtype_of(b, cache))
1506 }
1507 (Type::Slice(a), Type::Slice(b)) => a.is_doc_subtype_of(b, cache),
1508 (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_doc_subtype_of(b, cache),
1509 (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
1510 mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache)
1511 }
1512 (
1513 Type::BorrowedRef { mutability, type_, .. },
1514 Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
1515 ) => mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache),
1516 (Type::Infer, _) | (_, Type::Infer) => true,
1518 (_, Type::Generic(_)) => true,
1521 (Type::Generic(_), _) => false,
1522 (Type::SelfTy, Type::SelfTy) => true,
1524 (Type::Path { path: a }, Type::Path { path: b }) => {
1526 a.def_id() == b.def_id()
1527 && a.generics()
1528 .zip(b.generics())
1529 .map(|(ag, bg)| ag.zip(bg).all(|(at, bt)| at.is_doc_subtype_of(bt, cache)))
1530 .unwrap_or(true)
1531 }
1532 (a, b) => a
1534 .def_id(cache)
1535 .and_then(|a| Some((a, b.def_id(cache)?)))
1536 .map(|(a, b)| a == b)
1537 .unwrap_or(false),
1538 }
1539 }
1540
1541 pub(crate) fn primitive_type(&self) -> Option<PrimitiveType> {
1542 match *self {
1543 Primitive(p) | BorrowedRef { type_: Primitive(p), .. } => Some(p),
1544 Slice(..) | BorrowedRef { type_: Slice(..), .. } => Some(PrimitiveType::Slice),
1545 Array(..) | BorrowedRef { type_: Array(..), .. } => Some(PrimitiveType::Array),
1546 Tuple(ref tys) => {
1547 if tys.is_empty() {
1548 Some(PrimitiveType::Unit)
1549 } else {
1550 Some(PrimitiveType::Tuple)
1551 }
1552 }
1553 RawPointer(..) => Some(PrimitiveType::RawPointer),
1554 BareFunction(..) => Some(PrimitiveType::Fn),
1555 _ => None,
1556 }
1557 }
1558
1559 pub(crate) fn sugared_async_return_type(self) -> Type {
1569 if let Type::ImplTrait(mut v) = self
1570 && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = v.pop()
1571 && let Some(segment) = trait_.segments.pop()
1572 && let GenericArgs::AngleBracketed { mut constraints, .. } = segment.args
1573 && let Some(constraint) = constraints.pop()
1574 && let AssocItemConstraintKind::Equality { term } = constraint.kind
1575 && let Term::Type(ty) = term
1576 {
1577 ty
1578 } else {
1579 panic!("unexpected async fn return type")
1580 }
1581 }
1582
1583 pub(crate) fn is_assoc_ty(&self) -> bool {
1585 match self {
1586 Type::Path { path, .. } => path.is_assoc_ty(),
1587 _ => false,
1588 }
1589 }
1590
1591 pub(crate) fn is_self_type(&self) -> bool {
1592 matches!(*self, Type::SelfTy)
1593 }
1594
1595 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
1596 match self {
1597 Type::Path { path, .. } => path.generic_args(),
1598 _ => None,
1599 }
1600 }
1601
1602 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
1603 match self {
1604 Type::Path { path, .. } => path.generics(),
1605 _ => None,
1606 }
1607 }
1608
1609 pub(crate) fn is_full_generic(&self) -> bool {
1610 matches!(self, Type::Generic(_))
1611 }
1612
1613 pub(crate) fn is_unit(&self) -> bool {
1614 matches!(self, Type::Tuple(v) if v.is_empty())
1615 }
1616
1617 pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
1621 let t: PrimitiveType = match self {
1622 Type::Path { path } => return Some(path.def_id()),
1623 DynTrait(bounds, _) => return bounds.first().map(|b| b.trait_.def_id()),
1624 Primitive(p) => return cache.primitive_locations.get(p).cloned(),
1625 BorrowedRef { type_: Generic(..), .. } => PrimitiveType::Reference,
1626 BorrowedRef { type_, .. } => return type_.def_id(cache),
1627 Tuple(tys) => {
1628 if tys.is_empty() {
1629 PrimitiveType::Unit
1630 } else {
1631 PrimitiveType::Tuple
1632 }
1633 }
1634 BareFunction(..) => PrimitiveType::Fn,
1635 Slice(..) => PrimitiveType::Slice,
1636 Array(..) => PrimitiveType::Array,
1637 Type::Pat(..) => PrimitiveType::Pat,
1638 Type::FieldOf(..) => PrimitiveType::FieldOf,
1639 RawPointer(..) => PrimitiveType::RawPointer,
1640 QPath(QPathData { self_type, .. }) => return self_type.def_id(cache),
1641 Generic(_) | SelfTy | Infer | ImplTrait(_) | UnsafeBinder(_) => return None,
1642 };
1643 Primitive(t).def_id(cache)
1644 }
1645}
1646
1647#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1648pub(crate) struct QPathData {
1649 pub assoc: PathSegment,
1650 pub self_type: Type,
1651 pub should_fully_qualify: bool,
1653 pub trait_: Option<Path>,
1654}
1655
1656#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1663pub(crate) enum PrimitiveType {
1664 Isize,
1665 I8,
1666 I16,
1667 I32,
1668 I64,
1669 I128,
1670 Usize,
1671 U8,
1672 U16,
1673 U32,
1674 U64,
1675 U128,
1676 F16,
1677 F32,
1678 F64,
1679 F128,
1680 Char,
1681 Bool,
1682 Str,
1683 Slice,
1684 Array,
1685 Pat,
1686 FieldOf,
1687 Tuple,
1688 Unit,
1689 RawPointer,
1690 Reference,
1691 Fn,
1692 Never,
1693}
1694
1695type SimplifiedTypes = FxIndexMap<PrimitiveType, ArrayVec<SimplifiedType, 3>>;
1696impl PrimitiveType {
1697 pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1698 use ast::{FloatTy, IntTy, UintTy};
1699 match prim {
1700 hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1701 hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1702 hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1703 hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1704 hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1705 hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1706 hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1707 hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1708 hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1709 hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1710 hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1711 hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1712 hir::PrimTy::Float(FloatTy::F16) => PrimitiveType::F16,
1713 hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1714 hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1715 hir::PrimTy::Float(FloatTy::F128) => PrimitiveType::F128,
1716 hir::PrimTy::Str => PrimitiveType::Str,
1717 hir::PrimTy::Bool => PrimitiveType::Bool,
1718 hir::PrimTy::Char => PrimitiveType::Char,
1719 }
1720 }
1721
1722 pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1723 match s {
1724 sym::isize => Some(PrimitiveType::Isize),
1725 sym::i8 => Some(PrimitiveType::I8),
1726 sym::i16 => Some(PrimitiveType::I16),
1727 sym::i32 => Some(PrimitiveType::I32),
1728 sym::i64 => Some(PrimitiveType::I64),
1729 sym::i128 => Some(PrimitiveType::I128),
1730 sym::usize => Some(PrimitiveType::Usize),
1731 sym::u8 => Some(PrimitiveType::U8),
1732 sym::u16 => Some(PrimitiveType::U16),
1733 sym::u32 => Some(PrimitiveType::U32),
1734 sym::u64 => Some(PrimitiveType::U64),
1735 sym::u128 => Some(PrimitiveType::U128),
1736 sym::bool => Some(PrimitiveType::Bool),
1737 sym::char => Some(PrimitiveType::Char),
1738 sym::str => Some(PrimitiveType::Str),
1739 sym::f16 => Some(PrimitiveType::F16),
1740 sym::f32 => Some(PrimitiveType::F32),
1741 sym::f64 => Some(PrimitiveType::F64),
1742 sym::f128 => Some(PrimitiveType::F128),
1743 sym::array => Some(PrimitiveType::Array),
1744 sym::slice => Some(PrimitiveType::Slice),
1745 sym::tuple => Some(PrimitiveType::Tuple),
1746 sym::unit => Some(PrimitiveType::Unit),
1747 sym::pointer => Some(PrimitiveType::RawPointer),
1748 sym::reference => Some(PrimitiveType::Reference),
1749 kw::Fn => Some(PrimitiveType::Fn),
1750 sym::never => Some(PrimitiveType::Never),
1751 _ => None,
1752 }
1753 }
1754
1755 pub(crate) fn from_ty(ty: Ty<'_>) -> Option<Self> {
1756 match ty.kind() {
1757 ty::Array(..) => Some(Self::Array),
1758 ty::Bool => Some(Self::Bool),
1759 ty::Char => Some(Self::Char),
1760 ty::FnDef(..) | ty::FnPtr(..) => Some(Self::Fn),
1761 ty::Int(int) => Some(Self::from(*int)),
1762 ty::Uint(uint) => Some(Self::from(*uint)),
1763 ty::Float(float) => Some(Self::from(*float)),
1764 ty::Never => Some(Self::Never),
1765 ty::Pat(..) => Some(Self::Pat),
1766 ty::RawPtr(..) => Some(Self::RawPointer),
1767 ty::Ref(..) => Some(Self::Reference),
1768 ty::Slice(..) => Some(Self::Slice),
1769 ty::Str => Some(Self::Str),
1770 ty::Tuple(elems) if elems.is_empty() => Some(Self::Unit),
1771 ty::Tuple(_) => Some(Self::Tuple),
1772 ty::Adt(..)
1773 | ty::Alias(_, ..)
1774 | ty::Bound(..)
1775 | ty::Closure(..)
1776 | ty::Coroutine(..)
1777 | ty::CoroutineClosure(..)
1778 | ty::CoroutineWitness(..)
1779 | ty::Dynamic(..)
1780 | ty::Error(..)
1781 | ty::Foreign(..)
1782 | ty::Infer(..)
1783 | ty::Param(..)
1784 | ty::Placeholder(..)
1785 | ty::UnsafeBinder(..) => None,
1786 }
1787 }
1788
1789 pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
1790 use PrimitiveType::*;
1791 use ty::{FloatTy, IntTy, UintTy};
1792 static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
1793
1794 let single = |x| iter::once(x).collect();
1795 CELL.get_or_init(move || {
1796 map! {
1797 Isize => single(SimplifiedType::Int(IntTy::Isize)),
1798 I8 => single(SimplifiedType::Int(IntTy::I8)),
1799 I16 => single(SimplifiedType::Int(IntTy::I16)),
1800 I32 => single(SimplifiedType::Int(IntTy::I32)),
1801 I64 => single(SimplifiedType::Int(IntTy::I64)),
1802 I128 => single(SimplifiedType::Int(IntTy::I128)),
1803 Usize => single(SimplifiedType::Uint(UintTy::Usize)),
1804 U8 => single(SimplifiedType::Uint(UintTy::U8)),
1805 U16 => single(SimplifiedType::Uint(UintTy::U16)),
1806 U32 => single(SimplifiedType::Uint(UintTy::U32)),
1807 U64 => single(SimplifiedType::Uint(UintTy::U64)),
1808 U128 => single(SimplifiedType::Uint(UintTy::U128)),
1809 F16 => single(SimplifiedType::Float(FloatTy::F16)),
1810 F32 => single(SimplifiedType::Float(FloatTy::F32)),
1811 F64 => single(SimplifiedType::Float(FloatTy::F64)),
1812 F128 => single(SimplifiedType::Float(FloatTy::F128)),
1813 Str => single(SimplifiedType::Str),
1814 Bool => single(SimplifiedType::Bool),
1815 Char => single(SimplifiedType::Char),
1816 Array => single(SimplifiedType::Array),
1817 Slice => single(SimplifiedType::Slice),
1818 Tuple => [SimplifiedType::Tuple(1), SimplifiedType::Tuple(2), SimplifiedType::Tuple(3)].into(),
1824 Unit => single(SimplifiedType::Tuple(0)),
1825 RawPointer => [SimplifiedType::Ptr(Mutability::Not), SimplifiedType::Ptr(Mutability::Mut)].into_iter().collect(),
1826 Reference => [SimplifiedType::Ref(Mutability::Not), SimplifiedType::Ref(Mutability::Mut)].into_iter().collect(),
1827 Fn => single(SimplifiedType::Function(1)),
1830 Never => single(SimplifiedType::Never),
1831 }
1832 })
1833 }
1834
1835 pub(crate) fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = DefId> + 'tcx {
1836 Self::simplified_types()
1837 .get(self)
1838 .into_iter()
1839 .flatten()
1840 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1841 .copied()
1842 }
1843
1844 pub(crate) fn as_sym(&self) -> Symbol {
1845 use PrimitiveType::*;
1846 match self {
1847 Isize => sym::isize,
1848 I8 => sym::i8,
1849 I16 => sym::i16,
1850 I32 => sym::i32,
1851 I64 => sym::i64,
1852 I128 => sym::i128,
1853 Usize => sym::usize,
1854 U8 => sym::u8,
1855 U16 => sym::u16,
1856 U32 => sym::u32,
1857 U64 => sym::u64,
1858 U128 => sym::u128,
1859 F16 => sym::f16,
1860 F32 => sym::f32,
1861 F64 => sym::f64,
1862 F128 => sym::f128,
1863 Str => sym::str,
1864 Bool => sym::bool,
1865 Char => sym::char,
1866 Array => sym::array,
1867 Pat => sym::pat,
1868 FieldOf => sym::field_of,
1869 Slice => sym::slice,
1870 Tuple => sym::tuple,
1871 Unit => sym::unit,
1872 RawPointer => sym::pointer,
1873 Reference => sym::reference,
1874 Fn => kw::Fn,
1875 Never => sym::never,
1876 }
1877 }
1878
1879 pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxIndexMap<PrimitiveType, DefId> {
1891 static PRIMITIVE_LOCATIONS: OnceCell<FxIndexMap<PrimitiveType, DefId>> = OnceCell::new();
1892 PRIMITIVE_LOCATIONS.get_or_init(|| {
1893 let mut primitive_locations = FxIndexMap::default();
1894 for &crate_num in tcx.crates(()) {
1897 let e = ExternalCrate { crate_num };
1898 let crate_name = e.name(tcx);
1899 debug!(?crate_num, ?crate_name);
1900 for (def_id, prim) in e.primitives(tcx) {
1901 if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1903 continue;
1904 }
1905 primitive_locations.insert(prim, def_id);
1906 }
1907 }
1908 let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1909 for (def_id, prim) in local_primitives {
1910 primitive_locations.insert(prim, def_id);
1911 }
1912 primitive_locations
1913 })
1914 }
1915}
1916
1917impl From<ty::IntTy> for PrimitiveType {
1918 fn from(int_ty: ty::IntTy) -> PrimitiveType {
1919 match int_ty {
1920 ty::IntTy::Isize => PrimitiveType::Isize,
1921 ty::IntTy::I8 => PrimitiveType::I8,
1922 ty::IntTy::I16 => PrimitiveType::I16,
1923 ty::IntTy::I32 => PrimitiveType::I32,
1924 ty::IntTy::I64 => PrimitiveType::I64,
1925 ty::IntTy::I128 => PrimitiveType::I128,
1926 }
1927 }
1928}
1929
1930impl From<ty::UintTy> for PrimitiveType {
1931 fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1932 match uint_ty {
1933 ty::UintTy::Usize => PrimitiveType::Usize,
1934 ty::UintTy::U8 => PrimitiveType::U8,
1935 ty::UintTy::U16 => PrimitiveType::U16,
1936 ty::UintTy::U32 => PrimitiveType::U32,
1937 ty::UintTy::U64 => PrimitiveType::U64,
1938 ty::UintTy::U128 => PrimitiveType::U128,
1939 }
1940 }
1941}
1942
1943impl From<ty::FloatTy> for PrimitiveType {
1944 fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1945 match float_ty {
1946 ty::FloatTy::F16 => PrimitiveType::F16,
1947 ty::FloatTy::F32 => PrimitiveType::F32,
1948 ty::FloatTy::F64 => PrimitiveType::F64,
1949 ty::FloatTy::F128 => PrimitiveType::F128,
1950 }
1951 }
1952}
1953
1954impl From<hir::PrimTy> for PrimitiveType {
1955 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1956 match prim_ty {
1957 hir::PrimTy::Int(int_ty) => int_ty.into(),
1958 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1959 hir::PrimTy::Float(float_ty) => float_ty.into(),
1960 hir::PrimTy::Str => PrimitiveType::Str,
1961 hir::PrimTy::Bool => PrimitiveType::Bool,
1962 hir::PrimTy::Char => PrimitiveType::Char,
1963 }
1964 }
1965}
1966
1967#[derive(Clone, Debug)]
1968pub(crate) struct Struct {
1969 pub(crate) ctor_kind: Option<CtorKind>,
1970 pub(crate) generics: Generics,
1971 pub(crate) fields: ThinVec<Item>,
1972}
1973
1974impl Struct {
1975 pub(crate) fn has_stripped_entries(&self) -> bool {
1976 self.fields.iter().any(|f| f.is_stripped())
1977 }
1978}
1979
1980#[derive(Clone, Debug)]
1981pub(crate) struct Union {
1982 pub(crate) generics: Generics,
1983 pub(crate) fields: Vec<Item>,
1984}
1985
1986impl Union {
1987 pub(crate) fn has_stripped_entries(&self) -> bool {
1988 self.fields.iter().any(|f| f.is_stripped())
1989 }
1990}
1991
1992#[derive(Clone, Debug)]
1996pub(crate) struct VariantStruct {
1997 pub(crate) fields: ThinVec<Item>,
1998}
1999
2000impl VariantStruct {
2001 pub(crate) fn has_stripped_entries(&self) -> bool {
2002 self.fields.iter().any(|f| f.is_stripped())
2003 }
2004}
2005
2006#[derive(Clone, Debug)]
2007pub(crate) struct Enum {
2008 pub(crate) variants: IndexVec<VariantIdx, Item>,
2009 pub(crate) generics: Generics,
2010}
2011
2012impl Enum {
2013 pub(crate) fn has_stripped_entries(&self) -> bool {
2014 self.variants.iter().any(|f| f.is_stripped())
2015 }
2016
2017 pub(crate) fn non_stripped_variants(&self) -> impl Iterator<Item = &Item> {
2018 self.variants.iter().filter(|v| !v.is_stripped())
2019 }
2020}
2021
2022#[derive(Clone, Debug)]
2023pub(crate) struct Variant {
2024 pub kind: VariantKind,
2025 pub discriminant: Option<Discriminant>,
2026}
2027
2028#[derive(Clone, Debug)]
2029pub(crate) enum VariantKind {
2030 CLike,
2031 Tuple(ThinVec<Item>),
2032 Struct(VariantStruct),
2033}
2034
2035impl Variant {
2036 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
2037 match &self.kind {
2038 VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()),
2039 VariantKind::CLike | VariantKind::Tuple(_) => None,
2040 }
2041 }
2042}
2043
2044#[derive(Clone, Debug)]
2045pub(crate) struct Discriminant {
2046 pub(super) expr: Option<BodyId>,
2049 pub(super) value: DefId,
2050}
2051
2052impl Discriminant {
2053 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
2056 self.expr
2057 .map(|body| rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body)))
2058 }
2059 pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String {
2060 print_evaluated_const(tcx, self.value, with_underscores, false).unwrap()
2061 }
2062}
2063
2064#[derive(Copy, Clone, Debug)]
2067pub(crate) struct Span(rustc_span::Span);
2068
2069impl Span {
2070 pub(crate) fn new(sp: rustc_span::Span) -> Self {
2075 Self(sp.source_callsite())
2076 }
2077
2078 pub(crate) fn inner(&self) -> rustc_span::Span {
2079 self.0
2080 }
2081
2082 pub(crate) fn filename(&self, sess: &Session) -> FileName {
2083 sess.source_map().span_to_filename(self.0)
2084 }
2085
2086 pub(crate) fn lo(&self, sess: &Session) -> Loc {
2087 sess.source_map().lookup_char_pos(self.0.lo())
2088 }
2089
2090 pub(crate) fn hi(&self, sess: &Session) -> Loc {
2091 sess.source_map().lookup_char_pos(self.0.hi())
2092 }
2093
2094 pub(crate) fn cnum(&self, sess: &Session) -> CrateNum {
2095 self.lo(sess).file.cnum
2097 }
2098}
2099
2100#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2101pub(crate) struct Path {
2102 pub(crate) res: Res,
2103 pub(crate) segments: ThinVec<PathSegment>,
2104}
2105
2106impl Path {
2107 pub(crate) fn def_id(&self) -> DefId {
2108 self.res.def_id()
2109 }
2110
2111 pub(crate) fn last_opt(&self) -> Option<Symbol> {
2112 self.segments.last().map(|s| s.name)
2113 }
2114
2115 pub(crate) fn last(&self) -> Symbol {
2116 self.last_opt().expect("segments were empty")
2117 }
2118
2119 pub(crate) fn whole_name(&self) -> String {
2120 self.segments
2121 .iter()
2122 .map(|s| if s.name == kw::PathRoot { "" } else { s.name.as_str() })
2123 .intersperse("::")
2124 .collect()
2125 }
2126
2127 pub(crate) fn is_assoc_ty(&self) -> bool {
2129 match self.res {
2130 Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _)
2131 if self.segments.len() != 1 =>
2132 {
2133 true
2134 }
2135 Res::Def(DefKind::AssocTy, _) => true,
2136 _ => false,
2137 }
2138 }
2139
2140 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
2141 self.segments.last().map(|seg| &seg.args)
2142 }
2143
2144 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
2145 self.segments.last().and_then(|seg| {
2146 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2147 Some(args.iter().filter_map(|arg| match arg {
2148 GenericArg::Type(ty) => Some(ty),
2149 _ => None,
2150 }))
2151 } else {
2152 None
2153 }
2154 })
2155 }
2156}
2157
2158#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2159pub(crate) enum GenericArg {
2160 Lifetime(Lifetime),
2161 Type(Type),
2162 Const(Box<ConstantKind>),
2163 Infer,
2164}
2165
2166impl GenericArg {
2167 pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
2168 if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2169 }
2170
2171 pub(crate) fn as_ty(&self) -> Option<&Type> {
2172 if let Self::Type(ty) = self { Some(ty) } else { None }
2173 }
2174}
2175
2176#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2177pub(crate) enum GenericArgs {
2178 AngleBracketed { args: ThinVec<GenericArg>, constraints: ThinVec<AssocItemConstraint> },
2180 Parenthesized { inputs: ThinVec<Type>, output: Option<Box<Type>> },
2182 ReturnTypeNotation,
2184}
2185
2186impl GenericArgs {
2187 pub(crate) fn is_empty(&self) -> bool {
2188 match self {
2189 GenericArgs::AngleBracketed { args, constraints } => {
2190 args.is_empty() && constraints.is_empty()
2191 }
2192 GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
2193 GenericArgs::ReturnTypeNotation => false,
2194 }
2195 }
2196 pub(crate) fn constraints(&self) -> Box<dyn Iterator<Item = AssocItemConstraint> + '_> {
2197 match self {
2198 GenericArgs::AngleBracketed { constraints, .. } => {
2199 Box::new(constraints.iter().cloned())
2200 }
2201 GenericArgs::Parenthesized { output, .. } => Box::new(
2202 output
2203 .as_ref()
2204 .map(|ty| AssocItemConstraint {
2205 assoc: PathSegment {
2206 name: sym::Output,
2207 args: GenericArgs::AngleBracketed {
2208 args: ThinVec::new(),
2209 constraints: ThinVec::new(),
2210 },
2211 },
2212 kind: AssocItemConstraintKind::Equality {
2213 term: Term::Type((**ty).clone()),
2214 },
2215 })
2216 .into_iter(),
2217 ),
2218 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2219 }
2220 }
2221}
2222
2223impl<'a> IntoIterator for &'a GenericArgs {
2224 type IntoIter = Box<dyn Iterator<Item = GenericArg> + 'a>;
2225 type Item = GenericArg;
2226 fn into_iter(self) -> Self::IntoIter {
2227 match self {
2228 GenericArgs::AngleBracketed { args, .. } => Box::new(args.iter().cloned()),
2229 GenericArgs::Parenthesized { inputs, .. } => {
2230 Box::new(inputs.iter().cloned().map(GenericArg::Type))
2232 }
2233 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2234 }
2235 }
2236}
2237
2238#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2239pub(crate) struct PathSegment {
2240 pub(crate) name: Symbol,
2241 pub(crate) args: GenericArgs,
2242}
2243
2244#[derive(Clone, Debug)]
2245pub(crate) enum TypeAliasInnerType {
2246 Enum { variants: IndexVec<VariantIdx, Item>, is_non_exhaustive: bool },
2247 Union { fields: Vec<Item> },
2248 Struct { ctor_kind: Option<CtorKind>, fields: Vec<Item> },
2249}
2250
2251impl TypeAliasInnerType {
2252 fn has_stripped_entries(&self) -> Option<bool> {
2253 Some(match self {
2254 Self::Enum { variants, .. } => variants.iter().any(|v| v.is_stripped()),
2255 Self::Union { fields } | Self::Struct { fields, .. } => {
2256 fields.iter().any(|f| f.is_stripped())
2257 }
2258 })
2259 }
2260}
2261
2262#[derive(Clone, Debug)]
2263pub(crate) struct TypeAlias {
2264 pub(crate) type_: Type,
2265 pub(crate) generics: Generics,
2266 pub(crate) inner_type: Option<TypeAliasInnerType>,
2269 pub(crate) item_type: Option<Type>,
2276}
2277
2278#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2279pub(crate) struct BareFunctionDecl {
2280 pub(crate) safety: hir::Safety,
2281 pub(crate) generic_params: Vec<GenericParamDef>,
2282 pub(crate) decl: FnDecl,
2283 pub(crate) abi: ExternAbi,
2284}
2285
2286#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2287pub(crate) struct UnsafeBinderTy {
2288 pub(crate) generic_params: Vec<GenericParamDef>,
2289 pub(crate) ty: Type,
2290}
2291
2292#[derive(Clone, Debug)]
2293pub(crate) struct Static {
2294 pub(crate) type_: Box<Type>,
2295 pub(crate) mutability: Mutability,
2296 pub(crate) expr: Option<BodyId>,
2297}
2298
2299#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2300pub(crate) struct Constant {
2301 pub(crate) generics: Generics,
2302 pub(crate) kind: ConstantKind,
2303 pub(crate) type_: Type,
2304}
2305
2306#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2307pub(crate) enum Term {
2308 Type(Type),
2309 Constant(ConstantKind),
2310}
2311
2312impl Term {
2313 pub(crate) fn ty(&self) -> Option<&Type> {
2314 if let Term::Type(ty) = self { Some(ty) } else { None }
2315 }
2316}
2317
2318impl From<Type> for Term {
2319 fn from(ty: Type) -> Self {
2320 Term::Type(ty)
2321 }
2322}
2323
2324#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2325pub(crate) enum ConstantKind {
2326 TyConst { expr: Box<str> },
2332 Path { path: Box<str> },
2335 Anonymous { body: BodyId },
2339 Extern { def_id: DefId },
2341 Local { def_id: DefId, body: BodyId },
2343 Infer,
2345}
2346
2347impl ConstantKind {
2348 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2349 match *self {
2350 ConstantKind::TyConst { ref expr } => expr.to_string(),
2351 ConstantKind::Path { ref path } => path.to_string(),
2352 ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2353 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2354 rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body))
2355 }
2356 ConstantKind::Infer => "_".to_string(),
2357 }
2358 }
2359
2360 pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2361 match *self {
2362 ConstantKind::TyConst { .. }
2363 | ConstantKind::Path { .. }
2364 | ConstantKind::Anonymous { .. }
2365 | ConstantKind::Infer => None,
2366 ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2367 print_evaluated_const(tcx, def_id, true, true)
2368 }
2369 }
2370 }
2371
2372 pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2373 match *self {
2374 ConstantKind::TyConst { .. }
2375 | ConstantKind::Extern { .. }
2376 | ConstantKind::Path { .. }
2377 | ConstantKind::Infer => false,
2378 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2379 is_literal_expr(tcx, body.hir_id)
2380 }
2381 }
2382 }
2383}
2384
2385#[derive(Clone, Debug)]
2386pub(crate) struct Impl {
2387 pub(crate) safety: hir::Safety,
2388 pub(crate) generics: Generics,
2389 pub(crate) trait_: Option<Path>,
2390 pub(crate) for_: Type,
2391 pub(crate) items: Vec<Item>,
2392 pub(crate) polarity: ty::ImplPolarity,
2393 pub(crate) kind: ImplKind,
2394 pub(crate) is_deprecated: bool,
2395}
2396
2397impl Impl {
2398 pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxIndexSet<Symbol> {
2399 self.trait_
2400 .as_ref()
2401 .map(|t| t.def_id())
2402 .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name()).collect())
2403 .unwrap_or_default()
2404 }
2405
2406 pub(crate) fn is_negative_trait_impl(&self) -> bool {
2407 matches!(self.polarity, ty::ImplPolarity::Negative)
2408 }
2409}
2410
2411#[derive(Clone, Debug)]
2412pub(crate) enum ImplKind {
2413 Normal,
2414 Auto,
2415 FakeVariadic,
2416 Blanket(Box<Type>),
2417}
2418
2419impl ImplKind {
2420 pub(crate) fn is_auto(&self) -> bool {
2421 matches!(self, ImplKind::Auto)
2422 }
2423
2424 pub(crate) fn is_blanket(&self) -> bool {
2425 matches!(self, ImplKind::Blanket(_))
2426 }
2427
2428 pub(crate) fn is_fake_variadic(&self) -> bool {
2429 matches!(self, ImplKind::FakeVariadic)
2430 }
2431
2432 pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
2433 match self {
2434 ImplKind::Blanket(ty) => Some(ty),
2435 _ => None,
2436 }
2437 }
2438}
2439
2440#[derive(Clone, Debug)]
2441pub(crate) struct Import {
2442 pub(crate) kind: ImportKind,
2443 pub(crate) source: ImportSource,
2445 pub(crate) should_be_displayed: bool,
2446}
2447
2448impl Import {
2449 pub(crate) fn new_simple(
2450 name: Symbol,
2451 source: ImportSource,
2452 should_be_displayed: bool,
2453 ) -> Self {
2454 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2455 }
2456
2457 pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2458 Self { kind: ImportKind::Glob, source, should_be_displayed }
2459 }
2460
2461 pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool {
2462 self.source.did.is_some_and(|did| tcx.is_doc_hidden(did))
2463 }
2464}
2465
2466#[derive(Clone, Debug)]
2467pub(crate) enum ImportKind {
2468 Simple(Symbol),
2470 Glob,
2472}
2473
2474#[derive(Clone, Debug)]
2475pub(crate) struct ImportSource {
2476 pub(crate) path: Path,
2477 pub(crate) did: Option<DefId>,
2478}
2479
2480#[derive(Clone, Debug)]
2481pub(crate) struct Macro {
2482 pub(crate) source: String,
2483 pub(crate) macro_rules: bool,
2485}
2486
2487#[derive(Clone, Debug)]
2488pub(crate) struct ProcMacro {
2489 pub(crate) kind: MacroKind,
2490 pub(crate) helpers: Vec<Symbol>,
2491}
2492
2493#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2504pub(crate) struct AssocItemConstraint {
2505 pub(crate) assoc: PathSegment,
2506 pub(crate) kind: AssocItemConstraintKind,
2507}
2508
2509#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2511pub(crate) enum AssocItemConstraintKind {
2512 Equality { term: Term },
2513 Bound { bounds: Vec<GenericBound> },
2514}
2515
2516#[cfg(target_pointer_width = "64")]
2518mod size_asserts {
2519 use rustc_data_structures::static_assert_size;
2520
2521 use super::*;
2522 static_assert_size!(Crate, 16); static_assert_size!(DocFragment, 48);
2525 static_assert_size!(GenericArg, 32);
2526 static_assert_size!(GenericArgs, 24);
2527 static_assert_size!(GenericParamDef, 40);
2528 static_assert_size!(Generics, 16);
2529 static_assert_size!(Item, 8);
2530 static_assert_size!(ItemInner, 136);
2531 static_assert_size!(ItemKind, 48);
2532 static_assert_size!(PathSegment, 32);
2533 static_assert_size!(Type, 32);
2534 }