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