1use std::hash::Hash;
2use std::path::PathBuf;
3use std::sync::{Arc, OnceLock as OnceCell};
4use std::{fmt, iter};
5
6use arrayvec::ArrayVec;
7use itertools::Either;
8use rustc_abi::{ExternAbi, VariantIdx};
9use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
10use rustc_data_structures::thin_vec::ThinVec;
11use rustc_hir::attrs::{AttributeKind, DeprecatedSince, Deprecation};
12use rustc_hir::def::{CtorKind, DefKind, Res};
13use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
14use rustc_hir::lang_items::LangItem;
15use rustc_hir::{BodyId, ConstStability, Mutability, Stability, StableSince, find_attr};
16use rustc_index::IndexVec;
17use rustc_metadata::rendered_const;
18use rustc_middle::span_bug;
19use rustc_middle::ty::fast_reject::SimplifiedType;
20use rustc_middle::ty::{self, TyCtxt, Visibility};
21use rustc_resolve::rustdoc::{
22 DocFragment, add_doc_fragment, attrs_to_doc_fragments, inner_docs, span_of_fragments,
23};
24use rustc_session::Session;
25use rustc_span::hygiene::MacroKind;
26use rustc_span::symbol::{Symbol, kw, sym};
27use rustc_span::{DUMMY_SP, FileName, Loc};
28use tracing::{debug, trace};
29use {rustc_ast as ast, rustc_hir as hir};
30
31pub(crate) use self::ItemKind::*;
32pub(crate) use self::Type::{
33 Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath,
34 RawPointer, SelfTy, Slice, Tuple, UnsafeBinder,
35};
36use crate::clean::cfg::Cfg;
37use crate::clean::clean_middle_path;
38use crate::clean::inline::{self, print_inlined_const};
39use crate::clean::utils::{is_literal_expr, print_evaluated_const};
40use crate::core::DocContext;
41use crate::formats::cache::Cache;
42use crate::formats::item_type::ItemType;
43use crate::html::format::HrefInfo;
44use crate::html::render::Context;
45use crate::passes::collect_intra_doc_links::UrlFragment;
46
47#[cfg(test)]
48mod tests;
49
50pub(crate) type ItemIdSet = FxHashSet<ItemId>;
51
52#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
53pub(crate) enum ItemId {
54 DefId(DefId),
56 Auto { trait_: DefId, for_: DefId },
58 Blanket { impl_id: DefId, for_: DefId },
60}
61
62impl ItemId {
63 #[inline]
64 pub(crate) fn is_local(self) -> bool {
65 match self {
66 ItemId::Auto { for_: id, .. }
67 | ItemId::Blanket { for_: id, .. }
68 | ItemId::DefId(id) => id.is_local(),
69 }
70 }
71
72 #[inline]
73 #[track_caller]
74 pub(crate) fn expect_def_id(self) -> DefId {
75 self.as_def_id()
76 .unwrap_or_else(|| panic!("ItemId::expect_def_id: `{self:?}` isn't a DefId"))
77 }
78
79 #[inline]
80 pub(crate) fn as_def_id(self) -> Option<DefId> {
81 match self {
82 ItemId::DefId(id) => Some(id),
83 _ => None,
84 }
85 }
86
87 #[inline]
88 pub(crate) fn as_local_def_id(self) -> Option<LocalDefId> {
89 self.as_def_id().and_then(|id| id.as_local())
90 }
91
92 #[inline]
93 pub(crate) fn krate(self) -> CrateNum {
94 match self {
95 ItemId::Auto { for_: id, .. }
96 | ItemId::Blanket { for_: id, .. }
97 | ItemId::DefId(id) => id.krate,
98 }
99 }
100}
101
102impl From<DefId> for ItemId {
103 fn from(id: DefId) -> Self {
104 Self::DefId(id)
105 }
106}
107
108#[derive(Debug)]
110pub(crate) struct Crate {
111 pub(crate) module: Item,
112 pub(crate) external_traits: Box<FxIndexMap<DefId, Trait>>,
114}
115
116impl Crate {
117 pub(crate) fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
118 ExternalCrate::LOCAL.name(tcx)
119 }
120
121 pub(crate) fn src(&self, tcx: TyCtxt<'_>) -> FileName {
122 ExternalCrate::LOCAL.src(tcx)
123 }
124}
125
126#[derive(Copy, Clone, Debug)]
127pub(crate) struct ExternalCrate {
128 pub(crate) crate_num: CrateNum,
129}
130
131impl ExternalCrate {
132 const LOCAL: Self = Self { crate_num: LOCAL_CRATE };
133
134 #[inline]
135 pub(crate) fn def_id(&self) -> DefId {
136 self.crate_num.as_def_id()
137 }
138
139 pub(crate) fn src(&self, tcx: TyCtxt<'_>) -> FileName {
140 let krate_span = tcx.def_span(self.def_id());
141 tcx.sess.source_map().span_to_filename(krate_span)
142 }
143
144 pub(crate) fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
145 tcx.crate_name(self.crate_num)
146 }
147
148 pub(crate) fn src_root(&self, tcx: TyCtxt<'_>) -> PathBuf {
149 match self.src(tcx) {
150 FileName::Real(ref p) => match p.local_path_if_available().parent() {
151 Some(p) => p.to_path_buf(),
152 None => PathBuf::new(),
153 },
154 _ => PathBuf::new(),
155 }
156 }
157
158 pub(crate) fn location(
161 &self,
162 extern_url: Option<&str>,
163 extern_url_takes_precedence: bool,
164 dst: &std::path::Path,
165 tcx: TyCtxt<'_>,
166 ) -> ExternalLocation {
167 use ExternalLocation::*;
168
169 fn to_remote(url: impl ToString) -> ExternalLocation {
170 let mut url = url.to_string();
171 if !url.ends_with('/') {
172 url.push('/');
173 }
174 Remote(url)
175 }
176
177 let local_location = dst.join(self.name(tcx).as_str());
181 if local_location.is_dir() {
182 return Local;
183 }
184
185 if extern_url_takes_precedence && let Some(url) = extern_url {
186 return to_remote(url);
187 }
188
189 let did = self.crate_num.as_def_id();
192 tcx.get_attrs(did, sym::doc)
193 .flat_map(|attr| attr.meta_item_list().unwrap_or_default())
194 .filter(|a| a.has_name(sym::html_root_url))
195 .filter_map(|a| a.value_str())
196 .map(to_remote)
197 .next()
198 .or_else(|| extern_url.map(to_remote)) .unwrap_or(Unknown) }
201
202 fn mapped_root_modules<T>(
203 &self,
204 tcx: TyCtxt<'_>,
205 f: impl Fn(DefId, TyCtxt<'_>) -> Option<(DefId, T)>,
206 ) -> impl Iterator<Item = (DefId, T)> {
207 let root = self.def_id();
208
209 if root.is_local() {
210 Either::Left(
211 tcx.hir_root_module()
212 .item_ids
213 .iter()
214 .filter(move |&&id| matches!(tcx.hir_item(id).kind, hir::ItemKind::Mod(..)))
215 .filter_map(move |&id| f(id.owner_id.into(), tcx)),
216 )
217 } else {
218 Either::Right(
219 tcx.module_children(root)
220 .iter()
221 .filter_map(|item| {
222 if let Res::Def(DefKind::Mod, did) = item.res { Some(did) } else { None }
223 })
224 .filter_map(move |did| f(did, tcx)),
225 )
226 }
227 }
228
229 pub(crate) fn keywords(&self, tcx: TyCtxt<'_>) -> impl Iterator<Item = (DefId, Symbol)> {
230 self.retrieve_keywords_or_documented_attributes(tcx, sym::keyword)
231 }
232 pub(crate) fn documented_attributes(
233 &self,
234 tcx: TyCtxt<'_>,
235 ) -> impl Iterator<Item = (DefId, Symbol)> {
236 self.retrieve_keywords_or_documented_attributes(tcx, sym::attribute)
237 }
238
239 fn retrieve_keywords_or_documented_attributes(
240 &self,
241 tcx: TyCtxt<'_>,
242 name: Symbol,
243 ) -> impl Iterator<Item = (DefId, Symbol)> {
244 let as_target = move |did: DefId, tcx: TyCtxt<'_>| -> Option<(DefId, Symbol)> {
245 tcx.get_attrs(did, sym::doc)
246 .flat_map(|attr| attr.meta_item_list().unwrap_or_default())
247 .filter(|meta| meta.has_name(name))
248 .find_map(|meta| meta.value_str())
249 .map(|value| (did, value))
250 };
251 self.mapped_root_modules(tcx, as_target)
252 }
253
254 pub(crate) fn primitives(
255 &self,
256 tcx: TyCtxt<'_>,
257 ) -> impl Iterator<Item = (DefId, PrimitiveType)> {
258 fn as_primitive(def_id: DefId, tcx: TyCtxt<'_>) -> Option<(DefId, PrimitiveType)> {
276 tcx.get_attrs(def_id, sym::rustc_doc_primitive).next().map(|attr| {
277 let attr_value = attr.value_str().expect("syntax should already be validated");
278 let Some(prim) = PrimitiveType::from_symbol(attr_value) else {
279 span_bug!(
280 attr.span(),
281 "primitive `{attr_value}` is not a member of `PrimitiveType`"
282 );
283 };
284
285 (def_id, prim)
286 })
287 }
288
289 self.mapped_root_modules(tcx, as_primitive)
290 }
291}
292
293#[derive(Debug)]
295pub(crate) enum ExternalLocation {
296 Remote(String),
298 Local,
300 Unknown,
302}
303
304#[derive(Clone)]
308pub(crate) struct Item {
309 pub(crate) inner: Box<ItemInner>,
310}
311
312#[derive(Clone)]
318pub(crate) struct ItemInner {
319 pub(crate) name: Option<Symbol>,
322 pub(crate) kind: ItemKind,
325 pub(crate) attrs: Attributes,
326 pub(crate) stability: Option<Stability>,
328 pub(crate) item_id: ItemId,
329 pub(crate) inline_stmt_id: Option<LocalDefId>,
333 pub(crate) cfg: Option<Arc<Cfg>>,
334}
335
336impl std::ops::Deref for Item {
337 type Target = ItemInner;
338 fn deref(&self) -> &ItemInner {
339 &self.inner
340 }
341}
342
343impl fmt::Debug for Item {
346 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
347 let alternate = f.alternate();
348 let mut fmt = f.debug_struct("Item");
350 fmt.field("name", &self.name).field("item_id", &self.item_id);
351 if alternate {
353 fmt.field("attrs", &self.attrs).field("kind", &self.kind).field("cfg", &self.cfg);
354 } else {
355 fmt.field("kind", &self.type_());
356 fmt.field("docs", &self.doc_value());
357 }
358 fmt.finish()
359 }
360}
361
362pub(crate) fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
363 Span::new(def_id.as_local().map_or_else(
364 || tcx.def_span(def_id),
365 |local| tcx.hir_span_with_body(tcx.local_def_id_to_hir_id(local)),
366 ))
367}
368
369fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
370 let parent = tcx.parent(def_id);
371 match tcx.def_kind(parent) {
372 DefKind::Struct | DefKind::Union => false,
373 DefKind::Variant => true,
374 parent_kind => panic!("unexpected parent kind: {parent_kind:?}"),
375 }
376}
377
378impl Item {
379 pub(crate) fn stability(&self, tcx: TyCtxt<'_>) -> Option<Stability> {
383 let stability = self.inner.stability;
384 debug_assert!(
385 stability.is_some()
386 || self.def_id().is_none_or(|did| tcx.lookup_stability(did).is_none()),
387 "missing stability for cleaned item: {self:?}",
388 );
389 stability
390 }
391
392 pub(crate) fn const_stability(&self, tcx: TyCtxt<'_>) -> Option<ConstStability> {
393 self.def_id().and_then(|did| tcx.lookup_const_stability(did))
394 }
395
396 pub(crate) fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
397 self.def_id().and_then(|did| tcx.lookup_deprecation(did)).or_else(|| {
398 let stab = self.stability(tcx)?;
402 if let rustc_hir::StabilityLevel::Stable {
403 allowed_through_unstable_modules: Some(note),
404 ..
405 } = stab.level
406 {
407 Some(Deprecation {
408 since: DeprecatedSince::Unspecified,
409 note: Some(note),
410 suggestion: None,
411 })
412 } else {
413 None
414 }
415 })
416 }
417
418 pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
419 self.item_id.as_def_id().map(|did| inner_docs(tcx.get_all_attrs(did))).unwrap_or(false)
420 }
421
422 pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option<Span> {
423 let kind = match &self.kind {
424 ItemKind::StrippedItem(k) => k,
425 _ => &self.kind,
426 };
427 match kind {
428 ItemKind::ModuleItem(Module { span, .. }) => Some(*span),
429 ItemKind::ImplItem(box Impl { kind: ImplKind::Auto, .. }) => None,
430 ItemKind::ImplItem(box Impl { kind: ImplKind::Blanket(_), .. }) => {
431 if let ItemId::Blanket { impl_id, .. } = self.item_id {
432 Some(rustc_span(impl_id, tcx))
433 } else {
434 panic!("blanket impl item has non-blanket ID")
435 }
436 }
437 _ => self.def_id().map(|did| rustc_span(did, tcx)),
438 }
439 }
440
441 pub(crate) fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
442 span_of_fragments(&self.attrs.doc_strings)
443 .unwrap_or_else(|| self.span(tcx).map_or(DUMMY_SP, |span| span.inner()))
444 }
445
446 pub(crate) fn doc_value(&self) -> String {
448 self.attrs.doc_value()
449 }
450
451 pub(crate) fn opt_doc_value(&self) -> Option<String> {
455 self.attrs.opt_doc_value()
456 }
457
458 pub(crate) fn from_def_id_and_parts(
459 def_id: DefId,
460 name: Option<Symbol>,
461 kind: ItemKind,
462 cx: &mut DocContext<'_>,
463 ) -> Item {
464 let hir_attrs = cx.tcx.get_all_attrs(def_id);
465
466 Self::from_def_id_and_attrs_and_parts(
467 def_id,
468 name,
469 kind,
470 Attributes::from_hir(hir_attrs),
471 None,
472 )
473 }
474
475 pub(crate) fn from_def_id_and_attrs_and_parts(
476 def_id: DefId,
477 name: Option<Symbol>,
478 kind: ItemKind,
479 attrs: Attributes,
480 cfg: Option<Arc<Cfg>>,
481 ) -> Item {
482 trace!("name={name:?}, def_id={def_id:?} cfg={cfg:?}");
483
484 Item {
485 inner: Box::new(ItemInner {
486 item_id: def_id.into(),
487 kind,
488 attrs,
489 stability: None,
490 name,
491 cfg,
492 inline_stmt_id: None,
493 }),
494 }
495 }
496
497 pub(crate) fn item_or_reexport_id(&self) -> ItemId {
503 self.attrs
505 .doc_strings
506 .first()
507 .map(|x| x.item_id)
508 .flatten()
509 .map(ItemId::from)
510 .unwrap_or(self.item_id)
511 }
512
513 pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
514 use crate::html::format::{href, link_tooltip};
515
516 let Some(links) = cx.cache().intra_doc_links.get(&self.item_or_reexport_id()) else {
517 return vec![];
518 };
519 links
520 .iter()
521 .filter_map(|ItemLink { link: s, link_text, page_id: id, fragment }| {
522 debug!(?id);
523 if let Ok(HrefInfo { mut url, .. }) = href(*id, cx) {
524 debug!(?url);
525 if let Some(ref fragment) = *fragment {
526 fragment.render(&mut url, cx.tcx())
527 }
528 Some(RenderedLink {
529 original_text: s.clone(),
530 new_text: link_text.clone(),
531 tooltip: link_tooltip(*id, fragment, cx).to_string(),
532 href: url,
533 })
534 } else {
535 None
536 }
537 })
538 .collect()
539 }
540
541 pub(crate) fn link_names(&self, cache: &Cache) -> Vec<RenderedLink> {
547 let Some(links) = cache.intra_doc_links.get(&self.item_id) else {
548 return vec![];
549 };
550 links
551 .iter()
552 .map(|ItemLink { link: s, link_text, .. }| RenderedLink {
553 original_text: s.clone(),
554 new_text: link_text.clone(),
555 href: String::new(),
556 tooltip: String::new(),
557 })
558 .collect()
559 }
560
561 pub(crate) fn is_crate(&self) -> bool {
562 self.is_mod() && self.def_id().is_some_and(|did| did.is_crate_root())
563 }
564 pub(crate) fn is_mod(&self) -> bool {
565 self.type_() == ItemType::Module
566 }
567 pub(crate) fn is_struct(&self) -> bool {
568 self.type_() == ItemType::Struct
569 }
570 pub(crate) fn is_enum(&self) -> bool {
571 self.type_() == ItemType::Enum
572 }
573 pub(crate) fn is_variant(&self) -> bool {
574 self.type_() == ItemType::Variant
575 }
576 pub(crate) fn is_associated_type(&self) -> bool {
577 matches!(self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..)))
578 }
579 pub(crate) fn is_required_associated_type(&self) -> bool {
580 matches!(self.kind, RequiredAssocTypeItem(..) | StrippedItem(box RequiredAssocTypeItem(..)))
581 }
582 pub(crate) fn is_associated_const(&self) -> bool {
583 matches!(self.kind, ProvidedAssocConstItem(..) | ImplAssocConstItem(..) | StrippedItem(box (ProvidedAssocConstItem(..) | ImplAssocConstItem(..))))
584 }
585 pub(crate) fn is_required_associated_const(&self) -> bool {
586 matches!(self.kind, RequiredAssocConstItem(..) | StrippedItem(box RequiredAssocConstItem(..)))
587 }
588 pub(crate) fn is_method(&self) -> bool {
589 self.type_() == ItemType::Method
590 }
591 pub(crate) fn is_ty_method(&self) -> bool {
592 self.type_() == ItemType::TyMethod
593 }
594 pub(crate) fn is_primitive(&self) -> bool {
595 self.type_() == ItemType::Primitive
596 }
597 pub(crate) fn is_union(&self) -> bool {
598 self.type_() == ItemType::Union
599 }
600 pub(crate) fn is_import(&self) -> bool {
601 self.type_() == ItemType::Import
602 }
603 pub(crate) fn is_extern_crate(&self) -> bool {
604 self.type_() == ItemType::ExternCrate
605 }
606 pub(crate) fn is_keyword(&self) -> bool {
607 self.type_() == ItemType::Keyword
608 }
609 pub(crate) fn is_attribute(&self) -> bool {
610 self.type_() == ItemType::Attribute
611 }
612 pub(crate) fn is_fake_item(&self) -> bool {
621 matches!(self.type_(), ItemType::Primitive | ItemType::Keyword | ItemType::Attribute)
622 }
623 pub(crate) fn is_stripped(&self) -> bool {
624 match self.kind {
625 StrippedItem(..) => true,
626 ImportItem(ref i) => !i.should_be_displayed,
627 _ => false,
628 }
629 }
630 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
631 match self.kind {
632 StructItem(ref struct_) => Some(struct_.has_stripped_entries()),
633 UnionItem(ref union_) => Some(union_.has_stripped_entries()),
634 EnumItem(ref enum_) => Some(enum_.has_stripped_entries()),
635 VariantItem(ref v) => v.has_stripped_entries(),
636 TypeAliasItem(ref type_alias) => {
637 type_alias.inner_type.as_ref().and_then(|t| t.has_stripped_entries())
638 }
639 _ => None,
640 }
641 }
642
643 pub(crate) fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
644 self.stability(tcx).as_ref().and_then(|s| {
645 let mut classes = Vec::with_capacity(2);
646
647 if s.is_unstable() {
648 classes.push("unstable");
649 }
650
651 if self.deprecation(tcx).is_some() {
653 classes.push("deprecated");
654 }
655
656 if !classes.is_empty() { Some(classes.join(" ")) } else { None }
657 })
658 }
659
660 pub(crate) fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<StableSince> {
661 self.stability(tcx).and_then(|stability| stability.stable_since())
662 }
663
664 pub(crate) fn is_non_exhaustive(&self) -> bool {
665 find_attr!(&self.attrs.other_attrs, AttributeKind::NonExhaustive(..))
666 }
667
668 pub(crate) fn type_(&self) -> ItemType {
670 ItemType::from(self)
671 }
672
673 pub(crate) fn is_default(&self) -> bool {
674 match self.kind {
675 ItemKind::MethodItem(_, Some(defaultness)) => {
676 defaultness.has_value() && !defaultness.is_final()
677 }
678 _ => false,
679 }
680 }
681
682 pub(crate) fn fn_header(&self, tcx: TyCtxt<'_>) -> Option<hir::FnHeader> {
684 fn build_fn_header(
685 def_id: DefId,
686 tcx: TyCtxt<'_>,
687 asyncness: ty::Asyncness,
688 ) -> hir::FnHeader {
689 let sig = tcx.fn_sig(def_id).skip_binder();
690 let constness = if tcx.is_const_fn(def_id) {
691 if let Some(assoc) = tcx.opt_associated_item(def_id)
695 && let ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) =
696 assoc.container
697 {
698 hir::Constness::NotConst
699 } else {
700 hir::Constness::Const
701 }
702 } else {
703 hir::Constness::NotConst
704 };
705 let asyncness = match asyncness {
706 ty::Asyncness::Yes => hir::IsAsync::Async(DUMMY_SP),
707 ty::Asyncness::No => hir::IsAsync::NotAsync,
708 };
709 hir::FnHeader {
710 safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
711 hir::HeaderSafety::SafeTargetFeatures
712 } else {
713 sig.safety().into()
714 },
715 abi: sig.abi(),
716 constness,
717 asyncness,
718 }
719 }
720 let header = match self.kind {
721 ItemKind::ForeignFunctionItem(_, safety) => {
722 let def_id = self.def_id().unwrap();
723 let abi = tcx.fn_sig(def_id).skip_binder().abi();
724 hir::FnHeader {
725 safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
726 hir::HeaderSafety::SafeTargetFeatures
727 } else {
728 safety.into()
729 },
730 abi,
731 constness: if tcx.is_const_fn(def_id) {
732 hir::Constness::Const
733 } else {
734 hir::Constness::NotConst
735 },
736 asyncness: hir::IsAsync::NotAsync,
737 }
738 }
739 ItemKind::FunctionItem(_)
740 | ItemKind::MethodItem(_, _)
741 | ItemKind::RequiredMethodItem(_) => {
742 let def_id = self.def_id().unwrap();
743 build_fn_header(def_id, tcx, tcx.asyncness(def_id))
744 }
745 _ => return None,
746 };
747 Some(header)
748 }
749
750 pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option<Visibility<DefId>> {
753 let def_id = match self.item_id {
754 ItemId::Auto { .. } | ItemId::Blanket { .. } => return None,
756 ItemId::DefId(def_id) => def_id,
757 };
758
759 match self.kind {
760 ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) | ItemKind::AttributeItem => {
764 return Some(Visibility::Public);
765 }
766 StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => {
768 return None;
769 }
770 VariantItem(..) | ImplItem(..) => return None,
772 RequiredAssocConstItem(..)
774 | ProvidedAssocConstItem(..)
775 | ImplAssocConstItem(..)
776 | AssocTypeItem(..)
777 | RequiredAssocTypeItem(..)
778 | RequiredMethodItem(..)
779 | MethodItem(..) => {
780 match tcx.associated_item(def_id).container {
781 ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) => {
784 return None;
785 }
786 ty::AssocContainer::InherentImpl => {}
787 }
788 }
789 _ => {}
790 }
791 let def_id = match self.inline_stmt_id {
792 Some(inlined) => inlined.to_def_id(),
793 None => def_id,
794 };
795 Some(tcx.visibility(def_id))
796 }
797
798 pub fn is_doc_hidden(&self) -> bool {
799 self.attrs.is_doc_hidden()
800 }
801
802 pub fn def_id(&self) -> Option<DefId> {
803 self.item_id.as_def_id()
804 }
805}
806
807#[derive(Clone, Debug)]
808pub(crate) enum ItemKind {
809 ExternCrateItem {
810 src: Option<Symbol>,
812 },
813 ImportItem(Import),
814 StructItem(Struct),
815 UnionItem(Union),
816 EnumItem(Enum),
817 FunctionItem(Box<Function>),
818 ModuleItem(Module),
819 TypeAliasItem(Box<TypeAlias>),
820 StaticItem(Static),
821 TraitItem(Box<Trait>),
822 TraitAliasItem(TraitAlias),
823 ImplItem(Box<Impl>),
824 RequiredMethodItem(Box<Function>),
826 MethodItem(Box<Function>, Option<hir::Defaultness>),
830 StructFieldItem(Type),
831 VariantItem(Variant),
832 ForeignFunctionItem(Box<Function>, hir::Safety),
834 ForeignStaticItem(Static, hir::Safety),
836 ForeignTypeItem,
838 MacroItem(Macro),
839 ProcMacroItem(ProcMacro),
840 PrimitiveItem(PrimitiveType),
841 RequiredAssocConstItem(Generics, Box<Type>),
843 ConstantItem(Box<Constant>),
844 ProvidedAssocConstItem(Box<Constant>),
846 ImplAssocConstItem(Box<Constant>),
848 RequiredAssocTypeItem(Generics, Vec<GenericBound>),
852 AssocTypeItem(Box<TypeAlias>, Vec<GenericBound>),
854 StrippedItem(Box<ItemKind>),
856 KeywordItem,
859 AttributeItem,
862}
863
864impl ItemKind {
865 pub(crate) fn inner_items(&self) -> impl Iterator<Item = &Item> {
868 match self {
869 StructItem(s) => s.fields.iter(),
870 UnionItem(u) => u.fields.iter(),
871 VariantItem(v) => match &v.kind {
872 VariantKind::CLike => [].iter(),
873 VariantKind::Tuple(t) => t.iter(),
874 VariantKind::Struct(s) => s.fields.iter(),
875 },
876 EnumItem(e) => e.variants.iter(),
877 TraitItem(t) => t.items.iter(),
878 ImplItem(i) => i.items.iter(),
879 ModuleItem(m) => m.items.iter(),
880 ExternCrateItem { .. }
881 | ImportItem(_)
882 | FunctionItem(_)
883 | TypeAliasItem(_)
884 | StaticItem(_)
885 | ConstantItem(_)
886 | TraitAliasItem(_)
887 | RequiredMethodItem(_)
888 | MethodItem(_, _)
889 | StructFieldItem(_)
890 | ForeignFunctionItem(_, _)
891 | ForeignStaticItem(_, _)
892 | ForeignTypeItem
893 | MacroItem(_)
894 | ProcMacroItem(_)
895 | PrimitiveItem(_)
896 | RequiredAssocConstItem(..)
897 | ProvidedAssocConstItem(..)
898 | ImplAssocConstItem(..)
899 | RequiredAssocTypeItem(..)
900 | AssocTypeItem(..)
901 | StrippedItem(_)
902 | KeywordItem
903 | AttributeItem => [].iter(),
904 }
905 }
906}
907
908#[derive(Clone, Debug)]
909pub(crate) struct Module {
910 pub(crate) items: Vec<Item>,
911 pub(crate) span: Span,
912}
913
914pub(crate) fn hir_attr_lists<'a, I: IntoIterator<Item = &'a hir::Attribute>>(
915 attrs: I,
916 name: Symbol,
917) -> impl Iterator<Item = ast::MetaItemInner> + use<'a, I> {
918 attrs
919 .into_iter()
920 .filter(move |attr| attr.has_name(name))
921 .filter_map(ast::attr::AttributeExt::meta_item_list)
922 .flatten()
923}
924
925pub(crate) trait NestedAttributesExt {
926 fn has_word(self, word: Symbol) -> bool
928 where
929 Self: Sized,
930 {
931 <Self as NestedAttributesExt>::get_word_attr(self, word).is_some()
932 }
933
934 fn get_word_attr(self, word: Symbol) -> Option<ast::MetaItemInner>;
937}
938
939impl<I: Iterator<Item = ast::MetaItemInner>> NestedAttributesExt for I {
940 fn get_word_attr(mut self, word: Symbol) -> Option<ast::MetaItemInner> {
941 self.find(|attr| attr.is_word() && attr.has_name(word))
942 }
943}
944
945#[derive(Clone, Debug, PartialEq, Eq, Hash)]
949pub(crate) struct ItemLink {
950 pub(crate) link: Box<str>,
952 pub(crate) link_text: Box<str>,
957 pub(crate) page_id: DefId,
961 pub(crate) fragment: Option<UrlFragment>,
963}
964
965pub struct RenderedLink {
966 pub(crate) original_text: Box<str>,
970 pub(crate) new_text: Box<str>,
972 pub(crate) href: String,
974 pub(crate) tooltip: String,
976}
977
978#[derive(Clone, Debug, Default)]
981pub(crate) struct Attributes {
982 pub(crate) doc_strings: Vec<DocFragment>,
983 pub(crate) other_attrs: ThinVec<hir::Attribute>,
984}
985
986impl Attributes {
987 pub(crate) fn lists(&self, name: Symbol) -> impl Iterator<Item = ast::MetaItemInner> {
988 hir_attr_lists(&self.other_attrs[..], name)
989 }
990
991 pub(crate) fn has_doc_flag(&self, flag: Symbol) -> bool {
992 for attr in &self.other_attrs {
993 if !attr.has_name(sym::doc) {
994 continue;
995 }
996
997 if let Some(items) = attr.meta_item_list()
998 && items.iter().filter_map(|i| i.meta_item()).any(|it| it.has_name(flag))
999 {
1000 return true;
1001 }
1002 }
1003
1004 false
1005 }
1006
1007 pub(crate) fn is_doc_hidden(&self) -> bool {
1008 self.has_doc_flag(sym::hidden)
1009 }
1010
1011 pub(crate) fn from_hir(attrs: &[hir::Attribute]) -> Attributes {
1012 Attributes::from_hir_iter(attrs.iter().map(|attr| (attr, None)), false)
1013 }
1014
1015 pub(crate) fn from_hir_with_additional(
1016 attrs: &[hir::Attribute],
1017 (additional_attrs, def_id): (&[hir::Attribute], DefId),
1018 ) -> Attributes {
1019 let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id)));
1021 let attrs2 = attrs.iter().map(|attr| (attr, None));
1022 Attributes::from_hir_iter(attrs1.chain(attrs2), false)
1023 }
1024
1025 pub(crate) fn from_hir_iter<'a>(
1026 attrs: impl Iterator<Item = (&'a hir::Attribute, Option<DefId>)>,
1027 doc_only: bool,
1028 ) -> Attributes {
1029 let (doc_strings, other_attrs) = attrs_to_doc_fragments(attrs, doc_only);
1030 Attributes { doc_strings, other_attrs }
1031 }
1032
1033 pub(crate) fn doc_value(&self) -> String {
1035 self.opt_doc_value().unwrap_or_default()
1036 }
1037
1038 pub(crate) fn opt_doc_value(&self) -> Option<String> {
1042 (!self.doc_strings.is_empty()).then(|| {
1043 let mut res = String::new();
1044 for frag in &self.doc_strings {
1045 add_doc_fragment(&mut res, frag);
1046 }
1047 res.pop();
1048 res
1049 })
1050 }
1051
1052 pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> {
1053 let mut aliases = FxIndexSet::default();
1054
1055 for attr in
1056 hir_attr_lists(&self.other_attrs[..], sym::doc).filter(|a| a.has_name(sym::alias))
1057 {
1058 if let Some(values) = attr.meta_item_list() {
1059 for l in values {
1060 if let Some(lit) = l.lit()
1061 && let ast::LitKind::Str(s, _) = lit.kind
1062 {
1063 aliases.insert(s);
1064 }
1065 }
1066 } else if let Some(value) = attr.value_str() {
1067 aliases.insert(value);
1068 }
1069 }
1070 aliases.into_iter().collect::<Vec<_>>().into()
1071 }
1072}
1073
1074#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1075pub(crate) enum GenericBound {
1076 TraitBound(PolyTrait, hir::TraitBoundModifiers),
1077 Outlives(Lifetime),
1078 Use(Vec<PreciseCapturingArg>),
1080}
1081
1082impl GenericBound {
1083 pub(crate) fn sized(cx: &mut DocContext<'_>) -> GenericBound {
1084 Self::sized_with(cx, hir::TraitBoundModifiers::NONE)
1085 }
1086
1087 pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1088 Self::sized_with(
1089 cx,
1090 hir::TraitBoundModifiers {
1091 polarity: hir::BoundPolarity::Maybe(DUMMY_SP),
1092 constness: hir::BoundConstness::Never,
1093 },
1094 )
1095 }
1096
1097 fn sized_with(cx: &mut DocContext<'_>, modifiers: hir::TraitBoundModifiers) -> GenericBound {
1098 let did = cx.tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
1099 let empty = ty::Binder::dummy(ty::GenericArgs::empty());
1100 let path = clean_middle_path(cx, did, false, ThinVec::new(), empty);
1101 inline::record_extern_fqn(cx, did, ItemType::Trait);
1102 GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifiers)
1103 }
1104
1105 pub(crate) fn is_trait_bound(&self) -> bool {
1106 matches!(self, Self::TraitBound(..))
1107 }
1108
1109 pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1110 self.is_bounded_by_lang_item(cx, LangItem::Sized)
1111 }
1112
1113 pub(crate) fn is_meta_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1114 self.is_bounded_by_lang_item(cx, LangItem::MetaSized)
1115 }
1116
1117 fn is_bounded_by_lang_item(&self, cx: &DocContext<'_>, lang_item: LangItem) -> bool {
1118 if let GenericBound::TraitBound(
1119 PolyTrait { ref trait_, .. },
1120 rustc_hir::TraitBoundModifiers::NONE,
1121 ) = *self
1122 && cx.tcx.is_lang_item(trait_.def_id(), lang_item)
1123 {
1124 return true;
1125 }
1126 false
1127 }
1128
1129 pub(crate) fn get_trait_path(&self) -> Option<Path> {
1130 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1131 Some(trait_.clone())
1132 } else {
1133 None
1134 }
1135 }
1136}
1137
1138#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1139pub(crate) struct Lifetime(pub Symbol);
1140
1141impl Lifetime {
1142 pub(crate) fn statik() -> Lifetime {
1143 Lifetime(kw::StaticLifetime)
1144 }
1145
1146 pub(crate) fn elided() -> Lifetime {
1147 Lifetime(kw::UnderscoreLifetime)
1148 }
1149}
1150
1151#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1152pub(crate) enum PreciseCapturingArg {
1153 Lifetime(Lifetime),
1154 Param(Symbol),
1155}
1156
1157impl PreciseCapturingArg {
1158 pub(crate) fn name(self) -> Symbol {
1159 match self {
1160 PreciseCapturingArg::Lifetime(lt) => lt.0,
1161 PreciseCapturingArg::Param(param) => param,
1162 }
1163 }
1164}
1165
1166#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1167pub(crate) enum WherePredicate {
1168 BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
1169 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1170 EqPredicate { lhs: QPathData, rhs: Term },
1171}
1172
1173impl WherePredicate {
1174 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1175 match self {
1176 WherePredicate::BoundPredicate { bounds, .. } => Some(bounds),
1177 WherePredicate::RegionPredicate { bounds, .. } => Some(bounds),
1178 _ => None,
1179 }
1180 }
1181}
1182
1183#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1184pub(crate) enum GenericParamDefKind {
1185 Lifetime { outlives: ThinVec<Lifetime> },
1186 Type { bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
1187 Const { ty: Box<Type>, default: Option<Box<String>> },
1189}
1190
1191impl GenericParamDefKind {
1192 pub(crate) fn is_type(&self) -> bool {
1193 matches!(self, GenericParamDefKind::Type { .. })
1194 }
1195}
1196
1197#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1198pub(crate) struct GenericParamDef {
1199 pub(crate) name: Symbol,
1200 pub(crate) def_id: DefId,
1201 pub(crate) kind: GenericParamDefKind,
1202}
1203
1204impl GenericParamDef {
1205 pub(crate) fn lifetime(def_id: DefId, name: Symbol) -> Self {
1206 Self { name, def_id, kind: GenericParamDefKind::Lifetime { outlives: ThinVec::new() } }
1207 }
1208
1209 pub(crate) fn is_synthetic_param(&self) -> bool {
1210 match self.kind {
1211 GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
1212 GenericParamDefKind::Type { synthetic, .. } => synthetic,
1213 }
1214 }
1215
1216 pub(crate) fn is_type(&self) -> bool {
1217 self.kind.is_type()
1218 }
1219
1220 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1221 match self.kind {
1222 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1223 _ => None,
1224 }
1225 }
1226}
1227
1228#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
1230pub(crate) struct Generics {
1231 pub(crate) params: ThinVec<GenericParamDef>,
1232 pub(crate) where_predicates: ThinVec<WherePredicate>,
1233}
1234
1235impl Generics {
1236 pub(crate) fn is_empty(&self) -> bool {
1237 self.params.is_empty() && self.where_predicates.is_empty()
1238 }
1239}
1240
1241#[derive(Clone, Debug)]
1242pub(crate) struct Function {
1243 pub(crate) decl: FnDecl,
1244 pub(crate) generics: Generics,
1245}
1246
1247#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1248pub(crate) struct FnDecl {
1249 pub(crate) inputs: Vec<Parameter>,
1250 pub(crate) output: Type,
1251 pub(crate) c_variadic: bool,
1252}
1253
1254impl FnDecl {
1255 pub(crate) fn receiver_type(&self) -> Option<&Type> {
1256 self.inputs.first().and_then(|v| v.to_receiver())
1257 }
1258}
1259
1260#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1262pub(crate) struct Parameter {
1263 pub(crate) name: Option<Symbol>,
1264 pub(crate) type_: Type,
1265 pub(crate) is_const: bool,
1268}
1269
1270impl Parameter {
1271 pub(crate) fn to_receiver(&self) -> Option<&Type> {
1272 if self.name == Some(kw::SelfLower) { Some(&self.type_) } else { None }
1273 }
1274}
1275
1276#[derive(Clone, Debug)]
1277pub(crate) struct Trait {
1278 pub(crate) def_id: DefId,
1279 pub(crate) items: Vec<Item>,
1280 pub(crate) generics: Generics,
1281 pub(crate) bounds: Vec<GenericBound>,
1282}
1283
1284impl Trait {
1285 pub(crate) fn is_auto(&self, tcx: TyCtxt<'_>) -> bool {
1286 tcx.trait_is_auto(self.def_id)
1287 }
1288 pub(crate) fn is_notable_trait(&self, tcx: TyCtxt<'_>) -> bool {
1289 tcx.is_doc_notable_trait(self.def_id)
1290 }
1291 pub(crate) fn safety(&self, tcx: TyCtxt<'_>) -> hir::Safety {
1292 tcx.trait_def(self.def_id).safety
1293 }
1294 pub(crate) fn is_dyn_compatible(&self, tcx: TyCtxt<'_>) -> bool {
1295 tcx.is_dyn_compatible(self.def_id)
1296 }
1297}
1298
1299#[derive(Clone, Debug)]
1300pub(crate) struct TraitAlias {
1301 pub(crate) generics: Generics,
1302 pub(crate) bounds: Vec<GenericBound>,
1303}
1304
1305#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1307pub(crate) struct PolyTrait {
1308 pub(crate) trait_: Path,
1309 pub(crate) generic_params: Vec<GenericParamDef>,
1310}
1311
1312#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1314pub(crate) enum Type {
1315 Path {
1320 path: Path,
1321 },
1322 DynTrait(Vec<PolyTrait>, Option<Lifetime>),
1324 Generic(Symbol),
1326 SelfTy,
1328 Primitive(PrimitiveType),
1330 BareFunction(Box<BareFunctionDecl>),
1332 Tuple(Vec<Type>),
1334 Slice(Box<Type>),
1336 Array(Box<Type>, Box<str>),
1340 Pat(Box<Type>, Box<str>),
1341 RawPointer(Mutability, Box<Type>),
1343 BorrowedRef {
1345 lifetime: Option<Lifetime>,
1346 mutability: Mutability,
1347 type_: Box<Type>,
1348 },
1349
1350 QPath(Box<QPathData>),
1352
1353 Infer,
1355
1356 ImplTrait(Vec<GenericBound>),
1358
1359 UnsafeBinder(Box<UnsafeBinderTy>),
1360}
1361
1362impl Type {
1363 pub(crate) fn without_borrowed_ref(&self) -> &Type {
1365 let mut result = self;
1366 while let Type::BorrowedRef { type_, .. } = result {
1367 result = type_;
1368 }
1369 result
1370 }
1371
1372 pub(crate) fn is_borrowed_ref(&self) -> bool {
1373 matches!(self, Type::BorrowedRef { .. })
1374 }
1375
1376 fn is_type_alias(&self) -> bool {
1377 matches!(self, Type::Path { path: Path { res: Res::Def(DefKind::TyAlias, _), .. } })
1378 }
1379
1380 pub(crate) fn is_doc_subtype_of(&self, other: &Self, cache: &Cache) -> bool {
1401 let (self_cleared, other_cleared) = if !self.is_borrowed_ref() || !other.is_borrowed_ref() {
1404 (self.without_borrowed_ref(), other.without_borrowed_ref())
1405 } else {
1406 (self, other)
1407 };
1408
1409 if self_cleared.is_type_alias() || other_cleared.is_type_alias() {
1415 return true;
1416 }
1417
1418 match (self_cleared, other_cleared) {
1419 (Type::Tuple(a), Type::Tuple(b)) => {
1421 a.iter().eq_by(b, |a, b| a.is_doc_subtype_of(b, cache))
1422 }
1423 (Type::Slice(a), Type::Slice(b)) => a.is_doc_subtype_of(b, cache),
1424 (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_doc_subtype_of(b, cache),
1425 (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
1426 mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache)
1427 }
1428 (
1429 Type::BorrowedRef { mutability, type_, .. },
1430 Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
1431 ) => mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache),
1432 (Type::Infer, _) | (_, Type::Infer) => true,
1434 (_, Type::Generic(_)) => true,
1437 (Type::Generic(_), _) => false,
1438 (Type::SelfTy, Type::SelfTy) => true,
1440 (Type::Path { path: a }, Type::Path { path: b }) => {
1442 a.def_id() == b.def_id()
1443 && a.generics()
1444 .zip(b.generics())
1445 .map(|(ag, bg)| ag.zip(bg).all(|(at, bt)| at.is_doc_subtype_of(bt, cache)))
1446 .unwrap_or(true)
1447 }
1448 (a, b) => a
1450 .def_id(cache)
1451 .and_then(|a| Some((a, b.def_id(cache)?)))
1452 .map(|(a, b)| a == b)
1453 .unwrap_or(false),
1454 }
1455 }
1456
1457 pub(crate) fn primitive_type(&self) -> Option<PrimitiveType> {
1458 match *self {
1459 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1460 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1461 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1462 Tuple(ref tys) => {
1463 if tys.is_empty() {
1464 Some(PrimitiveType::Unit)
1465 } else {
1466 Some(PrimitiveType::Tuple)
1467 }
1468 }
1469 RawPointer(..) => Some(PrimitiveType::RawPointer),
1470 BareFunction(..) => Some(PrimitiveType::Fn),
1471 _ => None,
1472 }
1473 }
1474
1475 pub(crate) fn sugared_async_return_type(self) -> Type {
1485 if let Type::ImplTrait(mut v) = self
1486 && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = v.pop()
1487 && let Some(segment) = trait_.segments.pop()
1488 && let GenericArgs::AngleBracketed { mut constraints, .. } = segment.args
1489 && let Some(constraint) = constraints.pop()
1490 && let AssocItemConstraintKind::Equality { term } = constraint.kind
1491 && let Term::Type(ty) = term
1492 {
1493 ty
1494 } else {
1495 panic!("unexpected async fn return type")
1496 }
1497 }
1498
1499 pub(crate) fn is_assoc_ty(&self) -> bool {
1501 match self {
1502 Type::Path { path, .. } => path.is_assoc_ty(),
1503 _ => false,
1504 }
1505 }
1506
1507 pub(crate) fn is_self_type(&self) -> bool {
1508 matches!(*self, Type::SelfTy)
1509 }
1510
1511 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
1512 match self {
1513 Type::Path { path, .. } => path.generic_args(),
1514 _ => None,
1515 }
1516 }
1517
1518 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
1519 match self {
1520 Type::Path { path, .. } => path.generics(),
1521 _ => None,
1522 }
1523 }
1524
1525 pub(crate) fn is_full_generic(&self) -> bool {
1526 matches!(self, Type::Generic(_))
1527 }
1528
1529 pub(crate) fn is_unit(&self) -> bool {
1530 matches!(self, Type::Tuple(v) if v.is_empty())
1531 }
1532
1533 pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
1537 let t: PrimitiveType = match self {
1538 Type::Path { path } => return Some(path.def_id()),
1539 DynTrait(bounds, _) => return bounds.first().map(|b| b.trait_.def_id()),
1540 Primitive(p) => return cache.primitive_locations.get(p).cloned(),
1541 BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
1542 BorrowedRef { type_, .. } => return type_.def_id(cache),
1543 Tuple(tys) => {
1544 if tys.is_empty() {
1545 PrimitiveType::Unit
1546 } else {
1547 PrimitiveType::Tuple
1548 }
1549 }
1550 BareFunction(..) => PrimitiveType::Fn,
1551 Slice(..) => PrimitiveType::Slice,
1552 Array(..) => PrimitiveType::Array,
1553 Type::Pat(..) => PrimitiveType::Pat,
1554 RawPointer(..) => PrimitiveType::RawPointer,
1555 QPath(box QPathData { self_type, .. }) => return self_type.def_id(cache),
1556 Generic(_) | SelfTy | Infer | ImplTrait(_) | UnsafeBinder(_) => return None,
1557 };
1558 Primitive(t).def_id(cache)
1559 }
1560}
1561
1562#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1563pub(crate) struct QPathData {
1564 pub assoc: PathSegment,
1565 pub self_type: Type,
1566 pub should_fully_qualify: bool,
1568 pub trait_: Option<Path>,
1569}
1570
1571#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1578pub(crate) enum PrimitiveType {
1579 Isize,
1580 I8,
1581 I16,
1582 I32,
1583 I64,
1584 I128,
1585 Usize,
1586 U8,
1587 U16,
1588 U32,
1589 U64,
1590 U128,
1591 F16,
1592 F32,
1593 F64,
1594 F128,
1595 Char,
1596 Bool,
1597 Str,
1598 Slice,
1599 Array,
1600 Pat,
1601 Tuple,
1602 Unit,
1603 RawPointer,
1604 Reference,
1605 Fn,
1606 Never,
1607}
1608
1609type SimplifiedTypes = FxIndexMap<PrimitiveType, ArrayVec<SimplifiedType, 3>>;
1610impl PrimitiveType {
1611 pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1612 use ast::{FloatTy, IntTy, UintTy};
1613 match prim {
1614 hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1615 hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1616 hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1617 hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1618 hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1619 hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1620 hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1621 hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1622 hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1623 hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1624 hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1625 hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1626 hir::PrimTy::Float(FloatTy::F16) => PrimitiveType::F16,
1627 hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1628 hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1629 hir::PrimTy::Float(FloatTy::F128) => PrimitiveType::F128,
1630 hir::PrimTy::Str => PrimitiveType::Str,
1631 hir::PrimTy::Bool => PrimitiveType::Bool,
1632 hir::PrimTy::Char => PrimitiveType::Char,
1633 }
1634 }
1635
1636 pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1637 match s {
1638 sym::isize => Some(PrimitiveType::Isize),
1639 sym::i8 => Some(PrimitiveType::I8),
1640 sym::i16 => Some(PrimitiveType::I16),
1641 sym::i32 => Some(PrimitiveType::I32),
1642 sym::i64 => Some(PrimitiveType::I64),
1643 sym::i128 => Some(PrimitiveType::I128),
1644 sym::usize => Some(PrimitiveType::Usize),
1645 sym::u8 => Some(PrimitiveType::U8),
1646 sym::u16 => Some(PrimitiveType::U16),
1647 sym::u32 => Some(PrimitiveType::U32),
1648 sym::u64 => Some(PrimitiveType::U64),
1649 sym::u128 => Some(PrimitiveType::U128),
1650 sym::bool => Some(PrimitiveType::Bool),
1651 sym::char => Some(PrimitiveType::Char),
1652 sym::str => Some(PrimitiveType::Str),
1653 sym::f16 => Some(PrimitiveType::F16),
1654 sym::f32 => Some(PrimitiveType::F32),
1655 sym::f64 => Some(PrimitiveType::F64),
1656 sym::f128 => Some(PrimitiveType::F128),
1657 sym::array => Some(PrimitiveType::Array),
1658 sym::slice => Some(PrimitiveType::Slice),
1659 sym::tuple => Some(PrimitiveType::Tuple),
1660 sym::unit => Some(PrimitiveType::Unit),
1661 sym::pointer => Some(PrimitiveType::RawPointer),
1662 sym::reference => Some(PrimitiveType::Reference),
1663 kw::Fn => Some(PrimitiveType::Fn),
1664 sym::never => Some(PrimitiveType::Never),
1665 _ => None,
1666 }
1667 }
1668
1669 pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
1670 use PrimitiveType::*;
1671 use ty::{FloatTy, IntTy, UintTy};
1672 static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
1673
1674 let single = |x| iter::once(x).collect();
1675 CELL.get_or_init(move || {
1676 map! {
1677 Isize => single(SimplifiedType::Int(IntTy::Isize)),
1678 I8 => single(SimplifiedType::Int(IntTy::I8)),
1679 I16 => single(SimplifiedType::Int(IntTy::I16)),
1680 I32 => single(SimplifiedType::Int(IntTy::I32)),
1681 I64 => single(SimplifiedType::Int(IntTy::I64)),
1682 I128 => single(SimplifiedType::Int(IntTy::I128)),
1683 Usize => single(SimplifiedType::Uint(UintTy::Usize)),
1684 U8 => single(SimplifiedType::Uint(UintTy::U8)),
1685 U16 => single(SimplifiedType::Uint(UintTy::U16)),
1686 U32 => single(SimplifiedType::Uint(UintTy::U32)),
1687 U64 => single(SimplifiedType::Uint(UintTy::U64)),
1688 U128 => single(SimplifiedType::Uint(UintTy::U128)),
1689 F16 => single(SimplifiedType::Float(FloatTy::F16)),
1690 F32 => single(SimplifiedType::Float(FloatTy::F32)),
1691 F64 => single(SimplifiedType::Float(FloatTy::F64)),
1692 F128 => single(SimplifiedType::Float(FloatTy::F128)),
1693 Str => single(SimplifiedType::Str),
1694 Bool => single(SimplifiedType::Bool),
1695 Char => single(SimplifiedType::Char),
1696 Array => single(SimplifiedType::Array),
1697 Slice => single(SimplifiedType::Slice),
1698 Tuple => [SimplifiedType::Tuple(1), SimplifiedType::Tuple(2), SimplifiedType::Tuple(3)].into(),
1704 Unit => single(SimplifiedType::Tuple(0)),
1705 RawPointer => [SimplifiedType::Ptr(Mutability::Not), SimplifiedType::Ptr(Mutability::Mut)].into_iter().collect(),
1706 Reference => [SimplifiedType::Ref(Mutability::Not), SimplifiedType::Ref(Mutability::Mut)].into_iter().collect(),
1707 Fn => single(SimplifiedType::Function(1)),
1710 Never => single(SimplifiedType::Never),
1711 }
1712 })
1713 }
1714
1715 pub(crate) fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = DefId> + 'tcx {
1716 Self::simplified_types()
1717 .get(self)
1718 .into_iter()
1719 .flatten()
1720 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1721 .copied()
1722 }
1723
1724 pub(crate) fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> {
1725 Self::simplified_types()
1726 .values()
1727 .flatten()
1728 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1729 .copied()
1730 }
1731
1732 pub(crate) fn as_sym(&self) -> Symbol {
1733 use PrimitiveType::*;
1734 match self {
1735 Isize => sym::isize,
1736 I8 => sym::i8,
1737 I16 => sym::i16,
1738 I32 => sym::i32,
1739 I64 => sym::i64,
1740 I128 => sym::i128,
1741 Usize => sym::usize,
1742 U8 => sym::u8,
1743 U16 => sym::u16,
1744 U32 => sym::u32,
1745 U64 => sym::u64,
1746 U128 => sym::u128,
1747 F16 => sym::f16,
1748 F32 => sym::f32,
1749 F64 => sym::f64,
1750 F128 => sym::f128,
1751 Str => sym::str,
1752 Bool => sym::bool,
1753 Char => sym::char,
1754 Array => sym::array,
1755 Pat => sym::pat,
1756 Slice => sym::slice,
1757 Tuple => sym::tuple,
1758 Unit => sym::unit,
1759 RawPointer => sym::pointer,
1760 Reference => sym::reference,
1761 Fn => kw::Fn,
1762 Never => sym::never,
1763 }
1764 }
1765
1766 pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxIndexMap<PrimitiveType, DefId> {
1778 static PRIMITIVE_LOCATIONS: OnceCell<FxIndexMap<PrimitiveType, DefId>> = OnceCell::new();
1779 PRIMITIVE_LOCATIONS.get_or_init(|| {
1780 let mut primitive_locations = FxIndexMap::default();
1781 for &crate_num in tcx.crates(()) {
1784 let e = ExternalCrate { crate_num };
1785 let crate_name = e.name(tcx);
1786 debug!(?crate_num, ?crate_name);
1787 for (def_id, prim) in e.primitives(tcx) {
1788 if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1790 continue;
1791 }
1792 primitive_locations.insert(prim, def_id);
1793 }
1794 }
1795 let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1796 for (def_id, prim) in local_primitives {
1797 primitive_locations.insert(prim, def_id);
1798 }
1799 primitive_locations
1800 })
1801 }
1802}
1803
1804impl From<ty::IntTy> for PrimitiveType {
1805 fn from(int_ty: ty::IntTy) -> PrimitiveType {
1806 match int_ty {
1807 ty::IntTy::Isize => PrimitiveType::Isize,
1808 ty::IntTy::I8 => PrimitiveType::I8,
1809 ty::IntTy::I16 => PrimitiveType::I16,
1810 ty::IntTy::I32 => PrimitiveType::I32,
1811 ty::IntTy::I64 => PrimitiveType::I64,
1812 ty::IntTy::I128 => PrimitiveType::I128,
1813 }
1814 }
1815}
1816
1817impl From<ty::UintTy> for PrimitiveType {
1818 fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1819 match uint_ty {
1820 ty::UintTy::Usize => PrimitiveType::Usize,
1821 ty::UintTy::U8 => PrimitiveType::U8,
1822 ty::UintTy::U16 => PrimitiveType::U16,
1823 ty::UintTy::U32 => PrimitiveType::U32,
1824 ty::UintTy::U64 => PrimitiveType::U64,
1825 ty::UintTy::U128 => PrimitiveType::U128,
1826 }
1827 }
1828}
1829
1830impl From<ty::FloatTy> for PrimitiveType {
1831 fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1832 match float_ty {
1833 ty::FloatTy::F16 => PrimitiveType::F16,
1834 ty::FloatTy::F32 => PrimitiveType::F32,
1835 ty::FloatTy::F64 => PrimitiveType::F64,
1836 ty::FloatTy::F128 => PrimitiveType::F128,
1837 }
1838 }
1839}
1840
1841impl From<hir::PrimTy> for PrimitiveType {
1842 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1843 match prim_ty {
1844 hir::PrimTy::Int(int_ty) => int_ty.into(),
1845 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1846 hir::PrimTy::Float(float_ty) => float_ty.into(),
1847 hir::PrimTy::Str => PrimitiveType::Str,
1848 hir::PrimTy::Bool => PrimitiveType::Bool,
1849 hir::PrimTy::Char => PrimitiveType::Char,
1850 }
1851 }
1852}
1853
1854#[derive(Clone, Debug)]
1855pub(crate) struct Struct {
1856 pub(crate) ctor_kind: Option<CtorKind>,
1857 pub(crate) generics: Generics,
1858 pub(crate) fields: ThinVec<Item>,
1859}
1860
1861impl Struct {
1862 pub(crate) fn has_stripped_entries(&self) -> bool {
1863 self.fields.iter().any(|f| f.is_stripped())
1864 }
1865}
1866
1867#[derive(Clone, Debug)]
1868pub(crate) struct Union {
1869 pub(crate) generics: Generics,
1870 pub(crate) fields: Vec<Item>,
1871}
1872
1873impl Union {
1874 pub(crate) fn has_stripped_entries(&self) -> bool {
1875 self.fields.iter().any(|f| f.is_stripped())
1876 }
1877}
1878
1879#[derive(Clone, Debug)]
1883pub(crate) struct VariantStruct {
1884 pub(crate) fields: ThinVec<Item>,
1885}
1886
1887impl VariantStruct {
1888 pub(crate) fn has_stripped_entries(&self) -> bool {
1889 self.fields.iter().any(|f| f.is_stripped())
1890 }
1891}
1892
1893#[derive(Clone, Debug)]
1894pub(crate) struct Enum {
1895 pub(crate) variants: IndexVec<VariantIdx, Item>,
1896 pub(crate) generics: Generics,
1897}
1898
1899impl Enum {
1900 pub(crate) fn has_stripped_entries(&self) -> bool {
1901 self.variants.iter().any(|f| f.is_stripped())
1902 }
1903
1904 pub(crate) fn non_stripped_variants(&self) -> impl Iterator<Item = &Item> {
1905 self.variants.iter().filter(|v| !v.is_stripped())
1906 }
1907}
1908
1909#[derive(Clone, Debug)]
1910pub(crate) struct Variant {
1911 pub kind: VariantKind,
1912 pub discriminant: Option<Discriminant>,
1913}
1914
1915#[derive(Clone, Debug)]
1916pub(crate) enum VariantKind {
1917 CLike,
1918 Tuple(ThinVec<Item>),
1919 Struct(VariantStruct),
1920}
1921
1922impl Variant {
1923 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
1924 match &self.kind {
1925 VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()),
1926 VariantKind::CLike | VariantKind::Tuple(_) => None,
1927 }
1928 }
1929}
1930
1931#[derive(Clone, Debug)]
1932pub(crate) struct Discriminant {
1933 pub(super) expr: Option<BodyId>,
1936 pub(super) value: DefId,
1937}
1938
1939impl Discriminant {
1940 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
1943 self.expr
1944 .map(|body| rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body)))
1945 }
1946 pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String {
1947 print_evaluated_const(tcx, self.value, with_underscores, false).unwrap()
1948 }
1949}
1950
1951#[derive(Copy, Clone, Debug)]
1954pub(crate) struct Span(rustc_span::Span);
1955
1956impl Span {
1957 pub(crate) fn new(sp: rustc_span::Span) -> Self {
1962 Self(sp.source_callsite())
1963 }
1964
1965 pub(crate) fn inner(&self) -> rustc_span::Span {
1966 self.0
1967 }
1968
1969 pub(crate) fn filename(&self, sess: &Session) -> FileName {
1970 sess.source_map().span_to_filename(self.0)
1971 }
1972
1973 pub(crate) fn lo(&self, sess: &Session) -> Loc {
1974 sess.source_map().lookup_char_pos(self.0.lo())
1975 }
1976
1977 pub(crate) fn hi(&self, sess: &Session) -> Loc {
1978 sess.source_map().lookup_char_pos(self.0.hi())
1979 }
1980
1981 pub(crate) fn cnum(&self, sess: &Session) -> CrateNum {
1982 self.lo(sess).file.cnum
1984 }
1985}
1986
1987#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1988pub(crate) struct Path {
1989 pub(crate) res: Res,
1990 pub(crate) segments: ThinVec<PathSegment>,
1991}
1992
1993impl Path {
1994 pub(crate) fn def_id(&self) -> DefId {
1995 self.res.def_id()
1996 }
1997
1998 pub(crate) fn last_opt(&self) -> Option<Symbol> {
1999 self.segments.last().map(|s| s.name)
2000 }
2001
2002 pub(crate) fn last(&self) -> Symbol {
2003 self.last_opt().expect("segments were empty")
2004 }
2005
2006 pub(crate) fn whole_name(&self) -> String {
2007 self.segments
2008 .iter()
2009 .map(|s| if s.name == kw::PathRoot { "" } else { s.name.as_str() })
2010 .intersperse("::")
2011 .collect()
2012 }
2013
2014 pub(crate) fn is_assoc_ty(&self) -> bool {
2016 match self.res {
2017 Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _)
2018 if self.segments.len() != 1 =>
2019 {
2020 true
2021 }
2022 Res::Def(DefKind::AssocTy, _) => true,
2023 _ => false,
2024 }
2025 }
2026
2027 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
2028 self.segments.last().map(|seg| &seg.args)
2029 }
2030
2031 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
2032 self.segments.last().and_then(|seg| {
2033 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2034 Some(args.iter().filter_map(|arg| match arg {
2035 GenericArg::Type(ty) => Some(ty),
2036 _ => None,
2037 }))
2038 } else {
2039 None
2040 }
2041 })
2042 }
2043}
2044
2045#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2046pub(crate) enum GenericArg {
2047 Lifetime(Lifetime),
2048 Type(Type),
2049 Const(Box<ConstantKind>),
2050 Infer,
2051}
2052
2053impl GenericArg {
2054 pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
2055 if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2056 }
2057
2058 pub(crate) fn as_ty(&self) -> Option<&Type> {
2059 if let Self::Type(ty) = self { Some(ty) } else { None }
2060 }
2061}
2062
2063#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2064pub(crate) enum GenericArgs {
2065 AngleBracketed { args: ThinVec<GenericArg>, constraints: ThinVec<AssocItemConstraint> },
2067 Parenthesized { inputs: ThinVec<Type>, output: Option<Box<Type>> },
2069 ReturnTypeNotation,
2071}
2072
2073impl GenericArgs {
2074 pub(crate) fn is_empty(&self) -> bool {
2075 match self {
2076 GenericArgs::AngleBracketed { args, constraints } => {
2077 args.is_empty() && constraints.is_empty()
2078 }
2079 GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
2080 GenericArgs::ReturnTypeNotation => false,
2081 }
2082 }
2083 pub(crate) fn constraints(&self) -> Box<dyn Iterator<Item = AssocItemConstraint> + '_> {
2084 match self {
2085 GenericArgs::AngleBracketed { constraints, .. } => {
2086 Box::new(constraints.iter().cloned())
2087 }
2088 GenericArgs::Parenthesized { output, .. } => Box::new(
2089 output
2090 .as_ref()
2091 .map(|ty| AssocItemConstraint {
2092 assoc: PathSegment {
2093 name: sym::Output,
2094 args: GenericArgs::AngleBracketed {
2095 args: ThinVec::new(),
2096 constraints: ThinVec::new(),
2097 },
2098 },
2099 kind: AssocItemConstraintKind::Equality {
2100 term: Term::Type((**ty).clone()),
2101 },
2102 })
2103 .into_iter(),
2104 ),
2105 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2106 }
2107 }
2108}
2109
2110impl<'a> IntoIterator for &'a GenericArgs {
2111 type IntoIter = Box<dyn Iterator<Item = GenericArg> + 'a>;
2112 type Item = GenericArg;
2113 fn into_iter(self) -> Self::IntoIter {
2114 match self {
2115 GenericArgs::AngleBracketed { args, .. } => Box::new(args.iter().cloned()),
2116 GenericArgs::Parenthesized { inputs, .. } => {
2117 Box::new(inputs.iter().cloned().map(GenericArg::Type))
2119 }
2120 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2121 }
2122 }
2123}
2124
2125#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2126pub(crate) struct PathSegment {
2127 pub(crate) name: Symbol,
2128 pub(crate) args: GenericArgs,
2129}
2130
2131#[derive(Clone, Debug)]
2132pub(crate) enum TypeAliasInnerType {
2133 Enum { variants: IndexVec<VariantIdx, Item>, is_non_exhaustive: bool },
2134 Union { fields: Vec<Item> },
2135 Struct { ctor_kind: Option<CtorKind>, fields: Vec<Item> },
2136}
2137
2138impl TypeAliasInnerType {
2139 fn has_stripped_entries(&self) -> Option<bool> {
2140 Some(match self {
2141 Self::Enum { variants, .. } => variants.iter().any(|v| v.is_stripped()),
2142 Self::Union { fields } | Self::Struct { fields, .. } => {
2143 fields.iter().any(|f| f.is_stripped())
2144 }
2145 })
2146 }
2147}
2148
2149#[derive(Clone, Debug)]
2150pub(crate) struct TypeAlias {
2151 pub(crate) type_: Type,
2152 pub(crate) generics: Generics,
2153 pub(crate) inner_type: Option<TypeAliasInnerType>,
2156 pub(crate) item_type: Option<Type>,
2163}
2164
2165#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2166pub(crate) struct BareFunctionDecl {
2167 pub(crate) safety: hir::Safety,
2168 pub(crate) generic_params: Vec<GenericParamDef>,
2169 pub(crate) decl: FnDecl,
2170 pub(crate) abi: ExternAbi,
2171}
2172
2173#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2174pub(crate) struct UnsafeBinderTy {
2175 pub(crate) generic_params: Vec<GenericParamDef>,
2176 pub(crate) ty: Type,
2177}
2178
2179#[derive(Clone, Debug)]
2180pub(crate) struct Static {
2181 pub(crate) type_: Box<Type>,
2182 pub(crate) mutability: Mutability,
2183 pub(crate) expr: Option<BodyId>,
2184}
2185
2186#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2187pub(crate) struct Constant {
2188 pub(crate) generics: Generics,
2189 pub(crate) kind: ConstantKind,
2190 pub(crate) type_: Type,
2191}
2192
2193#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2194pub(crate) enum Term {
2195 Type(Type),
2196 Constant(ConstantKind),
2197}
2198
2199impl Term {
2200 pub(crate) fn ty(&self) -> Option<&Type> {
2201 if let Term::Type(ty) = self { Some(ty) } else { None }
2202 }
2203}
2204
2205impl From<Type> for Term {
2206 fn from(ty: Type) -> Self {
2207 Term::Type(ty)
2208 }
2209}
2210
2211#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2212pub(crate) enum ConstantKind {
2213 TyConst { expr: Box<str> },
2219 Path { path: Box<str> },
2222 Anonymous { body: BodyId },
2226 Extern { def_id: DefId },
2228 Local { def_id: DefId, body: BodyId },
2230 Infer,
2232}
2233
2234impl ConstantKind {
2235 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2236 match *self {
2237 ConstantKind::TyConst { ref expr } => expr.to_string(),
2238 ConstantKind::Path { ref path } => path.to_string(),
2239 ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2240 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2241 rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body))
2242 }
2243 ConstantKind::Infer => "_".to_string(),
2244 }
2245 }
2246
2247 pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2248 match *self {
2249 ConstantKind::TyConst { .. }
2250 | ConstantKind::Path { .. }
2251 | ConstantKind::Anonymous { .. }
2252 | ConstantKind::Infer => None,
2253 ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2254 print_evaluated_const(tcx, def_id, true, true)
2255 }
2256 }
2257 }
2258
2259 pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2260 match *self {
2261 ConstantKind::TyConst { .. }
2262 | ConstantKind::Extern { .. }
2263 | ConstantKind::Path { .. }
2264 | ConstantKind::Infer => false,
2265 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2266 is_literal_expr(tcx, body.hir_id)
2267 }
2268 }
2269 }
2270}
2271
2272#[derive(Clone, Debug)]
2273pub(crate) struct Impl {
2274 pub(crate) safety: hir::Safety,
2275 pub(crate) generics: Generics,
2276 pub(crate) trait_: Option<Path>,
2277 pub(crate) for_: Type,
2278 pub(crate) items: Vec<Item>,
2279 pub(crate) polarity: ty::ImplPolarity,
2280 pub(crate) kind: ImplKind,
2281}
2282
2283impl Impl {
2284 pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxIndexSet<Symbol> {
2285 self.trait_
2286 .as_ref()
2287 .map(|t| t.def_id())
2288 .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name()).collect())
2289 .unwrap_or_default()
2290 }
2291
2292 pub(crate) fn is_negative_trait_impl(&self) -> bool {
2293 matches!(self.polarity, ty::ImplPolarity::Negative)
2294 }
2295}
2296
2297#[derive(Clone, Debug)]
2298pub(crate) enum ImplKind {
2299 Normal,
2300 Auto,
2301 FakeVariadic,
2302 Blanket(Box<Type>),
2303}
2304
2305impl ImplKind {
2306 pub(crate) fn is_auto(&self) -> bool {
2307 matches!(self, ImplKind::Auto)
2308 }
2309
2310 pub(crate) fn is_blanket(&self) -> bool {
2311 matches!(self, ImplKind::Blanket(_))
2312 }
2313
2314 pub(crate) fn is_fake_variadic(&self) -> bool {
2315 matches!(self, ImplKind::FakeVariadic)
2316 }
2317
2318 pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
2319 match self {
2320 ImplKind::Blanket(ty) => Some(ty),
2321 _ => None,
2322 }
2323 }
2324}
2325
2326#[derive(Clone, Debug)]
2327pub(crate) struct Import {
2328 pub(crate) kind: ImportKind,
2329 pub(crate) source: ImportSource,
2331 pub(crate) should_be_displayed: bool,
2332}
2333
2334impl Import {
2335 pub(crate) fn new_simple(
2336 name: Symbol,
2337 source: ImportSource,
2338 should_be_displayed: bool,
2339 ) -> Self {
2340 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2341 }
2342
2343 pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2344 Self { kind: ImportKind::Glob, source, should_be_displayed }
2345 }
2346
2347 pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool {
2348 self.source.did.is_some_and(|did| tcx.is_doc_hidden(did))
2349 }
2350}
2351
2352#[derive(Clone, Debug)]
2353pub(crate) enum ImportKind {
2354 Simple(Symbol),
2356 Glob,
2358}
2359
2360#[derive(Clone, Debug)]
2361pub(crate) struct ImportSource {
2362 pub(crate) path: Path,
2363 pub(crate) did: Option<DefId>,
2364}
2365
2366#[derive(Clone, Debug)]
2367pub(crate) struct Macro {
2368 pub(crate) source: String,
2369 pub(crate) macro_rules: bool,
2371}
2372
2373#[derive(Clone, Debug)]
2374pub(crate) struct ProcMacro {
2375 pub(crate) kind: MacroKind,
2376 pub(crate) helpers: Vec<Symbol>,
2377}
2378
2379#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2390pub(crate) struct AssocItemConstraint {
2391 pub(crate) assoc: PathSegment,
2392 pub(crate) kind: AssocItemConstraintKind,
2393}
2394
2395#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2397pub(crate) enum AssocItemConstraintKind {
2398 Equality { term: Term },
2399 Bound { bounds: Vec<GenericBound> },
2400}
2401
2402#[cfg(target_pointer_width = "64")]
2404mod size_asserts {
2405 use rustc_data_structures::static_assert_size;
2406
2407 use super::*;
2408 static_assert_size!(Crate, 16); static_assert_size!(DocFragment, 32);
2411 static_assert_size!(GenericArg, 32);
2412 static_assert_size!(GenericArgs, 24);
2413 static_assert_size!(GenericParamDef, 40);
2414 static_assert_size!(Generics, 16);
2415 static_assert_size!(Item, 8);
2416 static_assert_size!(ItemInner, 144);
2417 static_assert_size!(ItemKind, 48);
2418 static_assert_size!(PathSegment, 32);
2419 static_assert_size!(Type, 32);
2420 }