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