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