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, DocAttribute};
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::{Attribute, 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_all_attrs(did)
194 .iter()
195 .find_map(|a| match a {
196 Attribute::Parsed(AttributeKind::Doc(d)) => d.html_root_url.map(|(url, _)| url),
197 _ => None,
198 })
199 .map(to_remote)
200 .or_else(|| extern_url.map(to_remote)) .unwrap_or(Unknown) }
203
204 fn mapped_root_modules<T>(
205 &self,
206 tcx: TyCtxt<'_>,
207 f: impl Fn(DefId, TyCtxt<'_>) -> Option<(DefId, T)>,
208 ) -> impl Iterator<Item = (DefId, T)> {
209 let root = self.def_id();
210
211 if root.is_local() {
212 Either::Left(
213 tcx.hir_root_module()
214 .item_ids
215 .iter()
216 .filter(move |&&id| matches!(tcx.hir_item(id).kind, hir::ItemKind::Mod(..)))
217 .filter_map(move |&id| f(id.owner_id.into(), tcx)),
218 )
219 } else {
220 Either::Right(
221 tcx.module_children(root)
222 .iter()
223 .filter_map(|item| {
224 if let Res::Def(DefKind::Mod, did) = item.res { Some(did) } else { None }
225 })
226 .filter_map(move |did| f(did, tcx)),
227 )
228 }
229 }
230
231 pub(crate) fn keywords(&self, tcx: TyCtxt<'_>) -> impl Iterator<Item = (DefId, Symbol)> {
232 self.retrieve_keywords_or_documented_attributes(tcx, |d| d.keyword.map(|(v, _)| v))
233 }
234 pub(crate) fn documented_attributes(
235 &self,
236 tcx: TyCtxt<'_>,
237 ) -> impl Iterator<Item = (DefId, Symbol)> {
238 self.retrieve_keywords_or_documented_attributes(tcx, |d| d.attribute.map(|(v, _)| v))
239 }
240
241 fn retrieve_keywords_or_documented_attributes<F: Fn(&DocAttribute) -> Option<Symbol>>(
242 &self,
243 tcx: TyCtxt<'_>,
244 callback: F,
245 ) -> impl Iterator<Item = (DefId, Symbol)> {
246 let as_target = move |did: DefId, tcx: TyCtxt<'_>| -> Option<(DefId, Symbol)> {
247 tcx.get_all_attrs(did)
248 .iter()
249 .find_map(|attr| match attr {
250 Attribute::Parsed(AttributeKind::Doc(d)) => callback(d),
251 _ => None,
252 })
253 .map(|value| (did, value))
254 };
255 self.mapped_root_modules(tcx, as_target)
256 }
257
258 pub(crate) fn primitives(
259 &self,
260 tcx: TyCtxt<'_>,
261 ) -> impl Iterator<Item = (DefId, PrimitiveType)> {
262 fn as_primitive(def_id: DefId, tcx: TyCtxt<'_>) -> Option<(DefId, PrimitiveType)> {
280 tcx.get_attrs(def_id, sym::rustc_doc_primitive).next().map(|attr| {
281 let attr_value = attr.value_str().expect("syntax should already be validated");
282 let Some(prim) = PrimitiveType::from_symbol(attr_value) else {
283 span_bug!(
284 attr.span(),
285 "primitive `{attr_value}` is not a member of `PrimitiveType`"
286 );
287 };
288
289 (def_id, prim)
290 })
291 }
292
293 self.mapped_root_modules(tcx, as_primitive)
294 }
295}
296
297#[derive(Debug)]
299pub(crate) enum ExternalLocation {
300 Remote(String),
302 Local,
304 Unknown,
306}
307
308#[derive(Clone)]
312pub(crate) struct Item {
313 pub(crate) inner: Box<ItemInner>,
314}
315
316#[derive(Clone)]
322pub(crate) struct ItemInner {
323 pub(crate) name: Option<Symbol>,
326 pub(crate) kind: ItemKind,
329 pub(crate) attrs: Attributes,
330 pub(crate) stability: Option<Stability>,
332 pub(crate) item_id: ItemId,
333 pub(crate) inline_stmt_id: Option<LocalDefId>,
337 pub(crate) cfg: Option<Arc<Cfg>>,
338}
339
340impl std::ops::Deref for Item {
341 type Target = ItemInner;
342 fn deref(&self) -> &ItemInner {
343 &self.inner
344 }
345}
346
347impl fmt::Debug for Item {
350 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
351 let alternate = f.alternate();
352 let mut fmt = f.debug_struct("Item");
354 fmt.field("name", &self.name).field("item_id", &self.item_id);
355 if alternate {
357 fmt.field("attrs", &self.attrs).field("kind", &self.kind).field("cfg", &self.cfg);
358 } else {
359 fmt.field("kind", &self.type_());
360 fmt.field("docs", &self.doc_value());
361 }
362 fmt.finish()
363 }
364}
365
366pub(crate) fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
367 Span::new(def_id.as_local().map_or_else(
368 || tcx.def_span(def_id),
369 |local| tcx.hir_span_with_body(tcx.local_def_id_to_hir_id(local)),
370 ))
371}
372
373fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
374 let parent = tcx.parent(def_id);
375 match tcx.def_kind(parent) {
376 DefKind::Struct | DefKind::Union => false,
377 DefKind::Variant => true,
378 parent_kind => panic!("unexpected parent kind: {parent_kind:?}"),
379 }
380}
381
382impl Item {
383 pub(crate) fn stability(&self, tcx: TyCtxt<'_>) -> Option<Stability> {
387 let stability = self.inner.stability;
388 debug_assert!(
389 stability.is_some()
390 || self.def_id().is_none_or(|did| tcx.lookup_stability(did).is_none()),
391 "missing stability for cleaned item: {self:?}",
392 );
393 stability
394 }
395
396 pub(crate) fn const_stability(&self, tcx: TyCtxt<'_>) -> Option<ConstStability> {
397 self.def_id().and_then(|did| tcx.lookup_const_stability(did))
398 }
399
400 pub(crate) fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
401 self.def_id().and_then(|did| tcx.lookup_deprecation(did)).or_else(|| {
402 let stab = self.stability(tcx)?;
406 if let rustc_hir::StabilityLevel::Stable {
407 allowed_through_unstable_modules: Some(note),
408 ..
409 } = stab.level
410 {
411 Some(Deprecation {
412 since: DeprecatedSince::Unspecified,
413 note: Some(note),
414 suggestion: None,
415 })
416 } else {
417 None
418 }
419 })
420 }
421
422 pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
423 self.item_id.as_def_id().map(|did| inner_docs(tcx.get_all_attrs(did))).unwrap_or(false)
424 }
425
426 pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option<Span> {
427 let kind = match &self.kind {
428 ItemKind::StrippedItem(k) => k,
429 _ => &self.kind,
430 };
431 match kind {
432 ItemKind::ModuleItem(Module { span, .. }) => Some(*span),
433 ItemKind::ImplItem(box Impl { kind: ImplKind::Auto, .. }) => None,
434 ItemKind::ImplItem(box Impl { kind: ImplKind::Blanket(_), .. }) => {
435 if let ItemId::Blanket { impl_id, .. } = self.item_id {
436 Some(rustc_span(impl_id, tcx))
437 } else {
438 panic!("blanket impl item has non-blanket ID")
439 }
440 }
441 _ => self.def_id().map(|did| rustc_span(did, tcx)),
442 }
443 }
444
445 pub(crate) fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
446 span_of_fragments(&self.attrs.doc_strings)
447 .unwrap_or_else(|| self.span(tcx).map_or(DUMMY_SP, |span| span.inner()))
448 }
449
450 pub(crate) fn doc_value(&self) -> String {
452 self.attrs.doc_value()
453 }
454
455 pub(crate) fn opt_doc_value(&self) -> Option<String> {
459 self.attrs.opt_doc_value()
460 }
461
462 pub(crate) fn from_def_id_and_parts(
463 def_id: DefId,
464 name: Option<Symbol>,
465 kind: ItemKind,
466 cx: &mut DocContext<'_>,
467 ) -> Item {
468 let hir_attrs = cx.tcx.get_all_attrs(def_id);
469
470 Self::from_def_id_and_attrs_and_parts(
471 def_id,
472 name,
473 kind,
474 Attributes::from_hir(hir_attrs),
475 None,
476 )
477 }
478
479 pub(crate) fn from_def_id_and_attrs_and_parts(
480 def_id: DefId,
481 name: Option<Symbol>,
482 kind: ItemKind,
483 attrs: Attributes,
484 cfg: Option<Arc<Cfg>>,
485 ) -> Item {
486 trace!("name={name:?}, def_id={def_id:?} cfg={cfg:?}");
487
488 Item {
489 inner: Box::new(ItemInner {
490 item_id: def_id.into(),
491 kind,
492 attrs,
493 stability: None,
494 name,
495 cfg,
496 inline_stmt_id: None,
497 }),
498 }
499 }
500
501 pub(crate) fn item_or_reexport_id(&self) -> ItemId {
507 self.attrs
509 .doc_strings
510 .first()
511 .map(|x| x.item_id)
512 .flatten()
513 .map(ItemId::from)
514 .unwrap_or(self.item_id)
515 }
516
517 pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
518 use crate::html::format::{href, link_tooltip};
519
520 let Some(links) = cx.cache().intra_doc_links.get(&self.item_or_reexport_id()) else {
521 return vec![];
522 };
523 links
524 .iter()
525 .filter_map(|ItemLink { link: s, link_text, page_id: id, fragment }| {
526 debug!(?id);
527 if let Ok(HrefInfo { mut url, .. }) = href(*id, cx) {
528 debug!(?url);
529 match fragment {
530 Some(UrlFragment::Item(def_id)) => {
531 write!(url, "{}", crate::html::format::fragment(*def_id, cx.tcx()))
532 .unwrap();
533 }
534 Some(UrlFragment::UserWritten(raw)) => {
535 url.push('#');
536 url.push_str(raw);
537 }
538 None => {}
539 }
540 Some(RenderedLink {
541 original_text: s.clone(),
542 new_text: link_text.clone(),
543 tooltip: link_tooltip(*id, fragment, cx).to_string(),
544 href: url,
545 })
546 } else {
547 None
548 }
549 })
550 .collect()
551 }
552
553 pub(crate) fn link_names(&self, cache: &Cache) -> Vec<RenderedLink> {
559 let Some(links) = cache.intra_doc_links.get(&self.item_id) else {
560 return vec![];
561 };
562 links
563 .iter()
564 .map(|ItemLink { link: s, link_text, .. }| RenderedLink {
565 original_text: s.clone(),
566 new_text: link_text.clone(),
567 href: String::new(),
568 tooltip: String::new(),
569 })
570 .collect()
571 }
572
573 pub(crate) fn is_crate(&self) -> bool {
574 self.is_mod() && self.def_id().is_some_and(|did| did.is_crate_root())
575 }
576 pub(crate) fn is_mod(&self) -> bool {
577 self.type_() == ItemType::Module
578 }
579 pub(crate) fn is_struct(&self) -> bool {
580 self.type_() == ItemType::Struct
581 }
582 pub(crate) fn is_enum(&self) -> bool {
583 self.type_() == ItemType::Enum
584 }
585 pub(crate) fn is_variant(&self) -> bool {
586 self.type_() == ItemType::Variant
587 }
588 pub(crate) fn is_associated_type(&self) -> bool {
589 matches!(self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..)))
590 }
591 pub(crate) fn is_required_associated_type(&self) -> bool {
592 matches!(self.kind, RequiredAssocTypeItem(..) | StrippedItem(box RequiredAssocTypeItem(..)))
593 }
594 pub(crate) fn is_associated_const(&self) -> bool {
595 matches!(self.kind, ProvidedAssocConstItem(..) | ImplAssocConstItem(..) | StrippedItem(box (ProvidedAssocConstItem(..) | ImplAssocConstItem(..))))
596 }
597 pub(crate) fn is_required_associated_const(&self) -> bool {
598 matches!(self.kind, RequiredAssocConstItem(..) | StrippedItem(box RequiredAssocConstItem(..)))
599 }
600 pub(crate) fn is_method(&self) -> bool {
601 self.type_() == ItemType::Method
602 }
603 pub(crate) fn is_ty_method(&self) -> bool {
604 self.type_() == ItemType::TyMethod
605 }
606 pub(crate) fn is_primitive(&self) -> bool {
607 self.type_() == ItemType::Primitive
608 }
609 pub(crate) fn is_union(&self) -> bool {
610 self.type_() == ItemType::Union
611 }
612 pub(crate) fn is_import(&self) -> bool {
613 self.type_() == ItemType::Import
614 }
615 pub(crate) fn is_extern_crate(&self) -> bool {
616 self.type_() == ItemType::ExternCrate
617 }
618 pub(crate) fn is_keyword(&self) -> bool {
619 self.type_() == ItemType::Keyword
620 }
621 pub(crate) fn is_attribute(&self) -> bool {
622 self.type_() == ItemType::Attribute
623 }
624 pub(crate) fn is_fake_item(&self) -> bool {
633 matches!(self.type_(), ItemType::Primitive | ItemType::Keyword | ItemType::Attribute)
634 }
635 pub(crate) fn is_stripped(&self) -> bool {
636 match self.kind {
637 StrippedItem(..) => true,
638 ImportItem(ref i) => !i.should_be_displayed,
639 _ => false,
640 }
641 }
642 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
643 match self.kind {
644 StructItem(ref struct_) => Some(struct_.has_stripped_entries()),
645 UnionItem(ref union_) => Some(union_.has_stripped_entries()),
646 EnumItem(ref enum_) => Some(enum_.has_stripped_entries()),
647 VariantItem(ref v) => v.has_stripped_entries(),
648 TypeAliasItem(ref type_alias) => {
649 type_alias.inner_type.as_ref().and_then(|t| t.has_stripped_entries())
650 }
651 _ => None,
652 }
653 }
654
655 pub(crate) fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
656 self.stability(tcx).as_ref().and_then(|s| {
657 let mut classes = Vec::with_capacity(2);
658
659 if s.is_unstable() {
660 classes.push("unstable");
661 }
662
663 if self.deprecation(tcx).is_some() {
665 classes.push("deprecated");
666 }
667
668 if !classes.is_empty() { Some(classes.join(" ")) } else { None }
669 })
670 }
671
672 pub(crate) fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<StableSince> {
673 self.stability(tcx).and_then(|stability| stability.stable_since())
674 }
675
676 pub(crate) fn is_non_exhaustive(&self) -> bool {
677 find_attr!(&self.attrs.other_attrs, AttributeKind::NonExhaustive(..))
678 }
679
680 pub(crate) fn type_(&self) -> ItemType {
682 ItemType::from(self)
683 }
684
685 pub(crate) fn is_default(&self) -> bool {
686 match self.kind {
687 ItemKind::MethodItem(_, Some(defaultness)) => {
688 defaultness.has_value() && !defaultness.is_final()
689 }
690 _ => false,
691 }
692 }
693
694 pub(crate) fn fn_header(&self, tcx: TyCtxt<'_>) -> Option<hir::FnHeader> {
696 fn build_fn_header(
697 def_id: DefId,
698 tcx: TyCtxt<'_>,
699 asyncness: ty::Asyncness,
700 ) -> hir::FnHeader {
701 let sig = tcx.fn_sig(def_id).skip_binder();
702 let constness = if tcx.is_const_fn(def_id) {
703 if let Some(assoc) = tcx.opt_associated_item(def_id)
707 && let ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) =
708 assoc.container
709 {
710 hir::Constness::NotConst
711 } else {
712 hir::Constness::Const
713 }
714 } else {
715 hir::Constness::NotConst
716 };
717 let asyncness = match asyncness {
718 ty::Asyncness::Yes => hir::IsAsync::Async(DUMMY_SP),
719 ty::Asyncness::No => hir::IsAsync::NotAsync,
720 };
721 hir::FnHeader {
722 safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
723 hir::HeaderSafety::SafeTargetFeatures
724 } else {
725 sig.safety().into()
726 },
727 abi: sig.abi(),
728 constness,
729 asyncness,
730 }
731 }
732 let header = match self.kind {
733 ItemKind::ForeignFunctionItem(_, safety) => {
734 let def_id = self.def_id().unwrap();
735 let abi = tcx.fn_sig(def_id).skip_binder().abi();
736 hir::FnHeader {
737 safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
738 hir::HeaderSafety::SafeTargetFeatures
739 } else {
740 safety.into()
741 },
742 abi,
743 constness: if tcx.is_const_fn(def_id) {
744 hir::Constness::Const
745 } else {
746 hir::Constness::NotConst
747 },
748 asyncness: hir::IsAsync::NotAsync,
749 }
750 }
751 ItemKind::FunctionItem(_)
752 | ItemKind::MethodItem(_, _)
753 | ItemKind::RequiredMethodItem(_) => {
754 let def_id = self.def_id().unwrap();
755 build_fn_header(def_id, tcx, tcx.asyncness(def_id))
756 }
757 _ => return None,
758 };
759 Some(header)
760 }
761
762 pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option<Visibility<DefId>> {
765 let def_id = match self.item_id {
766 ItemId::Auto { .. } | ItemId::Blanket { .. } => return None,
768 ItemId::DefId(def_id) => def_id,
769 };
770
771 match self.kind {
772 ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) | ItemKind::AttributeItem => {
776 return Some(Visibility::Public);
777 }
778 StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => {
780 return None;
781 }
782 VariantItem(..) | ImplItem(..) => return None,
784 RequiredAssocConstItem(..)
786 | ProvidedAssocConstItem(..)
787 | ImplAssocConstItem(..)
788 | AssocTypeItem(..)
789 | RequiredAssocTypeItem(..)
790 | RequiredMethodItem(..)
791 | MethodItem(..) => {
792 match tcx.associated_item(def_id).container {
793 ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) => {
796 return None;
797 }
798 ty::AssocContainer::InherentImpl => {}
799 }
800 }
801 _ => {}
802 }
803 let def_id = match self.inline_stmt_id {
804 Some(inlined) => inlined.to_def_id(),
805 None => def_id,
806 };
807 Some(tcx.visibility(def_id))
808 }
809
810 pub fn is_doc_hidden(&self) -> bool {
811 self.attrs.is_doc_hidden()
812 }
813
814 pub fn def_id(&self) -> Option<DefId> {
815 self.item_id.as_def_id()
816 }
817}
818
819#[derive(Clone, Debug)]
820pub(crate) enum ItemKind {
821 ExternCrateItem {
822 src: Option<Symbol>,
824 },
825 ImportItem(Import),
826 StructItem(Struct),
827 UnionItem(Union),
828 EnumItem(Enum),
829 FunctionItem(Box<Function>),
830 ModuleItem(Module),
831 TypeAliasItem(Box<TypeAlias>),
832 StaticItem(Static),
833 TraitItem(Box<Trait>),
834 TraitAliasItem(TraitAlias),
835 ImplItem(Box<Impl>),
836 RequiredMethodItem(Box<Function>),
838 MethodItem(Box<Function>, Option<hir::Defaultness>),
842 StructFieldItem(Type),
843 VariantItem(Variant),
844 ForeignFunctionItem(Box<Function>, hir::Safety),
846 ForeignStaticItem(Static, hir::Safety),
848 ForeignTypeItem,
850 MacroItem(Macro),
851 ProcMacroItem(ProcMacro),
852 PrimitiveItem(PrimitiveType),
853 RequiredAssocConstItem(Generics, Box<Type>),
855 ConstantItem(Box<Constant>),
856 ProvidedAssocConstItem(Box<Constant>),
858 ImplAssocConstItem(Box<Constant>),
860 RequiredAssocTypeItem(Generics, Vec<GenericBound>),
864 AssocTypeItem(Box<TypeAlias>, Vec<GenericBound>),
866 StrippedItem(Box<ItemKind>),
868 KeywordItem,
871 AttributeItem,
874}
875
876impl ItemKind {
877 pub(crate) fn inner_items(&self) -> impl Iterator<Item = &Item> {
880 match self {
881 StructItem(s) => s.fields.iter(),
882 UnionItem(u) => u.fields.iter(),
883 VariantItem(v) => match &v.kind {
884 VariantKind::CLike => [].iter(),
885 VariantKind::Tuple(t) => t.iter(),
886 VariantKind::Struct(s) => s.fields.iter(),
887 },
888 EnumItem(e) => e.variants.iter(),
889 TraitItem(t) => t.items.iter(),
890 ImplItem(i) => i.items.iter(),
891 ModuleItem(m) => m.items.iter(),
892 ExternCrateItem { .. }
893 | ImportItem(_)
894 | FunctionItem(_)
895 | TypeAliasItem(_)
896 | StaticItem(_)
897 | ConstantItem(_)
898 | TraitAliasItem(_)
899 | RequiredMethodItem(_)
900 | MethodItem(_, _)
901 | StructFieldItem(_)
902 | ForeignFunctionItem(_, _)
903 | ForeignStaticItem(_, _)
904 | ForeignTypeItem
905 | MacroItem(_)
906 | ProcMacroItem(_)
907 | PrimitiveItem(_)
908 | RequiredAssocConstItem(..)
909 | ProvidedAssocConstItem(..)
910 | ImplAssocConstItem(..)
911 | RequiredAssocTypeItem(..)
912 | AssocTypeItem(..)
913 | StrippedItem(_)
914 | KeywordItem
915 | AttributeItem => [].iter(),
916 }
917 }
918}
919
920#[derive(Clone, Debug)]
921pub(crate) struct Module {
922 pub(crate) items: Vec<Item>,
923 pub(crate) span: Span,
924}
925
926#[derive(Clone, Debug, PartialEq, Eq, Hash)]
930pub(crate) struct ItemLink {
931 pub(crate) link: Box<str>,
933 pub(crate) link_text: Box<str>,
938 pub(crate) page_id: DefId,
942 pub(crate) fragment: Option<UrlFragment>,
944}
945
946pub struct RenderedLink {
947 pub(crate) original_text: Box<str>,
951 pub(crate) new_text: Box<str>,
953 pub(crate) href: String,
955 pub(crate) tooltip: String,
957}
958
959#[derive(Clone, Debug, Default)]
962pub(crate) struct Attributes {
963 pub(crate) doc_strings: Vec<DocFragment>,
964 pub(crate) other_attrs: ThinVec<hir::Attribute>,
965}
966
967impl Attributes {
968 pub(crate) fn has_doc_flag<F: Fn(&DocAttribute) -> bool>(&self, callback: F) -> bool {
969 self.other_attrs
970 .iter()
971 .any(|a| matches!(a, Attribute::Parsed(AttributeKind::Doc(d)) if callback(d)))
972 }
973
974 pub(crate) fn is_doc_hidden(&self) -> bool {
975 find_attr!(&self.other_attrs, AttributeKind::Doc(d) if d.hidden.is_some())
976 }
977
978 pub(crate) fn from_hir(attrs: &[hir::Attribute]) -> Attributes {
979 Attributes::from_hir_iter(attrs.iter().map(|attr| (attr, None)), false)
980 }
981
982 pub(crate) fn from_hir_with_additional(
983 attrs: &[hir::Attribute],
984 (additional_attrs, def_id): (&[hir::Attribute], DefId),
985 ) -> Attributes {
986 let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id)));
988 let attrs2 = attrs.iter().map(|attr| (attr, None));
989 Attributes::from_hir_iter(attrs1.chain(attrs2), false)
990 }
991
992 pub(crate) fn from_hir_iter<'a>(
993 attrs: impl Iterator<Item = (&'a hir::Attribute, Option<DefId>)>,
994 doc_only: bool,
995 ) -> Attributes {
996 let (doc_strings, other_attrs) = attrs_to_doc_fragments(attrs, doc_only);
997 Attributes { doc_strings, other_attrs }
998 }
999
1000 pub(crate) fn doc_value(&self) -> String {
1002 self.opt_doc_value().unwrap_or_default()
1003 }
1004
1005 pub(crate) fn opt_doc_value(&self) -> Option<String> {
1009 (!self.doc_strings.is_empty()).then(|| {
1010 let mut res = String::new();
1011 for frag in &self.doc_strings {
1012 add_doc_fragment(&mut res, frag);
1013 }
1014 res.pop();
1015 res
1016 })
1017 }
1018
1019 pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> {
1020 let mut aliases = FxIndexSet::default();
1021
1022 for attr in &self.other_attrs {
1023 if let Attribute::Parsed(AttributeKind::Doc(d)) = attr {
1024 for (alias, _) in &d.aliases {
1025 aliases.insert(*alias);
1026 }
1027 }
1028 }
1029 aliases.into_iter().collect::<Vec<_>>().into()
1030 }
1031}
1032
1033#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1034pub(crate) enum GenericBound {
1035 TraitBound(PolyTrait, hir::TraitBoundModifiers),
1036 Outlives(Lifetime),
1037 Use(Vec<PreciseCapturingArg>),
1039}
1040
1041impl GenericBound {
1042 pub(crate) fn sized(cx: &mut DocContext<'_>) -> GenericBound {
1043 Self::sized_with(cx, hir::TraitBoundModifiers::NONE)
1044 }
1045
1046 pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1047 Self::sized_with(
1048 cx,
1049 hir::TraitBoundModifiers {
1050 polarity: hir::BoundPolarity::Maybe(DUMMY_SP),
1051 constness: hir::BoundConstness::Never,
1052 },
1053 )
1054 }
1055
1056 fn sized_with(cx: &mut DocContext<'_>, modifiers: hir::TraitBoundModifiers) -> GenericBound {
1057 let did = cx.tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
1058 let empty = ty::Binder::dummy(ty::GenericArgs::empty());
1059 let path = clean_middle_path(cx, did, false, ThinVec::new(), empty);
1060 inline::record_extern_fqn(cx, did, ItemType::Trait);
1061 GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifiers)
1062 }
1063
1064 pub(crate) fn is_trait_bound(&self) -> bool {
1065 matches!(self, Self::TraitBound(..))
1066 }
1067
1068 pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1069 self.is_bounded_by_lang_item(cx, LangItem::Sized)
1070 }
1071
1072 pub(crate) fn is_meta_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1073 self.is_bounded_by_lang_item(cx, LangItem::MetaSized)
1074 }
1075
1076 fn is_bounded_by_lang_item(&self, cx: &DocContext<'_>, lang_item: LangItem) -> bool {
1077 if let GenericBound::TraitBound(
1078 PolyTrait { ref trait_, .. },
1079 rustc_hir::TraitBoundModifiers::NONE,
1080 ) = *self
1081 && cx.tcx.is_lang_item(trait_.def_id(), lang_item)
1082 {
1083 return true;
1084 }
1085 false
1086 }
1087
1088 pub(crate) fn get_trait_path(&self) -> Option<Path> {
1089 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1090 Some(trait_.clone())
1091 } else {
1092 None
1093 }
1094 }
1095}
1096
1097#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1098pub(crate) struct Lifetime(pub Symbol);
1099
1100impl Lifetime {
1101 pub(crate) fn statik() -> Lifetime {
1102 Lifetime(kw::StaticLifetime)
1103 }
1104
1105 pub(crate) fn elided() -> Lifetime {
1106 Lifetime(kw::UnderscoreLifetime)
1107 }
1108}
1109
1110#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1111pub(crate) enum PreciseCapturingArg {
1112 Lifetime(Lifetime),
1113 Param(Symbol),
1114}
1115
1116impl PreciseCapturingArg {
1117 pub(crate) fn name(self) -> Symbol {
1118 match self {
1119 PreciseCapturingArg::Lifetime(lt) => lt.0,
1120 PreciseCapturingArg::Param(param) => param,
1121 }
1122 }
1123}
1124
1125#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1126pub(crate) enum WherePredicate {
1127 BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
1128 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1129 EqPredicate { lhs: QPathData, rhs: Term },
1130}
1131
1132impl WherePredicate {
1133 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1134 match self {
1135 WherePredicate::BoundPredicate { bounds, .. } => Some(bounds),
1136 WherePredicate::RegionPredicate { bounds, .. } => Some(bounds),
1137 _ => None,
1138 }
1139 }
1140}
1141
1142#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1143pub(crate) enum GenericParamDefKind {
1144 Lifetime { outlives: ThinVec<Lifetime> },
1145 Type { bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
1146 Const { ty: Box<Type>, default: Option<Box<String>> },
1148}
1149
1150impl GenericParamDefKind {
1151 pub(crate) fn is_type(&self) -> bool {
1152 matches!(self, GenericParamDefKind::Type { .. })
1153 }
1154}
1155
1156#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1157pub(crate) struct GenericParamDef {
1158 pub(crate) name: Symbol,
1159 pub(crate) def_id: DefId,
1160 pub(crate) kind: GenericParamDefKind,
1161}
1162
1163impl GenericParamDef {
1164 pub(crate) fn lifetime(def_id: DefId, name: Symbol) -> Self {
1165 Self { name, def_id, kind: GenericParamDefKind::Lifetime { outlives: ThinVec::new() } }
1166 }
1167
1168 pub(crate) fn is_synthetic_param(&self) -> bool {
1169 match self.kind {
1170 GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
1171 GenericParamDefKind::Type { synthetic, .. } => synthetic,
1172 }
1173 }
1174
1175 pub(crate) fn is_type(&self) -> bool {
1176 self.kind.is_type()
1177 }
1178
1179 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1180 match self.kind {
1181 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1182 _ => None,
1183 }
1184 }
1185}
1186
1187#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
1189pub(crate) struct Generics {
1190 pub(crate) params: ThinVec<GenericParamDef>,
1191 pub(crate) where_predicates: ThinVec<WherePredicate>,
1192}
1193
1194impl Generics {
1195 pub(crate) fn is_empty(&self) -> bool {
1196 self.params.is_empty() && self.where_predicates.is_empty()
1197 }
1198}
1199
1200#[derive(Clone, Debug)]
1201pub(crate) struct Function {
1202 pub(crate) decl: FnDecl,
1203 pub(crate) generics: Generics,
1204}
1205
1206#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1207pub(crate) struct FnDecl {
1208 pub(crate) inputs: Vec<Parameter>,
1209 pub(crate) output: Type,
1210 pub(crate) c_variadic: bool,
1211}
1212
1213impl FnDecl {
1214 pub(crate) fn receiver_type(&self) -> Option<&Type> {
1215 self.inputs.first().and_then(|v| v.to_receiver())
1216 }
1217}
1218
1219#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1221pub(crate) struct Parameter {
1222 pub(crate) name: Option<Symbol>,
1223 pub(crate) type_: Type,
1224 pub(crate) is_const: bool,
1227}
1228
1229impl Parameter {
1230 pub(crate) fn to_receiver(&self) -> Option<&Type> {
1231 if self.name == Some(kw::SelfLower) { Some(&self.type_) } else { None }
1232 }
1233}
1234
1235#[derive(Clone, Debug)]
1236pub(crate) struct Trait {
1237 pub(crate) def_id: DefId,
1238 pub(crate) items: Vec<Item>,
1239 pub(crate) generics: Generics,
1240 pub(crate) bounds: Vec<GenericBound>,
1241}
1242
1243impl Trait {
1244 pub(crate) fn is_auto(&self, tcx: TyCtxt<'_>) -> bool {
1245 tcx.trait_is_auto(self.def_id)
1246 }
1247 pub(crate) fn is_notable_trait(&self, tcx: TyCtxt<'_>) -> bool {
1248 tcx.is_doc_notable_trait(self.def_id)
1249 }
1250 pub(crate) fn safety(&self, tcx: TyCtxt<'_>) -> hir::Safety {
1251 tcx.trait_def(self.def_id).safety
1252 }
1253 pub(crate) fn is_dyn_compatible(&self, tcx: TyCtxt<'_>) -> bool {
1254 tcx.is_dyn_compatible(self.def_id)
1255 }
1256}
1257
1258#[derive(Clone, Debug)]
1259pub(crate) struct TraitAlias {
1260 pub(crate) generics: Generics,
1261 pub(crate) bounds: Vec<GenericBound>,
1262}
1263
1264#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1266pub(crate) struct PolyTrait {
1267 pub(crate) trait_: Path,
1268 pub(crate) generic_params: Vec<GenericParamDef>,
1269}
1270
1271#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1273pub(crate) enum Type {
1274 Path {
1279 path: Path,
1280 },
1281 DynTrait(Vec<PolyTrait>, Option<Lifetime>),
1283 Generic(Symbol),
1285 SelfTy,
1287 Primitive(PrimitiveType),
1289 BareFunction(Box<BareFunctionDecl>),
1291 Tuple(Vec<Type>),
1293 Slice(Box<Type>),
1295 Array(Box<Type>, Box<str>),
1299 Pat(Box<Type>, Box<str>),
1300 RawPointer(Mutability, Box<Type>),
1302 BorrowedRef {
1304 lifetime: Option<Lifetime>,
1305 mutability: Mutability,
1306 type_: Box<Type>,
1307 },
1308
1309 QPath(Box<QPathData>),
1311
1312 Infer,
1314
1315 ImplTrait(Vec<GenericBound>),
1317
1318 UnsafeBinder(Box<UnsafeBinderTy>),
1319}
1320
1321impl Type {
1322 pub(crate) fn without_borrowed_ref(&self) -> &Type {
1324 let mut result = self;
1325 while let Type::BorrowedRef { type_, .. } = result {
1326 result = type_;
1327 }
1328 result
1329 }
1330
1331 pub(crate) fn is_borrowed_ref(&self) -> bool {
1332 matches!(self, Type::BorrowedRef { .. })
1333 }
1334
1335 fn is_type_alias(&self) -> bool {
1336 matches!(self, Type::Path { path: Path { res: Res::Def(DefKind::TyAlias, _), .. } })
1337 }
1338
1339 pub(crate) fn is_doc_subtype_of(&self, other: &Self, cache: &Cache) -> bool {
1360 let (self_cleared, other_cleared) = if !self.is_borrowed_ref() || !other.is_borrowed_ref() {
1363 (self.without_borrowed_ref(), other.without_borrowed_ref())
1364 } else {
1365 (self, other)
1366 };
1367
1368 if self_cleared.is_type_alias() || other_cleared.is_type_alias() {
1374 return true;
1375 }
1376
1377 match (self_cleared, other_cleared) {
1378 (Type::Tuple(a), Type::Tuple(b)) => {
1380 a.iter().eq_by(b, |a, b| a.is_doc_subtype_of(b, cache))
1381 }
1382 (Type::Slice(a), Type::Slice(b)) => a.is_doc_subtype_of(b, cache),
1383 (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_doc_subtype_of(b, cache),
1384 (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
1385 mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache)
1386 }
1387 (
1388 Type::BorrowedRef { mutability, type_, .. },
1389 Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
1390 ) => mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache),
1391 (Type::Infer, _) | (_, Type::Infer) => true,
1393 (_, Type::Generic(_)) => true,
1396 (Type::Generic(_), _) => false,
1397 (Type::SelfTy, Type::SelfTy) => true,
1399 (Type::Path { path: a }, Type::Path { path: b }) => {
1401 a.def_id() == b.def_id()
1402 && a.generics()
1403 .zip(b.generics())
1404 .map(|(ag, bg)| ag.zip(bg).all(|(at, bt)| at.is_doc_subtype_of(bt, cache)))
1405 .unwrap_or(true)
1406 }
1407 (a, b) => a
1409 .def_id(cache)
1410 .and_then(|a| Some((a, b.def_id(cache)?)))
1411 .map(|(a, b)| a == b)
1412 .unwrap_or(false),
1413 }
1414 }
1415
1416 pub(crate) fn primitive_type(&self) -> Option<PrimitiveType> {
1417 match *self {
1418 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1419 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1420 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1421 Tuple(ref tys) => {
1422 if tys.is_empty() {
1423 Some(PrimitiveType::Unit)
1424 } else {
1425 Some(PrimitiveType::Tuple)
1426 }
1427 }
1428 RawPointer(..) => Some(PrimitiveType::RawPointer),
1429 BareFunction(..) => Some(PrimitiveType::Fn),
1430 _ => None,
1431 }
1432 }
1433
1434 pub(crate) fn sugared_async_return_type(self) -> Type {
1444 if let Type::ImplTrait(mut v) = self
1445 && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = v.pop()
1446 && let Some(segment) = trait_.segments.pop()
1447 && let GenericArgs::AngleBracketed { mut constraints, .. } = segment.args
1448 && let Some(constraint) = constraints.pop()
1449 && let AssocItemConstraintKind::Equality { term } = constraint.kind
1450 && let Term::Type(ty) = term
1451 {
1452 ty
1453 } else {
1454 panic!("unexpected async fn return type")
1455 }
1456 }
1457
1458 pub(crate) fn is_assoc_ty(&self) -> bool {
1460 match self {
1461 Type::Path { path, .. } => path.is_assoc_ty(),
1462 _ => false,
1463 }
1464 }
1465
1466 pub(crate) fn is_self_type(&self) -> bool {
1467 matches!(*self, Type::SelfTy)
1468 }
1469
1470 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
1471 match self {
1472 Type::Path { path, .. } => path.generic_args(),
1473 _ => None,
1474 }
1475 }
1476
1477 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
1478 match self {
1479 Type::Path { path, .. } => path.generics(),
1480 _ => None,
1481 }
1482 }
1483
1484 pub(crate) fn is_full_generic(&self) -> bool {
1485 matches!(self, Type::Generic(_))
1486 }
1487
1488 pub(crate) fn is_unit(&self) -> bool {
1489 matches!(self, Type::Tuple(v) if v.is_empty())
1490 }
1491
1492 pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
1496 let t: PrimitiveType = match self {
1497 Type::Path { path } => return Some(path.def_id()),
1498 DynTrait(bounds, _) => return bounds.first().map(|b| b.trait_.def_id()),
1499 Primitive(p) => return cache.primitive_locations.get(p).cloned(),
1500 BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
1501 BorrowedRef { type_, .. } => return type_.def_id(cache),
1502 Tuple(tys) => {
1503 if tys.is_empty() {
1504 PrimitiveType::Unit
1505 } else {
1506 PrimitiveType::Tuple
1507 }
1508 }
1509 BareFunction(..) => PrimitiveType::Fn,
1510 Slice(..) => PrimitiveType::Slice,
1511 Array(..) => PrimitiveType::Array,
1512 Type::Pat(..) => PrimitiveType::Pat,
1513 RawPointer(..) => PrimitiveType::RawPointer,
1514 QPath(box QPathData { self_type, .. }) => return self_type.def_id(cache),
1515 Generic(_) | SelfTy | Infer | ImplTrait(_) | UnsafeBinder(_) => return None,
1516 };
1517 Primitive(t).def_id(cache)
1518 }
1519}
1520
1521#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1522pub(crate) struct QPathData {
1523 pub assoc: PathSegment,
1524 pub self_type: Type,
1525 pub should_fully_qualify: bool,
1527 pub trait_: Option<Path>,
1528}
1529
1530#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1537pub(crate) enum PrimitiveType {
1538 Isize,
1539 I8,
1540 I16,
1541 I32,
1542 I64,
1543 I128,
1544 Usize,
1545 U8,
1546 U16,
1547 U32,
1548 U64,
1549 U128,
1550 F16,
1551 F32,
1552 F64,
1553 F128,
1554 Char,
1555 Bool,
1556 Str,
1557 Slice,
1558 Array,
1559 Pat,
1560 Tuple,
1561 Unit,
1562 RawPointer,
1563 Reference,
1564 Fn,
1565 Never,
1566}
1567
1568type SimplifiedTypes = FxIndexMap<PrimitiveType, ArrayVec<SimplifiedType, 3>>;
1569impl PrimitiveType {
1570 pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1571 use ast::{FloatTy, IntTy, UintTy};
1572 match prim {
1573 hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1574 hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1575 hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1576 hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1577 hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1578 hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1579 hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1580 hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1581 hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1582 hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1583 hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1584 hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1585 hir::PrimTy::Float(FloatTy::F16) => PrimitiveType::F16,
1586 hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1587 hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1588 hir::PrimTy::Float(FloatTy::F128) => PrimitiveType::F128,
1589 hir::PrimTy::Str => PrimitiveType::Str,
1590 hir::PrimTy::Bool => PrimitiveType::Bool,
1591 hir::PrimTy::Char => PrimitiveType::Char,
1592 }
1593 }
1594
1595 pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1596 match s {
1597 sym::isize => Some(PrimitiveType::Isize),
1598 sym::i8 => Some(PrimitiveType::I8),
1599 sym::i16 => Some(PrimitiveType::I16),
1600 sym::i32 => Some(PrimitiveType::I32),
1601 sym::i64 => Some(PrimitiveType::I64),
1602 sym::i128 => Some(PrimitiveType::I128),
1603 sym::usize => Some(PrimitiveType::Usize),
1604 sym::u8 => Some(PrimitiveType::U8),
1605 sym::u16 => Some(PrimitiveType::U16),
1606 sym::u32 => Some(PrimitiveType::U32),
1607 sym::u64 => Some(PrimitiveType::U64),
1608 sym::u128 => Some(PrimitiveType::U128),
1609 sym::bool => Some(PrimitiveType::Bool),
1610 sym::char => Some(PrimitiveType::Char),
1611 sym::str => Some(PrimitiveType::Str),
1612 sym::f16 => Some(PrimitiveType::F16),
1613 sym::f32 => Some(PrimitiveType::F32),
1614 sym::f64 => Some(PrimitiveType::F64),
1615 sym::f128 => Some(PrimitiveType::F128),
1616 sym::array => Some(PrimitiveType::Array),
1617 sym::slice => Some(PrimitiveType::Slice),
1618 sym::tuple => Some(PrimitiveType::Tuple),
1619 sym::unit => Some(PrimitiveType::Unit),
1620 sym::pointer => Some(PrimitiveType::RawPointer),
1621 sym::reference => Some(PrimitiveType::Reference),
1622 kw::Fn => Some(PrimitiveType::Fn),
1623 sym::never => Some(PrimitiveType::Never),
1624 _ => None,
1625 }
1626 }
1627
1628 pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
1629 use PrimitiveType::*;
1630 use ty::{FloatTy, IntTy, UintTy};
1631 static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
1632
1633 let single = |x| iter::once(x).collect();
1634 CELL.get_or_init(move || {
1635 map! {
1636 Isize => single(SimplifiedType::Int(IntTy::Isize)),
1637 I8 => single(SimplifiedType::Int(IntTy::I8)),
1638 I16 => single(SimplifiedType::Int(IntTy::I16)),
1639 I32 => single(SimplifiedType::Int(IntTy::I32)),
1640 I64 => single(SimplifiedType::Int(IntTy::I64)),
1641 I128 => single(SimplifiedType::Int(IntTy::I128)),
1642 Usize => single(SimplifiedType::Uint(UintTy::Usize)),
1643 U8 => single(SimplifiedType::Uint(UintTy::U8)),
1644 U16 => single(SimplifiedType::Uint(UintTy::U16)),
1645 U32 => single(SimplifiedType::Uint(UintTy::U32)),
1646 U64 => single(SimplifiedType::Uint(UintTy::U64)),
1647 U128 => single(SimplifiedType::Uint(UintTy::U128)),
1648 F16 => single(SimplifiedType::Float(FloatTy::F16)),
1649 F32 => single(SimplifiedType::Float(FloatTy::F32)),
1650 F64 => single(SimplifiedType::Float(FloatTy::F64)),
1651 F128 => single(SimplifiedType::Float(FloatTy::F128)),
1652 Str => single(SimplifiedType::Str),
1653 Bool => single(SimplifiedType::Bool),
1654 Char => single(SimplifiedType::Char),
1655 Array => single(SimplifiedType::Array),
1656 Slice => single(SimplifiedType::Slice),
1657 Tuple => [SimplifiedType::Tuple(1), SimplifiedType::Tuple(2), SimplifiedType::Tuple(3)].into(),
1663 Unit => single(SimplifiedType::Tuple(0)),
1664 RawPointer => [SimplifiedType::Ptr(Mutability::Not), SimplifiedType::Ptr(Mutability::Mut)].into_iter().collect(),
1665 Reference => [SimplifiedType::Ref(Mutability::Not), SimplifiedType::Ref(Mutability::Mut)].into_iter().collect(),
1666 Fn => single(SimplifiedType::Function(1)),
1669 Never => single(SimplifiedType::Never),
1670 }
1671 })
1672 }
1673
1674 pub(crate) fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = DefId> + 'tcx {
1675 Self::simplified_types()
1676 .get(self)
1677 .into_iter()
1678 .flatten()
1679 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1680 .copied()
1681 }
1682
1683 pub(crate) fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> {
1684 Self::simplified_types()
1685 .values()
1686 .flatten()
1687 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1688 .copied()
1689 }
1690
1691 pub(crate) fn as_sym(&self) -> Symbol {
1692 use PrimitiveType::*;
1693 match self {
1694 Isize => sym::isize,
1695 I8 => sym::i8,
1696 I16 => sym::i16,
1697 I32 => sym::i32,
1698 I64 => sym::i64,
1699 I128 => sym::i128,
1700 Usize => sym::usize,
1701 U8 => sym::u8,
1702 U16 => sym::u16,
1703 U32 => sym::u32,
1704 U64 => sym::u64,
1705 U128 => sym::u128,
1706 F16 => sym::f16,
1707 F32 => sym::f32,
1708 F64 => sym::f64,
1709 F128 => sym::f128,
1710 Str => sym::str,
1711 Bool => sym::bool,
1712 Char => sym::char,
1713 Array => sym::array,
1714 Pat => sym::pat,
1715 Slice => sym::slice,
1716 Tuple => sym::tuple,
1717 Unit => sym::unit,
1718 RawPointer => sym::pointer,
1719 Reference => sym::reference,
1720 Fn => kw::Fn,
1721 Never => sym::never,
1722 }
1723 }
1724
1725 pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxIndexMap<PrimitiveType, DefId> {
1737 static PRIMITIVE_LOCATIONS: OnceCell<FxIndexMap<PrimitiveType, DefId>> = OnceCell::new();
1738 PRIMITIVE_LOCATIONS.get_or_init(|| {
1739 let mut primitive_locations = FxIndexMap::default();
1740 for &crate_num in tcx.crates(()) {
1743 let e = ExternalCrate { crate_num };
1744 let crate_name = e.name(tcx);
1745 debug!(?crate_num, ?crate_name);
1746 for (def_id, prim) in e.primitives(tcx) {
1747 if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1749 continue;
1750 }
1751 primitive_locations.insert(prim, def_id);
1752 }
1753 }
1754 let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1755 for (def_id, prim) in local_primitives {
1756 primitive_locations.insert(prim, def_id);
1757 }
1758 primitive_locations
1759 })
1760 }
1761}
1762
1763impl From<ty::IntTy> for PrimitiveType {
1764 fn from(int_ty: ty::IntTy) -> PrimitiveType {
1765 match int_ty {
1766 ty::IntTy::Isize => PrimitiveType::Isize,
1767 ty::IntTy::I8 => PrimitiveType::I8,
1768 ty::IntTy::I16 => PrimitiveType::I16,
1769 ty::IntTy::I32 => PrimitiveType::I32,
1770 ty::IntTy::I64 => PrimitiveType::I64,
1771 ty::IntTy::I128 => PrimitiveType::I128,
1772 }
1773 }
1774}
1775
1776impl From<ty::UintTy> for PrimitiveType {
1777 fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1778 match uint_ty {
1779 ty::UintTy::Usize => PrimitiveType::Usize,
1780 ty::UintTy::U8 => PrimitiveType::U8,
1781 ty::UintTy::U16 => PrimitiveType::U16,
1782 ty::UintTy::U32 => PrimitiveType::U32,
1783 ty::UintTy::U64 => PrimitiveType::U64,
1784 ty::UintTy::U128 => PrimitiveType::U128,
1785 }
1786 }
1787}
1788
1789impl From<ty::FloatTy> for PrimitiveType {
1790 fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1791 match float_ty {
1792 ty::FloatTy::F16 => PrimitiveType::F16,
1793 ty::FloatTy::F32 => PrimitiveType::F32,
1794 ty::FloatTy::F64 => PrimitiveType::F64,
1795 ty::FloatTy::F128 => PrimitiveType::F128,
1796 }
1797 }
1798}
1799
1800impl From<hir::PrimTy> for PrimitiveType {
1801 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1802 match prim_ty {
1803 hir::PrimTy::Int(int_ty) => int_ty.into(),
1804 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1805 hir::PrimTy::Float(float_ty) => float_ty.into(),
1806 hir::PrimTy::Str => PrimitiveType::Str,
1807 hir::PrimTy::Bool => PrimitiveType::Bool,
1808 hir::PrimTy::Char => PrimitiveType::Char,
1809 }
1810 }
1811}
1812
1813#[derive(Clone, Debug)]
1814pub(crate) struct Struct {
1815 pub(crate) ctor_kind: Option<CtorKind>,
1816 pub(crate) generics: Generics,
1817 pub(crate) fields: ThinVec<Item>,
1818}
1819
1820impl Struct {
1821 pub(crate) fn has_stripped_entries(&self) -> bool {
1822 self.fields.iter().any(|f| f.is_stripped())
1823 }
1824}
1825
1826#[derive(Clone, Debug)]
1827pub(crate) struct Union {
1828 pub(crate) generics: Generics,
1829 pub(crate) fields: Vec<Item>,
1830}
1831
1832impl Union {
1833 pub(crate) fn has_stripped_entries(&self) -> bool {
1834 self.fields.iter().any(|f| f.is_stripped())
1835 }
1836}
1837
1838#[derive(Clone, Debug)]
1842pub(crate) struct VariantStruct {
1843 pub(crate) fields: ThinVec<Item>,
1844}
1845
1846impl VariantStruct {
1847 pub(crate) fn has_stripped_entries(&self) -> bool {
1848 self.fields.iter().any(|f| f.is_stripped())
1849 }
1850}
1851
1852#[derive(Clone, Debug)]
1853pub(crate) struct Enum {
1854 pub(crate) variants: IndexVec<VariantIdx, Item>,
1855 pub(crate) generics: Generics,
1856}
1857
1858impl Enum {
1859 pub(crate) fn has_stripped_entries(&self) -> bool {
1860 self.variants.iter().any(|f| f.is_stripped())
1861 }
1862
1863 pub(crate) fn non_stripped_variants(&self) -> impl Iterator<Item = &Item> {
1864 self.variants.iter().filter(|v| !v.is_stripped())
1865 }
1866}
1867
1868#[derive(Clone, Debug)]
1869pub(crate) struct Variant {
1870 pub kind: VariantKind,
1871 pub discriminant: Option<Discriminant>,
1872}
1873
1874#[derive(Clone, Debug)]
1875pub(crate) enum VariantKind {
1876 CLike,
1877 Tuple(ThinVec<Item>),
1878 Struct(VariantStruct),
1879}
1880
1881impl Variant {
1882 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
1883 match &self.kind {
1884 VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()),
1885 VariantKind::CLike | VariantKind::Tuple(_) => None,
1886 }
1887 }
1888}
1889
1890#[derive(Clone, Debug)]
1891pub(crate) struct Discriminant {
1892 pub(super) expr: Option<BodyId>,
1895 pub(super) value: DefId,
1896}
1897
1898impl Discriminant {
1899 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
1902 self.expr
1903 .map(|body| rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body)))
1904 }
1905 pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String {
1906 print_evaluated_const(tcx, self.value, with_underscores, false).unwrap()
1907 }
1908}
1909
1910#[derive(Copy, Clone, Debug)]
1913pub(crate) struct Span(rustc_span::Span);
1914
1915impl Span {
1916 pub(crate) fn new(sp: rustc_span::Span) -> Self {
1921 Self(sp.source_callsite())
1922 }
1923
1924 pub(crate) fn inner(&self) -> rustc_span::Span {
1925 self.0
1926 }
1927
1928 pub(crate) fn filename(&self, sess: &Session) -> FileName {
1929 sess.source_map().span_to_filename(self.0)
1930 }
1931
1932 pub(crate) fn lo(&self, sess: &Session) -> Loc {
1933 sess.source_map().lookup_char_pos(self.0.lo())
1934 }
1935
1936 pub(crate) fn hi(&self, sess: &Session) -> Loc {
1937 sess.source_map().lookup_char_pos(self.0.hi())
1938 }
1939
1940 pub(crate) fn cnum(&self, sess: &Session) -> CrateNum {
1941 self.lo(sess).file.cnum
1943 }
1944}
1945
1946#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1947pub(crate) struct Path {
1948 pub(crate) res: Res,
1949 pub(crate) segments: ThinVec<PathSegment>,
1950}
1951
1952impl Path {
1953 pub(crate) fn def_id(&self) -> DefId {
1954 self.res.def_id()
1955 }
1956
1957 pub(crate) fn last_opt(&self) -> Option<Symbol> {
1958 self.segments.last().map(|s| s.name)
1959 }
1960
1961 pub(crate) fn last(&self) -> Symbol {
1962 self.last_opt().expect("segments were empty")
1963 }
1964
1965 pub(crate) fn whole_name(&self) -> String {
1966 self.segments
1967 .iter()
1968 .map(|s| if s.name == kw::PathRoot { "" } else { s.name.as_str() })
1969 .intersperse("::")
1970 .collect()
1971 }
1972
1973 pub(crate) fn is_assoc_ty(&self) -> bool {
1975 match self.res {
1976 Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _)
1977 if self.segments.len() != 1 =>
1978 {
1979 true
1980 }
1981 Res::Def(DefKind::AssocTy, _) => true,
1982 _ => false,
1983 }
1984 }
1985
1986 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
1987 self.segments.last().map(|seg| &seg.args)
1988 }
1989
1990 pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
1991 self.segments.last().and_then(|seg| {
1992 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
1993 Some(args.iter().filter_map(|arg| match arg {
1994 GenericArg::Type(ty) => Some(ty),
1995 _ => None,
1996 }))
1997 } else {
1998 None
1999 }
2000 })
2001 }
2002}
2003
2004#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2005pub(crate) enum GenericArg {
2006 Lifetime(Lifetime),
2007 Type(Type),
2008 Const(Box<ConstantKind>),
2009 Infer,
2010}
2011
2012impl GenericArg {
2013 pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
2014 if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2015 }
2016
2017 pub(crate) fn as_ty(&self) -> Option<&Type> {
2018 if let Self::Type(ty) = self { Some(ty) } else { None }
2019 }
2020}
2021
2022#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2023pub(crate) enum GenericArgs {
2024 AngleBracketed { args: ThinVec<GenericArg>, constraints: ThinVec<AssocItemConstraint> },
2026 Parenthesized { inputs: ThinVec<Type>, output: Option<Box<Type>> },
2028 ReturnTypeNotation,
2030}
2031
2032impl GenericArgs {
2033 pub(crate) fn is_empty(&self) -> bool {
2034 match self {
2035 GenericArgs::AngleBracketed { args, constraints } => {
2036 args.is_empty() && constraints.is_empty()
2037 }
2038 GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
2039 GenericArgs::ReturnTypeNotation => false,
2040 }
2041 }
2042 pub(crate) fn constraints(&self) -> Box<dyn Iterator<Item = AssocItemConstraint> + '_> {
2043 match self {
2044 GenericArgs::AngleBracketed { constraints, .. } => {
2045 Box::new(constraints.iter().cloned())
2046 }
2047 GenericArgs::Parenthesized { output, .. } => Box::new(
2048 output
2049 .as_ref()
2050 .map(|ty| AssocItemConstraint {
2051 assoc: PathSegment {
2052 name: sym::Output,
2053 args: GenericArgs::AngleBracketed {
2054 args: ThinVec::new(),
2055 constraints: ThinVec::new(),
2056 },
2057 },
2058 kind: AssocItemConstraintKind::Equality {
2059 term: Term::Type((**ty).clone()),
2060 },
2061 })
2062 .into_iter(),
2063 ),
2064 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2065 }
2066 }
2067}
2068
2069impl<'a> IntoIterator for &'a GenericArgs {
2070 type IntoIter = Box<dyn Iterator<Item = GenericArg> + 'a>;
2071 type Item = GenericArg;
2072 fn into_iter(self) -> Self::IntoIter {
2073 match self {
2074 GenericArgs::AngleBracketed { args, .. } => Box::new(args.iter().cloned()),
2075 GenericArgs::Parenthesized { inputs, .. } => {
2076 Box::new(inputs.iter().cloned().map(GenericArg::Type))
2078 }
2079 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2080 }
2081 }
2082}
2083
2084#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2085pub(crate) struct PathSegment {
2086 pub(crate) name: Symbol,
2087 pub(crate) args: GenericArgs,
2088}
2089
2090#[derive(Clone, Debug)]
2091pub(crate) enum TypeAliasInnerType {
2092 Enum { variants: IndexVec<VariantIdx, Item>, is_non_exhaustive: bool },
2093 Union { fields: Vec<Item> },
2094 Struct { ctor_kind: Option<CtorKind>, fields: Vec<Item> },
2095}
2096
2097impl TypeAliasInnerType {
2098 fn has_stripped_entries(&self) -> Option<bool> {
2099 Some(match self {
2100 Self::Enum { variants, .. } => variants.iter().any(|v| v.is_stripped()),
2101 Self::Union { fields } | Self::Struct { fields, .. } => {
2102 fields.iter().any(|f| f.is_stripped())
2103 }
2104 })
2105 }
2106}
2107
2108#[derive(Clone, Debug)]
2109pub(crate) struct TypeAlias {
2110 pub(crate) type_: Type,
2111 pub(crate) generics: Generics,
2112 pub(crate) inner_type: Option<TypeAliasInnerType>,
2115 pub(crate) item_type: Option<Type>,
2122}
2123
2124#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2125pub(crate) struct BareFunctionDecl {
2126 pub(crate) safety: hir::Safety,
2127 pub(crate) generic_params: Vec<GenericParamDef>,
2128 pub(crate) decl: FnDecl,
2129 pub(crate) abi: ExternAbi,
2130}
2131
2132#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2133pub(crate) struct UnsafeBinderTy {
2134 pub(crate) generic_params: Vec<GenericParamDef>,
2135 pub(crate) ty: Type,
2136}
2137
2138#[derive(Clone, Debug)]
2139pub(crate) struct Static {
2140 pub(crate) type_: Box<Type>,
2141 pub(crate) mutability: Mutability,
2142 pub(crate) expr: Option<BodyId>,
2143}
2144
2145#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2146pub(crate) struct Constant {
2147 pub(crate) generics: Generics,
2148 pub(crate) kind: ConstantKind,
2149 pub(crate) type_: Type,
2150}
2151
2152#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2153pub(crate) enum Term {
2154 Type(Type),
2155 Constant(ConstantKind),
2156}
2157
2158impl Term {
2159 pub(crate) fn ty(&self) -> Option<&Type> {
2160 if let Term::Type(ty) = self { Some(ty) } else { None }
2161 }
2162}
2163
2164impl From<Type> for Term {
2165 fn from(ty: Type) -> Self {
2166 Term::Type(ty)
2167 }
2168}
2169
2170#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2171pub(crate) enum ConstantKind {
2172 TyConst { expr: Box<str> },
2178 Path { path: Box<str> },
2181 Anonymous { body: BodyId },
2185 Extern { def_id: DefId },
2187 Local { def_id: DefId, body: BodyId },
2189 Infer,
2191}
2192
2193impl ConstantKind {
2194 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2195 match *self {
2196 ConstantKind::TyConst { ref expr } => expr.to_string(),
2197 ConstantKind::Path { ref path } => path.to_string(),
2198 ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2199 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2200 rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body))
2201 }
2202 ConstantKind::Infer => "_".to_string(),
2203 }
2204 }
2205
2206 pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2207 match *self {
2208 ConstantKind::TyConst { .. }
2209 | ConstantKind::Path { .. }
2210 | ConstantKind::Anonymous { .. }
2211 | ConstantKind::Infer => None,
2212 ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2213 print_evaluated_const(tcx, def_id, true, true)
2214 }
2215 }
2216 }
2217
2218 pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2219 match *self {
2220 ConstantKind::TyConst { .. }
2221 | ConstantKind::Extern { .. }
2222 | ConstantKind::Path { .. }
2223 | ConstantKind::Infer => false,
2224 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2225 is_literal_expr(tcx, body.hir_id)
2226 }
2227 }
2228 }
2229}
2230
2231#[derive(Clone, Debug)]
2232pub(crate) struct Impl {
2233 pub(crate) safety: hir::Safety,
2234 pub(crate) generics: Generics,
2235 pub(crate) trait_: Option<Path>,
2236 pub(crate) for_: Type,
2237 pub(crate) items: Vec<Item>,
2238 pub(crate) polarity: ty::ImplPolarity,
2239 pub(crate) kind: ImplKind,
2240}
2241
2242impl Impl {
2243 pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxIndexSet<Symbol> {
2244 self.trait_
2245 .as_ref()
2246 .map(|t| t.def_id())
2247 .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name()).collect())
2248 .unwrap_or_default()
2249 }
2250
2251 pub(crate) fn is_negative_trait_impl(&self) -> bool {
2252 matches!(self.polarity, ty::ImplPolarity::Negative)
2253 }
2254}
2255
2256#[derive(Clone, Debug)]
2257pub(crate) enum ImplKind {
2258 Normal,
2259 Auto,
2260 FakeVariadic,
2261 Blanket(Box<Type>),
2262}
2263
2264impl ImplKind {
2265 pub(crate) fn is_auto(&self) -> bool {
2266 matches!(self, ImplKind::Auto)
2267 }
2268
2269 pub(crate) fn is_blanket(&self) -> bool {
2270 matches!(self, ImplKind::Blanket(_))
2271 }
2272
2273 pub(crate) fn is_fake_variadic(&self) -> bool {
2274 matches!(self, ImplKind::FakeVariadic)
2275 }
2276
2277 pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
2278 match self {
2279 ImplKind::Blanket(ty) => Some(ty),
2280 _ => None,
2281 }
2282 }
2283}
2284
2285#[derive(Clone, Debug)]
2286pub(crate) struct Import {
2287 pub(crate) kind: ImportKind,
2288 pub(crate) source: ImportSource,
2290 pub(crate) should_be_displayed: bool,
2291}
2292
2293impl Import {
2294 pub(crate) fn new_simple(
2295 name: Symbol,
2296 source: ImportSource,
2297 should_be_displayed: bool,
2298 ) -> Self {
2299 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2300 }
2301
2302 pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2303 Self { kind: ImportKind::Glob, source, should_be_displayed }
2304 }
2305
2306 pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool {
2307 self.source.did.is_some_and(|did| tcx.is_doc_hidden(did))
2308 }
2309}
2310
2311#[derive(Clone, Debug)]
2312pub(crate) enum ImportKind {
2313 Simple(Symbol),
2315 Glob,
2317}
2318
2319#[derive(Clone, Debug)]
2320pub(crate) struct ImportSource {
2321 pub(crate) path: Path,
2322 pub(crate) did: Option<DefId>,
2323}
2324
2325#[derive(Clone, Debug)]
2326pub(crate) struct Macro {
2327 pub(crate) source: String,
2328 pub(crate) macro_rules: bool,
2330}
2331
2332#[derive(Clone, Debug)]
2333pub(crate) struct ProcMacro {
2334 pub(crate) kind: MacroKind,
2335 pub(crate) helpers: Vec<Symbol>,
2336}
2337
2338#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2349pub(crate) struct AssocItemConstraint {
2350 pub(crate) assoc: PathSegment,
2351 pub(crate) kind: AssocItemConstraintKind,
2352}
2353
2354#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2356pub(crate) enum AssocItemConstraintKind {
2357 Equality { term: Term },
2358 Bound { bounds: Vec<GenericBound> },
2359}
2360
2361#[cfg(target_pointer_width = "64")]
2363mod size_asserts {
2364 use rustc_data_structures::static_assert_size;
2365
2366 use super::*;
2367 static_assert_size!(Crate, 16); static_assert_size!(DocFragment, 48);
2370 static_assert_size!(GenericArg, 32);
2371 static_assert_size!(GenericArgs, 24);
2372 static_assert_size!(GenericParamDef, 40);
2373 static_assert_size!(Generics, 16);
2374 static_assert_size!(Item, 8);
2375 static_assert_size!(ItemInner, 144);
2376 static_assert_size!(ItemKind, 48);
2377 static_assert_size!(PathSegment, 32);
2378 static_assert_size!(Type, 32);
2379 }