1use std::hash::Hash;
2use std::path::PathBuf;
3use std::sync::{Arc, OnceLock as OnceCell};
4use std::{fmt, iter};
5
6use arrayvec::ArrayVec;
7use rustc_abi::{ExternAbi, VariantIdx};
8use rustc_attr_parsing::{AttributeKind, ConstStability, Deprecation, Stability, StableSince};
9use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
10use rustc_hir::def::{CtorKind, DefKind, Res};
11use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
12use rustc_hir::lang_items::LangItem;
13use rustc_hir::{BodyId, Mutability};
14use rustc_index::IndexVec;
15use rustc_metadata::rendered_const;
16use rustc_middle::span_bug;
17use rustc_middle::ty::fast_reject::SimplifiedType;
18use rustc_middle::ty::{self, TyCtxt, Visibility};
19use rustc_resolve::rustdoc::{
20 DocFragment, add_doc_fragment, attrs_to_doc_fragments, inner_docs, span_of_fragments,
21};
22use rustc_session::Session;
23use rustc_span::hygiene::MacroKind;
24use rustc_span::symbol::{Ident, Symbol, kw, sym};
25use rustc_span::{DUMMY_SP, FileName, Loc};
26use thin_vec::ThinVec;
27use tracing::{debug, trace};
28use {rustc_ast as ast, rustc_hir as hir};
29
30pub(crate) use self::ItemKind::*;
31pub(crate) use self::Type::{
32 Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath,
33 RawPointer, SelfTy, Slice, Tuple, UnsafeBinder,
34};
35use crate::clean::cfg::Cfg;
36use crate::clean::clean_middle_path;
37use crate::clean::inline::{self, print_inlined_const};
38use crate::clean::utils::{is_literal_expr, print_evaluated_const};
39use crate::core::DocContext;
40use crate::formats::cache::Cache;
41use crate::formats::item_type::ItemType;
42use crate::html::render::Context;
43use crate::passes::collect_intra_doc_links::UrlFragment;
44
45#[cfg(test)]
46mod tests;
47
48pub(crate) type ItemIdSet = FxHashSet<ItemId>;
49
50#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
51pub(crate) enum ItemId {
52 DefId(DefId),
54 Auto { trait_: DefId, for_: DefId },
56 Blanket { impl_id: DefId, for_: DefId },
58}
59
60impl ItemId {
61 #[inline]
62 pub(crate) fn is_local(self) -> bool {
63 match self {
64 ItemId::Auto { for_: id, .. }
65 | ItemId::Blanket { for_: id, .. }
66 | ItemId::DefId(id) => id.is_local(),
67 }
68 }
69
70 #[inline]
71 #[track_caller]
72 pub(crate) fn expect_def_id(self) -> DefId {
73 self.as_def_id()
74 .unwrap_or_else(|| panic!("ItemId::expect_def_id: `{self:?}` isn't a DefId"))
75 }
76
77 #[inline]
78 pub(crate) fn as_def_id(self) -> Option<DefId> {
79 match self {
80 ItemId::DefId(id) => Some(id),
81 _ => None,
82 }
83 }
84
85 #[inline]
86 pub(crate) fn as_local_def_id(self) -> Option<LocalDefId> {
87 self.as_def_id().and_then(|id| id.as_local())
88 }
89
90 #[inline]
91 pub(crate) fn krate(self) -> CrateNum {
92 match self {
93 ItemId::Auto { for_: id, .. }
94 | ItemId::Blanket { for_: id, .. }
95 | ItemId::DefId(id) => id.krate,
96 }
97 }
98}
99
100impl From<DefId> for ItemId {
101 fn from(id: DefId) -> Self {
102 Self::DefId(id)
103 }
104}
105
106#[derive(Clone, Debug)]
108pub(crate) struct Crate {
109 pub(crate) module: Item,
110 pub(crate) external_traits: Box<FxIndexMap<DefId, Trait>>,
112}
113
114impl Crate {
115 pub(crate) fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
116 ExternalCrate::LOCAL.name(tcx)
117 }
118
119 pub(crate) fn src(&self, tcx: TyCtxt<'_>) -> FileName {
120 ExternalCrate::LOCAL.src(tcx)
121 }
122}
123
124#[derive(Copy, Clone, Debug)]
125pub(crate) struct ExternalCrate {
126 pub(crate) crate_num: CrateNum,
127}
128
129impl ExternalCrate {
130 const LOCAL: Self = Self { crate_num: LOCAL_CRATE };
131
132 #[inline]
133 pub(crate) fn def_id(&self) -> DefId {
134 self.crate_num.as_def_id()
135 }
136
137 pub(crate) fn src(&self, tcx: TyCtxt<'_>) -> FileName {
138 let krate_span = tcx.def_span(self.def_id());
139 tcx.sess.source_map().span_to_filename(krate_span)
140 }
141
142 pub(crate) fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
143 tcx.crate_name(self.crate_num)
144 }
145
146 pub(crate) fn src_root(&self, tcx: TyCtxt<'_>) -> PathBuf {
147 match self.src(tcx) {
148 FileName::Real(ref p) => match p.local_path_if_available().parent() {
149 Some(p) => p.to_path_buf(),
150 None => PathBuf::new(),
151 },
152 _ => PathBuf::new(),
153 }
154 }
155
156 pub(crate) fn location(
159 &self,
160 extern_url: Option<&str>,
161 extern_url_takes_precedence: bool,
162 dst: &std::path::Path,
163 tcx: TyCtxt<'_>,
164 ) -> ExternalLocation {
165 use ExternalLocation::*;
166
167 fn to_remote(url: impl ToString) -> ExternalLocation {
168 let mut url = url.to_string();
169 if !url.ends_with('/') {
170 url.push('/');
171 }
172 Remote(url)
173 }
174
175 let local_location = dst.join(self.name(tcx).as_str());
179 if local_location.is_dir() {
180 return Local;
181 }
182
183 if extern_url_takes_precedence && let Some(url) = extern_url {
184 return to_remote(url);
185 }
186
187 let did = self.crate_num.as_def_id();
190 tcx.get_attrs(did, sym::doc)
191 .flat_map(|attr| attr.meta_item_list().unwrap_or_default())
192 .filter(|a| a.has_name(sym::html_root_url))
193 .filter_map(|a| a.value_str())
194 .map(to_remote)
195 .next()
196 .or_else(|| extern_url.map(to_remote)) .unwrap_or(Unknown) }
199
200 pub(crate) fn keywords(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, Symbol)> {
201 let root = self.def_id();
202
203 let as_keyword = |res: Res<!>| {
204 if let Res::Def(DefKind::Mod, def_id) = res {
205 let mut keyword = None;
206 let meta_items = tcx
207 .get_attrs(def_id, sym::doc)
208 .flat_map(|attr| attr.meta_item_list().unwrap_or_default());
209 for meta in meta_items {
210 if meta.has_name(sym::keyword)
211 && let Some(v) = meta.value_str()
212 {
213 keyword = Some(v);
214 break;
215 }
216 }
217 return keyword.map(|p| (def_id, p));
218 }
219 None
220 };
221 if root.is_local() {
222 tcx.hir_root_module()
223 .item_ids
224 .iter()
225 .filter_map(|&id| {
226 let item = tcx.hir_item(id);
227 match item.kind {
228 hir::ItemKind::Mod(..) => {
229 as_keyword(Res::Def(DefKind::Mod, id.owner_id.to_def_id()))
230 }
231 _ => None,
232 }
233 })
234 .collect()
235 } else {
236 tcx.module_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect()
237 }
238 }
239
240 pub(crate) fn primitives(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, PrimitiveType)> {
241 let root = self.def_id();
242
243 let as_primitive = |res: Res<!>| {
261 let Res::Def(DefKind::Mod, def_id) = res else { return None };
262 tcx.get_attrs(def_id, sym::rustc_doc_primitive)
263 .map(|attr| {
264 let attr_value = attr.value_str().expect("syntax should already be validated");
265 let Some(prim) = PrimitiveType::from_symbol(attr_value) else {
266 span_bug!(
267 attr.span(),
268 "primitive `{attr_value}` is not a member of `PrimitiveType`"
269 );
270 };
271
272 (def_id, prim)
273 })
274 .next()
275 };
276
277 if root.is_local() {
278 tcx.hir_root_module()
279 .item_ids
280 .iter()
281 .filter_map(|&id| {
282 let item = tcx.hir_item(id);
283 match item.kind {
284 hir::ItemKind::Mod(..) => {
285 as_primitive(Res::Def(DefKind::Mod, id.owner_id.to_def_id()))
286 }
287 _ => None,
288 }
289 })
290 .collect()
291 } else {
292 tcx.module_children(root).iter().map(|item| item.res).filter_map(as_primitive).collect()
293 }
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_attr_parsing::StabilityLevel::Stable {
407 allowed_through_unstable_modules: Some(note),
408 ..
409 } = stab.level
410 {
411 Some(Deprecation {
412 since: rustc_attr_parsing::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
424 .as_def_id()
425 .map(|did| inner_docs(tcx.get_attrs_unchecked(did)))
426 .unwrap_or(false)
427 }
428
429 pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option<Span> {
430 let kind = match &self.kind {
431 ItemKind::StrippedItem(k) => k,
432 _ => &self.kind,
433 };
434 match kind {
435 ItemKind::ModuleItem(Module { span, .. }) => Some(*span),
436 ItemKind::ImplItem(box Impl { kind: ImplKind::Auto, .. }) => None,
437 ItemKind::ImplItem(box Impl { kind: ImplKind::Blanket(_), .. }) => {
438 if let ItemId::Blanket { impl_id, .. } = self.item_id {
439 Some(rustc_span(impl_id, tcx))
440 } else {
441 panic!("blanket impl item has non-blanket ID")
442 }
443 }
444 _ => self.def_id().map(|did| rustc_span(did, tcx)),
445 }
446 }
447
448 pub(crate) fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
449 span_of_fragments(&self.attrs.doc_strings)
450 .unwrap_or_else(|| self.span(tcx).map_or(DUMMY_SP, |span| span.inner()))
451 }
452
453 pub(crate) fn doc_value(&self) -> String {
455 self.attrs.doc_value()
456 }
457
458 pub(crate) fn opt_doc_value(&self) -> Option<String> {
462 self.attrs.opt_doc_value()
463 }
464
465 pub(crate) fn from_def_id_and_parts(
466 def_id: DefId,
467 name: Option<Symbol>,
468 kind: ItemKind,
469 cx: &mut DocContext<'_>,
470 ) -> Item {
471 let hir_attrs = cx.tcx.get_attrs_unchecked(def_id);
472
473 Self::from_def_id_and_attrs_and_parts(
474 def_id,
475 name,
476 kind,
477 Attributes::from_hir(hir_attrs),
478 extract_cfg_from_attrs(hir_attrs.iter(), cx.tcx, &cx.cache.hidden_cfg),
479 )
480 }
481
482 pub(crate) fn from_def_id_and_attrs_and_parts(
483 def_id: DefId,
484 name: Option<Symbol>,
485 kind: ItemKind,
486 attrs: Attributes,
487 cfg: Option<Arc<Cfg>>,
488 ) -> Item {
489 trace!("name={name:?}, def_id={def_id:?} cfg={cfg:?}");
490
491 Item {
492 inner: Box::new(ItemInner {
493 item_id: def_id.into(),
494 kind,
495 attrs,
496 stability: None,
497 name,
498 cfg,
499 inline_stmt_id: None,
500 }),
501 }
502 }
503
504 pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
505 use crate::html::format::{href, link_tooltip};
506
507 let Some(links) = cx.cache().intra_doc_links.get(&self.item_id) else { return vec![] };
508 links
509 .iter()
510 .filter_map(|ItemLink { link: s, link_text, page_id: id, fragment }| {
511 debug!(?id);
512 if let Ok((mut href, ..)) = href(*id, cx) {
513 debug!(?href);
514 if let Some(ref fragment) = *fragment {
515 fragment.render(&mut href, cx.tcx())
516 }
517 Some(RenderedLink {
518 original_text: s.clone(),
519 new_text: link_text.clone(),
520 tooltip: link_tooltip(*id, fragment, cx),
521 href,
522 })
523 } else {
524 None
525 }
526 })
527 .collect()
528 }
529
530 pub(crate) fn link_names(&self, cache: &Cache) -> Vec<RenderedLink> {
536 let Some(links) = cache.intra_doc_links.get(&self.item_id) else {
537 return vec![];
538 };
539 links
540 .iter()
541 .map(|ItemLink { link: s, link_text, .. }| RenderedLink {
542 original_text: s.clone(),
543 new_text: link_text.clone(),
544 href: String::new(),
545 tooltip: String::new(),
546 })
547 .collect()
548 }
549
550 pub(crate) fn is_crate(&self) -> bool {
551 self.is_mod() && self.def_id().is_some_and(|did| did.is_crate_root())
552 }
553 pub(crate) fn is_mod(&self) -> bool {
554 self.type_() == ItemType::Module
555 }
556 pub(crate) fn is_struct(&self) -> bool {
557 self.type_() == ItemType::Struct
558 }
559 pub(crate) fn is_enum(&self) -> bool {
560 self.type_() == ItemType::Enum
561 }
562 pub(crate) fn is_variant(&self) -> bool {
563 self.type_() == ItemType::Variant
564 }
565 pub(crate) fn is_associated_type(&self) -> bool {
566 matches!(self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..)))
567 }
568 pub(crate) fn is_required_associated_type(&self) -> bool {
569 matches!(self.kind, RequiredAssocTypeItem(..) | StrippedItem(box RequiredAssocTypeItem(..)))
570 }
571 pub(crate) fn is_associated_const(&self) -> bool {
572 matches!(self.kind, ProvidedAssocConstItem(..) | ImplAssocConstItem(..) | StrippedItem(box (ProvidedAssocConstItem(..) | ImplAssocConstItem(..))))
573 }
574 pub(crate) fn is_required_associated_const(&self) -> bool {
575 matches!(self.kind, RequiredAssocConstItem(..) | StrippedItem(box RequiredAssocConstItem(..)))
576 }
577 pub(crate) fn is_method(&self) -> bool {
578 self.type_() == ItemType::Method
579 }
580 pub(crate) fn is_ty_method(&self) -> bool {
581 self.type_() == ItemType::TyMethod
582 }
583 pub(crate) fn is_primitive(&self) -> bool {
584 self.type_() == ItemType::Primitive
585 }
586 pub(crate) fn is_union(&self) -> bool {
587 self.type_() == ItemType::Union
588 }
589 pub(crate) fn is_import(&self) -> bool {
590 self.type_() == ItemType::Import
591 }
592 pub(crate) fn is_extern_crate(&self) -> bool {
593 self.type_() == ItemType::ExternCrate
594 }
595 pub(crate) fn is_keyword(&self) -> bool {
596 self.type_() == ItemType::Keyword
597 }
598 pub(crate) fn is_stripped(&self) -> bool {
599 match self.kind {
600 StrippedItem(..) => true,
601 ImportItem(ref i) => !i.should_be_displayed,
602 _ => false,
603 }
604 }
605 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
606 match self.kind {
607 StructItem(ref struct_) => Some(struct_.has_stripped_entries()),
608 UnionItem(ref union_) => Some(union_.has_stripped_entries()),
609 EnumItem(ref enum_) => Some(enum_.has_stripped_entries()),
610 VariantItem(ref v) => v.has_stripped_entries(),
611 _ => None,
612 }
613 }
614
615 pub(crate) fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
616 self.stability(tcx).as_ref().and_then(|s| {
617 let mut classes = Vec::with_capacity(2);
618
619 if s.is_unstable() {
620 classes.push("unstable");
621 }
622
623 if self.deprecation(tcx).is_some() {
625 classes.push("deprecated");
626 }
627
628 if !classes.is_empty() { Some(classes.join(" ")) } else { None }
629 })
630 }
631
632 pub(crate) fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<StableSince> {
633 self.stability(tcx).and_then(|stability| stability.stable_since())
634 }
635
636 pub(crate) fn is_non_exhaustive(&self) -> bool {
637 self.attrs.other_attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
638 }
639
640 pub(crate) fn type_(&self) -> ItemType {
642 ItemType::from(self)
643 }
644
645 pub(crate) fn is_default(&self) -> bool {
646 match self.kind {
647 ItemKind::MethodItem(_, Some(defaultness)) => {
648 defaultness.has_value() && !defaultness.is_final()
649 }
650 _ => false,
651 }
652 }
653
654 pub(crate) fn fn_header(&self, tcx: TyCtxt<'_>) -> Option<hir::FnHeader> {
656 fn build_fn_header(
657 def_id: DefId,
658 tcx: TyCtxt<'_>,
659 asyncness: ty::Asyncness,
660 ) -> hir::FnHeader {
661 let sig = tcx.fn_sig(def_id).skip_binder();
662 let constness = if tcx.is_const_fn(def_id) {
663 hir::Constness::Const
664 } else {
665 hir::Constness::NotConst
666 };
667 let asyncness = match asyncness {
668 ty::Asyncness::Yes => hir::IsAsync::Async(DUMMY_SP),
669 ty::Asyncness::No => hir::IsAsync::NotAsync,
670 };
671 hir::FnHeader {
672 safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
673 hir::HeaderSafety::SafeTargetFeatures
674 } else {
675 sig.safety().into()
676 },
677 abi: sig.abi(),
678 constness,
679 asyncness,
680 }
681 }
682 let header = match self.kind {
683 ItemKind::ForeignFunctionItem(_, safety) => {
684 let def_id = self.def_id().unwrap();
685 let abi = tcx.fn_sig(def_id).skip_binder().abi();
686 hir::FnHeader {
687 safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
688 hir::HeaderSafety::SafeTargetFeatures
689 } else {
690 safety.into()
691 },
692 abi,
693 constness: if tcx.is_const_fn(def_id) {
694 hir::Constness::Const
695 } else {
696 hir::Constness::NotConst
697 },
698 asyncness: hir::IsAsync::NotAsync,
699 }
700 }
701 ItemKind::FunctionItem(_)
702 | ItemKind::MethodItem(_, _)
703 | ItemKind::RequiredMethodItem(_) => {
704 let def_id = self.def_id().unwrap();
705 build_fn_header(def_id, tcx, tcx.asyncness(def_id))
706 }
707 _ => return None,
708 };
709 Some(header)
710 }
711
712 pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option<Visibility<DefId>> {
715 let def_id = match self.item_id {
716 ItemId::Auto { .. } | ItemId::Blanket { .. } => return None,
718 ItemId::DefId(def_id) => def_id,
719 };
720
721 match self.kind {
722 ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) => return Some(Visibility::Public),
726 StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => {
728 return None;
729 }
730 VariantItem(..) | ImplItem(..) => return None,
732 RequiredAssocConstItem(..)
734 | ProvidedAssocConstItem(..)
735 | ImplAssocConstItem(..)
736 | AssocTypeItem(..)
737 | RequiredAssocTypeItem(..)
738 | RequiredMethodItem(..)
739 | MethodItem(..) => {
740 let assoc_item = tcx.associated_item(def_id);
741 let is_trait_item = match assoc_item.container {
742 ty::AssocItemContainer::Trait => true,
743 ty::AssocItemContainer::Impl => {
744 tcx.impl_trait_ref(tcx.parent(assoc_item.def_id)).is_some()
747 }
748 };
749 if is_trait_item {
750 return None;
751 }
752 }
753 _ => {}
754 }
755 let def_id = match self.inline_stmt_id {
756 Some(inlined) => inlined.to_def_id(),
757 None => def_id,
758 };
759 Some(tcx.visibility(def_id))
760 }
761
762 pub(crate) fn attributes(&self, tcx: TyCtxt<'_>, cache: &Cache, is_json: bool) -> Vec<String> {
763 const ALLOWED_ATTRIBUTES: &[Symbol] =
764 &[sym::export_name, sym::link_section, sym::no_mangle, sym::non_exhaustive];
765
766 use rustc_abi::IntegerType;
767
768 let mut attrs: Vec<String> = self
769 .attrs
770 .other_attrs
771 .iter()
772 .filter_map(|attr| {
773 if is_json {
774 match attr {
775 hir::Attribute::Parsed(AttributeKind::Deprecation { .. }) => {
776 None
779 }
780 rustc_hir::Attribute::Parsed(rustc_attr_parsing::AttributeKind::Repr(
781 ..,
782 )) => {
783 None
788 }
789 _ => Some(rustc_hir_pretty::attribute_to_string(&tcx, attr)),
790 }
791 } else if ALLOWED_ATTRIBUTES.contains(&attr.name_or_empty()) {
792 Some(
793 rustc_hir_pretty::attribute_to_string(&tcx, attr)
794 .replace("\\\n", "")
795 .replace('\n', "")
796 .replace(" ", " "),
797 )
798 } else {
799 None
800 }
801 })
802 .collect();
803
804 if let Some(def_id) = self.def_id()
806 && let ItemType::Struct | ItemType::Enum | ItemType::Union = self.type_()
807 {
808 let adt = tcx.adt_def(def_id);
809 let repr = adt.repr();
810 let mut out = Vec::new();
811 if repr.c() {
812 out.push("C");
813 }
814 if repr.transparent() {
815 let render_transparent = cache.document_private
818 || adt
819 .all_fields()
820 .find(|field| {
821 let ty =
822 field.ty(tcx, ty::GenericArgs::identity_for_item(tcx, field.did));
823 tcx.layout_of(
824 ty::TypingEnv::post_analysis(tcx, field.did).as_query_input(ty),
825 )
826 .is_ok_and(|layout| !layout.is_1zst())
827 })
828 .map_or_else(
829 || adt.all_fields().any(|field| field.vis.is_public()),
830 |field| field.vis.is_public(),
831 );
832
833 if render_transparent {
834 out.push("transparent");
835 }
836 }
837 if repr.simd() {
838 out.push("simd");
839 }
840 let pack_s;
841 if let Some(pack) = repr.pack {
842 pack_s = format!("packed({})", pack.bytes());
843 out.push(&pack_s);
844 }
845 let align_s;
846 if let Some(align) = repr.align {
847 align_s = format!("align({})", align.bytes());
848 out.push(&align_s);
849 }
850 let int_s;
851 if let Some(int) = repr.int {
852 int_s = match int {
853 IntegerType::Pointer(is_signed) => {
854 format!("{}size", if is_signed { 'i' } else { 'u' })
855 }
856 IntegerType::Fixed(size, is_signed) => {
857 format!("{}{}", if is_signed { 'i' } else { 'u' }, size.size().bytes() * 8)
858 }
859 };
860 out.push(&int_s);
861 }
862 if !out.is_empty() {
863 attrs.push(format!("#[repr({})]", out.join(", ")));
864 }
865 }
866 attrs
867 }
868
869 pub fn is_doc_hidden(&self) -> bool {
870 self.attrs.is_doc_hidden()
871 }
872
873 pub fn def_id(&self) -> Option<DefId> {
874 self.item_id.as_def_id()
875 }
876}
877
878#[derive(Clone, Debug)]
879pub(crate) enum ItemKind {
880 ExternCrateItem {
881 src: Option<Symbol>,
883 },
884 ImportItem(Import),
885 StructItem(Struct),
886 UnionItem(Union),
887 EnumItem(Enum),
888 FunctionItem(Box<Function>),
889 ModuleItem(Module),
890 TypeAliasItem(Box<TypeAlias>),
891 StaticItem(Static),
892 TraitItem(Box<Trait>),
893 TraitAliasItem(TraitAlias),
894 ImplItem(Box<Impl>),
895 RequiredMethodItem(Box<Function>),
897 MethodItem(Box<Function>, Option<hir::Defaultness>),
901 StructFieldItem(Type),
902 VariantItem(Variant),
903 ForeignFunctionItem(Box<Function>, hir::Safety),
905 ForeignStaticItem(Static, hir::Safety),
907 ForeignTypeItem,
909 MacroItem(Macro),
910 ProcMacroItem(ProcMacro),
911 PrimitiveItem(PrimitiveType),
912 RequiredAssocConstItem(Generics, Box<Type>),
914 ConstantItem(Box<Constant>),
915 ProvidedAssocConstItem(Box<Constant>),
917 ImplAssocConstItem(Box<Constant>),
919 RequiredAssocTypeItem(Generics, Vec<GenericBound>),
923 AssocTypeItem(Box<TypeAlias>, Vec<GenericBound>),
925 StrippedItem(Box<ItemKind>),
927 KeywordItem,
928}
929
930impl ItemKind {
931 pub(crate) fn inner_items(&self) -> impl Iterator<Item = &Item> {
934 match self {
935 StructItem(s) => s.fields.iter(),
936 UnionItem(u) => u.fields.iter(),
937 VariantItem(v) => match &v.kind {
938 VariantKind::CLike => [].iter(),
939 VariantKind::Tuple(t) => t.iter(),
940 VariantKind::Struct(s) => s.fields.iter(),
941 },
942 EnumItem(e) => e.variants.iter(),
943 TraitItem(t) => t.items.iter(),
944 ImplItem(i) => i.items.iter(),
945 ModuleItem(m) => m.items.iter(),
946 ExternCrateItem { .. }
947 | ImportItem(_)
948 | FunctionItem(_)
949 | TypeAliasItem(_)
950 | StaticItem(_)
951 | ConstantItem(_)
952 | TraitAliasItem(_)
953 | RequiredMethodItem(_)
954 | MethodItem(_, _)
955 | StructFieldItem(_)
956 | ForeignFunctionItem(_, _)
957 | ForeignStaticItem(_, _)
958 | ForeignTypeItem
959 | MacroItem(_)
960 | ProcMacroItem(_)
961 | PrimitiveItem(_)
962 | RequiredAssocConstItem(..)
963 | ProvidedAssocConstItem(..)
964 | ImplAssocConstItem(..)
965 | RequiredAssocTypeItem(..)
966 | AssocTypeItem(..)
967 | StrippedItem(_)
968 | KeywordItem => [].iter(),
969 }
970 }
971
972 pub(crate) fn is_non_assoc(&self) -> bool {
974 matches!(
975 self,
976 StructItem(_)
977 | UnionItem(_)
978 | EnumItem(_)
979 | TraitItem(_)
980 | ModuleItem(_)
981 | ExternCrateItem { .. }
982 | FunctionItem(_)
983 | TypeAliasItem(_)
984 | StaticItem(_)
985 | ConstantItem(_)
986 | TraitAliasItem(_)
987 | ForeignFunctionItem(_, _)
988 | ForeignStaticItem(_, _)
989 | ForeignTypeItem
990 | MacroItem(_)
991 | ProcMacroItem(_)
992 | PrimitiveItem(_)
993 )
994 }
995}
996
997#[derive(Clone, Debug)]
998pub(crate) struct Module {
999 pub(crate) items: Vec<Item>,
1000 pub(crate) span: Span,
1001}
1002
1003pub(crate) fn hir_attr_lists<'a, I: IntoIterator<Item = &'a hir::Attribute>>(
1004 attrs: I,
1005 name: Symbol,
1006) -> impl Iterator<Item = ast::MetaItemInner> + use<'a, I> {
1007 attrs
1008 .into_iter()
1009 .filter(move |attr| attr.has_name(name))
1010 .filter_map(ast::attr::AttributeExt::meta_item_list)
1011 .flatten()
1012}
1013
1014pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute> + Clone>(
1015 attrs: I,
1016 tcx: TyCtxt<'_>,
1017 hidden_cfg: &FxHashSet<Cfg>,
1018) -> Option<Arc<Cfg>> {
1019 let doc_cfg_active = tcx.features().doc_cfg();
1020 let doc_auto_cfg_active = tcx.features().doc_auto_cfg();
1021
1022 fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
1023 let mut iter = it.into_iter();
1024 let item = iter.next()?;
1025 if iter.next().is_some() {
1026 return None;
1027 }
1028 Some(item)
1029 }
1030
1031 let mut cfg = if doc_cfg_active || doc_auto_cfg_active {
1032 let mut doc_cfg = attrs
1033 .clone()
1034 .filter(|attr| attr.has_name(sym::doc))
1035 .flat_map(|attr| attr.meta_item_list().unwrap_or_default())
1036 .filter(|attr| attr.has_name(sym::cfg))
1037 .peekable();
1038 if doc_cfg.peek().is_some() && doc_cfg_active {
1039 let sess = tcx.sess;
1040 doc_cfg.fold(Cfg::True, |mut cfg, item| {
1041 if let Some(cfg_mi) =
1042 item.meta_item().and_then(|item| rustc_expand::config::parse_cfg(item, sess))
1043 {
1044 rustc_attr_parsing::cfg_matches(
1046 cfg_mi,
1047 tcx.sess,
1048 rustc_ast::CRATE_NODE_ID,
1049 Some(tcx.features()),
1050 );
1051 match Cfg::parse(cfg_mi) {
1052 Ok(new_cfg) => cfg &= new_cfg,
1053 Err(e) => {
1054 sess.dcx().span_err(e.span, e.msg);
1055 }
1056 }
1057 }
1058 cfg
1059 })
1060 } else if doc_auto_cfg_active {
1061 attrs
1064 .clone()
1065 .filter(|attr| attr.has_name(sym::cfg_trace))
1066 .filter_map(|attr| single(attr.meta_item_list()?))
1067 .filter_map(|attr| Cfg::parse_without(attr.meta_item()?, hidden_cfg).ok().flatten())
1068 .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
1069 } else {
1070 Cfg::True
1071 }
1072 } else {
1073 Cfg::True
1074 };
1075
1076 for attr in hir_attr_lists(attrs, sym::target_feature) {
1079 if attr.has_name(sym::enable) && attr.value_str().is_some() {
1080 let mut meta = attr.meta_item().unwrap().clone();
1083 meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature));
1084
1085 if let Ok(feat_cfg) = Cfg::parse(&ast::MetaItemInner::MetaItem(meta)) {
1086 cfg &= feat_cfg;
1087 }
1088 }
1089 }
1090
1091 if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) }
1092}
1093
1094pub(crate) trait NestedAttributesExt {
1095 fn has_word(self, word: Symbol) -> bool
1097 where
1098 Self: Sized,
1099 {
1100 <Self as NestedAttributesExt>::get_word_attr(self, word).is_some()
1101 }
1102
1103 fn get_word_attr(self, word: Symbol) -> Option<ast::MetaItemInner>;
1106}
1107
1108impl<I: Iterator<Item = ast::MetaItemInner>> NestedAttributesExt for I {
1109 fn get_word_attr(mut self, word: Symbol) -> Option<ast::MetaItemInner> {
1110 self.find(|attr| attr.is_word() && attr.has_name(word))
1111 }
1112}
1113
1114#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1118pub(crate) struct ItemLink {
1119 pub(crate) link: Box<str>,
1121 pub(crate) link_text: Box<str>,
1126 pub(crate) page_id: DefId,
1130 pub(crate) fragment: Option<UrlFragment>,
1132}
1133
1134pub struct RenderedLink {
1135 pub(crate) original_text: Box<str>,
1139 pub(crate) new_text: Box<str>,
1141 pub(crate) href: String,
1143 pub(crate) tooltip: String,
1145}
1146
1147#[derive(Clone, Debug, Default)]
1150pub(crate) struct Attributes {
1151 pub(crate) doc_strings: Vec<DocFragment>,
1152 pub(crate) other_attrs: ThinVec<hir::Attribute>,
1153}
1154
1155impl Attributes {
1156 pub(crate) fn lists(&self, name: Symbol) -> impl Iterator<Item = ast::MetaItemInner> {
1157 hir_attr_lists(&self.other_attrs[..], name)
1158 }
1159
1160 pub(crate) fn has_doc_flag(&self, flag: Symbol) -> bool {
1161 for attr in &self.other_attrs {
1162 if !attr.has_name(sym::doc) {
1163 continue;
1164 }
1165
1166 if let Some(items) = attr.meta_item_list()
1167 && items.iter().filter_map(|i| i.meta_item()).any(|it| it.has_name(flag))
1168 {
1169 return true;
1170 }
1171 }
1172
1173 false
1174 }
1175
1176 pub(crate) fn is_doc_hidden(&self) -> bool {
1177 self.has_doc_flag(sym::hidden)
1178 }
1179
1180 pub(crate) fn from_hir(attrs: &[hir::Attribute]) -> Attributes {
1181 Attributes::from_hir_iter(attrs.iter().map(|attr| (attr, None)), false)
1182 }
1183
1184 pub(crate) fn from_hir_with_additional(
1185 attrs: &[hir::Attribute],
1186 (additional_attrs, def_id): (&[hir::Attribute], DefId),
1187 ) -> Attributes {
1188 let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id)));
1190 let attrs2 = attrs.iter().map(|attr| (attr, None));
1191 Attributes::from_hir_iter(attrs1.chain(attrs2), false)
1192 }
1193
1194 pub(crate) fn from_hir_iter<'a>(
1195 attrs: impl Iterator<Item = (&'a hir::Attribute, Option<DefId>)>,
1196 doc_only: bool,
1197 ) -> Attributes {
1198 let (doc_strings, other_attrs) = attrs_to_doc_fragments(attrs, doc_only);
1199 Attributes { doc_strings, other_attrs }
1200 }
1201
1202 pub(crate) fn doc_value(&self) -> String {
1204 self.opt_doc_value().unwrap_or_default()
1205 }
1206
1207 pub(crate) fn opt_doc_value(&self) -> Option<String> {
1211 (!self.doc_strings.is_empty()).then(|| {
1212 let mut res = String::new();
1213 for frag in &self.doc_strings {
1214 add_doc_fragment(&mut res, frag);
1215 }
1216 res.pop();
1217 res
1218 })
1219 }
1220
1221 pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> {
1222 let mut aliases = FxIndexSet::default();
1223
1224 for attr in
1225 hir_attr_lists(&self.other_attrs[..], sym::doc).filter(|a| a.has_name(sym::alias))
1226 {
1227 if let Some(values) = attr.meta_item_list() {
1228 for l in values {
1229 if let Some(lit) = l.lit()
1230 && let ast::LitKind::Str(s, _) = lit.kind
1231 {
1232 aliases.insert(s);
1233 }
1234 }
1235 } else if let Some(value) = attr.value_str() {
1236 aliases.insert(value);
1237 }
1238 }
1239 aliases.into_iter().collect::<Vec<_>>().into()
1240 }
1241}
1242
1243#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1244pub(crate) enum GenericBound {
1245 TraitBound(PolyTrait, hir::TraitBoundModifiers),
1246 Outlives(Lifetime),
1247 Use(Vec<PreciseCapturingArg>),
1249}
1250
1251impl GenericBound {
1252 pub(crate) fn sized(cx: &mut DocContext<'_>) -> GenericBound {
1253 Self::sized_with(cx, hir::TraitBoundModifiers::NONE)
1254 }
1255
1256 pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1257 Self::sized_with(
1258 cx,
1259 hir::TraitBoundModifiers {
1260 polarity: hir::BoundPolarity::Maybe(DUMMY_SP),
1261 constness: hir::BoundConstness::Never,
1262 },
1263 )
1264 }
1265
1266 fn sized_with(cx: &mut DocContext<'_>, modifiers: hir::TraitBoundModifiers) -> GenericBound {
1267 let did = cx.tcx.require_lang_item(LangItem::Sized, None);
1268 let empty = ty::Binder::dummy(ty::GenericArgs::empty());
1269 let path = clean_middle_path(cx, did, false, ThinVec::new(), empty);
1270 inline::record_extern_fqn(cx, did, ItemType::Trait);
1271 GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifiers)
1272 }
1273
1274 pub(crate) fn is_trait_bound(&self) -> bool {
1275 matches!(self, Self::TraitBound(..))
1276 }
1277
1278 pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1279 if let GenericBound::TraitBound(
1280 PolyTrait { ref trait_, .. },
1281 rustc_hir::TraitBoundModifiers::NONE,
1282 ) = *self
1283 && Some(trait_.def_id()) == cx.tcx.lang_items().sized_trait()
1284 {
1285 return true;
1286 }
1287 false
1288 }
1289
1290 pub(crate) fn get_trait_path(&self) -> Option<Path> {
1291 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1292 Some(trait_.clone())
1293 } else {
1294 None
1295 }
1296 }
1297}
1298
1299#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1300pub(crate) struct Lifetime(pub Symbol);
1301
1302impl Lifetime {
1303 pub(crate) fn statik() -> Lifetime {
1304 Lifetime(kw::StaticLifetime)
1305 }
1306
1307 pub(crate) fn elided() -> Lifetime {
1308 Lifetime(kw::UnderscoreLifetime)
1309 }
1310}
1311
1312#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1313pub(crate) enum PreciseCapturingArg {
1314 Lifetime(Lifetime),
1315 Param(Symbol),
1316}
1317
1318impl PreciseCapturingArg {
1319 pub(crate) fn name(self) -> Symbol {
1320 match self {
1321 PreciseCapturingArg::Lifetime(lt) => lt.0,
1322 PreciseCapturingArg::Param(param) => param,
1323 }
1324 }
1325}
1326
1327#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1328pub(crate) enum WherePredicate {
1329 BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
1330 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1331 EqPredicate { lhs: Type, rhs: Term },
1332}
1333
1334impl WherePredicate {
1335 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1336 match *self {
1337 WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
1338 WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
1339 _ => None,
1340 }
1341 }
1342}
1343
1344#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1345pub(crate) enum GenericParamDefKind {
1346 Lifetime { outlives: ThinVec<Lifetime> },
1347 Type { bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
1348 Const { ty: Box<Type>, default: Option<Box<String>>, synthetic: bool },
1350}
1351
1352impl GenericParamDefKind {
1353 pub(crate) fn is_type(&self) -> bool {
1354 matches!(self, GenericParamDefKind::Type { .. })
1355 }
1356}
1357
1358#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1359pub(crate) struct GenericParamDef {
1360 pub(crate) name: Symbol,
1361 pub(crate) def_id: DefId,
1362 pub(crate) kind: GenericParamDefKind,
1363}
1364
1365impl GenericParamDef {
1366 pub(crate) fn lifetime(def_id: DefId, name: Symbol) -> Self {
1367 Self { name, def_id, kind: GenericParamDefKind::Lifetime { outlives: ThinVec::new() } }
1368 }
1369
1370 pub(crate) fn is_synthetic_param(&self) -> bool {
1371 match self.kind {
1372 GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
1373 GenericParamDefKind::Type { synthetic, .. } => synthetic,
1374 }
1375 }
1376
1377 pub(crate) fn is_type(&self) -> bool {
1378 self.kind.is_type()
1379 }
1380
1381 pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1382 match self.kind {
1383 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1384 _ => None,
1385 }
1386 }
1387}
1388
1389#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
1391pub(crate) struct Generics {
1392 pub(crate) params: ThinVec<GenericParamDef>,
1393 pub(crate) where_predicates: ThinVec<WherePredicate>,
1394}
1395
1396impl Generics {
1397 pub(crate) fn is_empty(&self) -> bool {
1398 self.params.is_empty() && self.where_predicates.is_empty()
1399 }
1400}
1401
1402#[derive(Clone, Debug)]
1403pub(crate) struct Function {
1404 pub(crate) decl: FnDecl,
1405 pub(crate) generics: Generics,
1406}
1407
1408#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1409pub(crate) struct FnDecl {
1410 pub(crate) inputs: Arguments,
1411 pub(crate) output: Type,
1412 pub(crate) c_variadic: bool,
1413}
1414
1415impl FnDecl {
1416 pub(crate) fn receiver_type(&self) -> Option<&Type> {
1417 self.inputs.values.first().and_then(|v| v.to_receiver())
1418 }
1419}
1420
1421#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1422pub(crate) struct Arguments {
1423 pub(crate) values: Vec<Argument>,
1424}
1425
1426#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1427pub(crate) struct Argument {
1428 pub(crate) type_: Type,
1429 pub(crate) name: Symbol,
1430 pub(crate) is_const: bool,
1433}
1434
1435impl Argument {
1436 pub(crate) fn to_receiver(&self) -> Option<&Type> {
1437 if self.name == kw::SelfLower { Some(&self.type_) } else { None }
1438 }
1439}
1440
1441#[derive(Clone, Debug)]
1442pub(crate) struct Trait {
1443 pub(crate) def_id: DefId,
1444 pub(crate) items: Vec<Item>,
1445 pub(crate) generics: Generics,
1446 pub(crate) bounds: Vec<GenericBound>,
1447}
1448
1449impl Trait {
1450 pub(crate) fn is_auto(&self, tcx: TyCtxt<'_>) -> bool {
1451 tcx.trait_is_auto(self.def_id)
1452 }
1453 pub(crate) fn is_notable_trait(&self, tcx: TyCtxt<'_>) -> bool {
1454 tcx.is_doc_notable_trait(self.def_id)
1455 }
1456 pub(crate) fn safety(&self, tcx: TyCtxt<'_>) -> hir::Safety {
1457 tcx.trait_def(self.def_id).safety
1458 }
1459 pub(crate) fn is_dyn_compatible(&self, tcx: TyCtxt<'_>) -> bool {
1460 tcx.is_dyn_compatible(self.def_id)
1461 }
1462}
1463
1464#[derive(Clone, Debug)]
1465pub(crate) struct TraitAlias {
1466 pub(crate) generics: Generics,
1467 pub(crate) bounds: Vec<GenericBound>,
1468}
1469
1470#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1472pub(crate) struct PolyTrait {
1473 pub(crate) trait_: Path,
1474 pub(crate) generic_params: Vec<GenericParamDef>,
1475}
1476
1477#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1479pub(crate) enum Type {
1480 Path {
1485 path: Path,
1486 },
1487 DynTrait(Vec<PolyTrait>, Option<Lifetime>),
1489 Generic(Symbol),
1491 SelfTy,
1493 Primitive(PrimitiveType),
1495 BareFunction(Box<BareFunctionDecl>),
1497 Tuple(Vec<Type>),
1499 Slice(Box<Type>),
1501 Array(Box<Type>, Box<str>),
1505 Pat(Box<Type>, Box<str>),
1506 RawPointer(Mutability, Box<Type>),
1508 BorrowedRef {
1510 lifetime: Option<Lifetime>,
1511 mutability: Mutability,
1512 type_: Box<Type>,
1513 },
1514
1515 QPath(Box<QPathData>),
1517
1518 Infer,
1520
1521 ImplTrait(Vec<GenericBound>),
1523
1524 UnsafeBinder(Box<UnsafeBinderTy>),
1525}
1526
1527impl Type {
1528 pub(crate) fn without_borrowed_ref(&self) -> &Type {
1530 let mut result = self;
1531 while let Type::BorrowedRef { type_, .. } = result {
1532 result = type_;
1533 }
1534 result
1535 }
1536
1537 pub(crate) fn is_borrowed_ref(&self) -> bool {
1538 matches!(self, Type::BorrowedRef { .. })
1539 }
1540
1541 fn is_type_alias(&self) -> bool {
1542 matches!(self, Type::Path { path: Path { res: Res::Def(DefKind::TyAlias, _), .. } })
1543 }
1544
1545 pub(crate) fn is_doc_subtype_of(&self, other: &Self, cache: &Cache) -> bool {
1566 let (self_cleared, other_cleared) = if !self.is_borrowed_ref() || !other.is_borrowed_ref() {
1569 (self.without_borrowed_ref(), other.without_borrowed_ref())
1570 } else {
1571 (self, other)
1572 };
1573
1574 if self_cleared.is_type_alias() || other_cleared.is_type_alias() {
1580 return true;
1581 }
1582
1583 match (self_cleared, other_cleared) {
1584 (Type::Tuple(a), Type::Tuple(b)) => {
1586 a.len() == b.len() && a.iter().zip(b).all(|(a, b)| a.is_doc_subtype_of(b, cache))
1587 }
1588 (Type::Slice(a), Type::Slice(b)) => a.is_doc_subtype_of(b, cache),
1589 (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_doc_subtype_of(b, cache),
1590 (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
1591 mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache)
1592 }
1593 (
1594 Type::BorrowedRef { mutability, type_, .. },
1595 Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
1596 ) => mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache),
1597 (Type::Infer, _) | (_, Type::Infer) => true,
1599 (_, Type::Generic(_)) => true,
1602 (Type::Generic(_), _) => false,
1603 (Type::SelfTy, Type::SelfTy) => true,
1605 (Type::Path { path: a }, Type::Path { path: b }) => {
1607 a.def_id() == b.def_id()
1608 && a.generics()
1609 .zip(b.generics())
1610 .map(|(ag, bg)| {
1611 ag.iter().zip(bg.iter()).all(|(at, bt)| at.is_doc_subtype_of(bt, cache))
1612 })
1613 .unwrap_or(true)
1614 }
1615 (a, b) => a
1617 .def_id(cache)
1618 .and_then(|a| Some((a, b.def_id(cache)?)))
1619 .map(|(a, b)| a == b)
1620 .unwrap_or(false),
1621 }
1622 }
1623
1624 pub(crate) fn primitive_type(&self) -> Option<PrimitiveType> {
1625 match *self {
1626 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1627 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1628 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1629 Tuple(ref tys) => {
1630 if tys.is_empty() {
1631 Some(PrimitiveType::Unit)
1632 } else {
1633 Some(PrimitiveType::Tuple)
1634 }
1635 }
1636 RawPointer(..) => Some(PrimitiveType::RawPointer),
1637 BareFunction(..) => Some(PrimitiveType::Fn),
1638 _ => None,
1639 }
1640 }
1641
1642 pub(crate) fn sugared_async_return_type(self) -> Type {
1652 if let Type::ImplTrait(mut v) = self
1653 && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = v.pop()
1654 && let Some(segment) = trait_.segments.pop()
1655 && let GenericArgs::AngleBracketed { mut constraints, .. } = segment.args
1656 && let Some(constraint) = constraints.pop()
1657 && let AssocItemConstraintKind::Equality { term } = constraint.kind
1658 && let Term::Type(ty) = term
1659 {
1660 ty
1661 } else {
1662 panic!("unexpected async fn return type")
1663 }
1664 }
1665
1666 pub(crate) fn is_assoc_ty(&self) -> bool {
1668 match self {
1669 Type::Path { path, .. } => path.is_assoc_ty(),
1670 _ => false,
1671 }
1672 }
1673
1674 pub(crate) fn is_self_type(&self) -> bool {
1675 matches!(*self, Type::SelfTy)
1676 }
1677
1678 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
1679 match self {
1680 Type::Path { path, .. } => path.generic_args(),
1681 _ => None,
1682 }
1683 }
1684
1685 pub(crate) fn generics(&self) -> Option<Vec<&Type>> {
1686 match self {
1687 Type::Path { path, .. } => path.generics(),
1688 _ => None,
1689 }
1690 }
1691
1692 pub(crate) fn is_full_generic(&self) -> bool {
1693 matches!(self, Type::Generic(_))
1694 }
1695
1696 pub(crate) fn is_unit(&self) -> bool {
1697 matches!(self, Type::Tuple(v) if v.is_empty())
1698 }
1699
1700 pub(crate) fn projection(&self) -> Option<(&Type, DefId, PathSegment)> {
1701 if let QPath(box QPathData { self_type, trait_, assoc, .. }) = self {
1702 Some((self_type, trait_.as_ref()?.def_id(), assoc.clone()))
1703 } else {
1704 None
1705 }
1706 }
1707
1708 pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
1712 let t: PrimitiveType = match *self {
1713 Type::Path { ref path } => return Some(path.def_id()),
1714 DynTrait(ref bounds, _) => return bounds.first().map(|b| b.trait_.def_id()),
1715 Primitive(p) => return cache.primitive_locations.get(&p).cloned(),
1716 BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
1717 BorrowedRef { ref type_, .. } => return type_.def_id(cache),
1718 Tuple(ref tys) => {
1719 if tys.is_empty() {
1720 PrimitiveType::Unit
1721 } else {
1722 PrimitiveType::Tuple
1723 }
1724 }
1725 BareFunction(..) => PrimitiveType::Fn,
1726 Slice(..) => PrimitiveType::Slice,
1727 Array(..) => PrimitiveType::Array,
1728 Type::Pat(..) => PrimitiveType::Pat,
1729 RawPointer(..) => PrimitiveType::RawPointer,
1730 QPath(box QPathData { ref self_type, .. }) => return self_type.def_id(cache),
1731 Generic(_) | SelfTy | Infer | ImplTrait(_) | UnsafeBinder(_) => return None,
1732 };
1733 Primitive(t).def_id(cache)
1734 }
1735}
1736
1737#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1738pub(crate) struct QPathData {
1739 pub assoc: PathSegment,
1740 pub self_type: Type,
1741 pub should_show_cast: bool,
1743 pub trait_: Option<Path>,
1744}
1745
1746#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1753pub(crate) enum PrimitiveType {
1754 Isize,
1755 I8,
1756 I16,
1757 I32,
1758 I64,
1759 I128,
1760 Usize,
1761 U8,
1762 U16,
1763 U32,
1764 U64,
1765 U128,
1766 F16,
1767 F32,
1768 F64,
1769 F128,
1770 Char,
1771 Bool,
1772 Str,
1773 Slice,
1774 Array,
1775 Pat,
1776 Tuple,
1777 Unit,
1778 RawPointer,
1779 Reference,
1780 Fn,
1781 Never,
1782}
1783
1784type SimplifiedTypes = FxIndexMap<PrimitiveType, ArrayVec<SimplifiedType, 3>>;
1785impl PrimitiveType {
1786 pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1787 use ast::{FloatTy, IntTy, UintTy};
1788 match prim {
1789 hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1790 hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1791 hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1792 hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1793 hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1794 hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1795 hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1796 hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1797 hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1798 hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1799 hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1800 hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1801 hir::PrimTy::Float(FloatTy::F16) => PrimitiveType::F16,
1802 hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1803 hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1804 hir::PrimTy::Float(FloatTy::F128) => PrimitiveType::F128,
1805 hir::PrimTy::Str => PrimitiveType::Str,
1806 hir::PrimTy::Bool => PrimitiveType::Bool,
1807 hir::PrimTy::Char => PrimitiveType::Char,
1808 }
1809 }
1810
1811 pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1812 match s {
1813 sym::isize => Some(PrimitiveType::Isize),
1814 sym::i8 => Some(PrimitiveType::I8),
1815 sym::i16 => Some(PrimitiveType::I16),
1816 sym::i32 => Some(PrimitiveType::I32),
1817 sym::i64 => Some(PrimitiveType::I64),
1818 sym::i128 => Some(PrimitiveType::I128),
1819 sym::usize => Some(PrimitiveType::Usize),
1820 sym::u8 => Some(PrimitiveType::U8),
1821 sym::u16 => Some(PrimitiveType::U16),
1822 sym::u32 => Some(PrimitiveType::U32),
1823 sym::u64 => Some(PrimitiveType::U64),
1824 sym::u128 => Some(PrimitiveType::U128),
1825 sym::bool => Some(PrimitiveType::Bool),
1826 sym::char => Some(PrimitiveType::Char),
1827 sym::str => Some(PrimitiveType::Str),
1828 sym::f16 => Some(PrimitiveType::F16),
1829 sym::f32 => Some(PrimitiveType::F32),
1830 sym::f64 => Some(PrimitiveType::F64),
1831 sym::f128 => Some(PrimitiveType::F128),
1832 sym::array => Some(PrimitiveType::Array),
1833 sym::slice => Some(PrimitiveType::Slice),
1834 sym::tuple => Some(PrimitiveType::Tuple),
1835 sym::unit => Some(PrimitiveType::Unit),
1836 sym::pointer => Some(PrimitiveType::RawPointer),
1837 sym::reference => Some(PrimitiveType::Reference),
1838 kw::Fn => Some(PrimitiveType::Fn),
1839 sym::never => Some(PrimitiveType::Never),
1840 _ => None,
1841 }
1842 }
1843
1844 pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
1845 use PrimitiveType::*;
1846 use ty::{FloatTy, IntTy, UintTy};
1847 static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
1848
1849 let single = |x| iter::once(x).collect();
1850 CELL.get_or_init(move || {
1851 map! {
1852 Isize => single(SimplifiedType::Int(IntTy::Isize)),
1853 I8 => single(SimplifiedType::Int(IntTy::I8)),
1854 I16 => single(SimplifiedType::Int(IntTy::I16)),
1855 I32 => single(SimplifiedType::Int(IntTy::I32)),
1856 I64 => single(SimplifiedType::Int(IntTy::I64)),
1857 I128 => single(SimplifiedType::Int(IntTy::I128)),
1858 Usize => single(SimplifiedType::Uint(UintTy::Usize)),
1859 U8 => single(SimplifiedType::Uint(UintTy::U8)),
1860 U16 => single(SimplifiedType::Uint(UintTy::U16)),
1861 U32 => single(SimplifiedType::Uint(UintTy::U32)),
1862 U64 => single(SimplifiedType::Uint(UintTy::U64)),
1863 U128 => single(SimplifiedType::Uint(UintTy::U128)),
1864 F16 => single(SimplifiedType::Float(FloatTy::F16)),
1865 F32 => single(SimplifiedType::Float(FloatTy::F32)),
1866 F64 => single(SimplifiedType::Float(FloatTy::F64)),
1867 F128 => single(SimplifiedType::Float(FloatTy::F128)),
1868 Str => single(SimplifiedType::Str),
1869 Bool => single(SimplifiedType::Bool),
1870 Char => single(SimplifiedType::Char),
1871 Array => single(SimplifiedType::Array),
1872 Slice => single(SimplifiedType::Slice),
1873 Tuple => [SimplifiedType::Tuple(1), SimplifiedType::Tuple(2), SimplifiedType::Tuple(3)].into(),
1879 Unit => single(SimplifiedType::Tuple(0)),
1880 RawPointer => [SimplifiedType::Ptr(Mutability::Not), SimplifiedType::Ptr(Mutability::Mut)].into_iter().collect(),
1881 Reference => [SimplifiedType::Ref(Mutability::Not), SimplifiedType::Ref(Mutability::Mut)].into_iter().collect(),
1882 Fn => single(SimplifiedType::Function(1)),
1885 Never => single(SimplifiedType::Never),
1886 }
1887 })
1888 }
1889
1890 pub(crate) fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = DefId> + 'tcx {
1891 Self::simplified_types()
1892 .get(self)
1893 .into_iter()
1894 .flatten()
1895 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1896 .copied()
1897 }
1898
1899 pub(crate) fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> {
1900 Self::simplified_types()
1901 .values()
1902 .flatten()
1903 .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1904 .copied()
1905 }
1906
1907 pub(crate) fn as_sym(&self) -> Symbol {
1908 use PrimitiveType::*;
1909 match self {
1910 Isize => sym::isize,
1911 I8 => sym::i8,
1912 I16 => sym::i16,
1913 I32 => sym::i32,
1914 I64 => sym::i64,
1915 I128 => sym::i128,
1916 Usize => sym::usize,
1917 U8 => sym::u8,
1918 U16 => sym::u16,
1919 U32 => sym::u32,
1920 U64 => sym::u64,
1921 U128 => sym::u128,
1922 F16 => sym::f16,
1923 F32 => sym::f32,
1924 F64 => sym::f64,
1925 F128 => sym::f128,
1926 Str => sym::str,
1927 Bool => sym::bool,
1928 Char => sym::char,
1929 Array => sym::array,
1930 Pat => sym::pat,
1931 Slice => sym::slice,
1932 Tuple => sym::tuple,
1933 Unit => sym::unit,
1934 RawPointer => sym::pointer,
1935 Reference => sym::reference,
1936 Fn => kw::Fn,
1937 Never => sym::never,
1938 }
1939 }
1940
1941 pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxIndexMap<PrimitiveType, DefId> {
1953 static PRIMITIVE_LOCATIONS: OnceCell<FxIndexMap<PrimitiveType, DefId>> = OnceCell::new();
1954 PRIMITIVE_LOCATIONS.get_or_init(|| {
1955 let mut primitive_locations = FxIndexMap::default();
1956 for &crate_num in tcx.crates(()) {
1959 let e = ExternalCrate { crate_num };
1960 let crate_name = e.name(tcx);
1961 debug!(?crate_num, ?crate_name);
1962 for &(def_id, prim) in &e.primitives(tcx) {
1963 if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1965 continue;
1966 }
1967 primitive_locations.insert(prim, def_id);
1968 }
1969 }
1970 let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1971 for (def_id, prim) in local_primitives {
1972 primitive_locations.insert(prim, def_id);
1973 }
1974 primitive_locations
1975 })
1976 }
1977}
1978
1979impl From<ast::IntTy> for PrimitiveType {
1980 fn from(int_ty: ast::IntTy) -> PrimitiveType {
1981 match int_ty {
1982 ast::IntTy::Isize => PrimitiveType::Isize,
1983 ast::IntTy::I8 => PrimitiveType::I8,
1984 ast::IntTy::I16 => PrimitiveType::I16,
1985 ast::IntTy::I32 => PrimitiveType::I32,
1986 ast::IntTy::I64 => PrimitiveType::I64,
1987 ast::IntTy::I128 => PrimitiveType::I128,
1988 }
1989 }
1990}
1991
1992impl From<ast::UintTy> for PrimitiveType {
1993 fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1994 match uint_ty {
1995 ast::UintTy::Usize => PrimitiveType::Usize,
1996 ast::UintTy::U8 => PrimitiveType::U8,
1997 ast::UintTy::U16 => PrimitiveType::U16,
1998 ast::UintTy::U32 => PrimitiveType::U32,
1999 ast::UintTy::U64 => PrimitiveType::U64,
2000 ast::UintTy::U128 => PrimitiveType::U128,
2001 }
2002 }
2003}
2004
2005impl From<ast::FloatTy> for PrimitiveType {
2006 fn from(float_ty: ast::FloatTy) -> PrimitiveType {
2007 match float_ty {
2008 ast::FloatTy::F16 => PrimitiveType::F16,
2009 ast::FloatTy::F32 => PrimitiveType::F32,
2010 ast::FloatTy::F64 => PrimitiveType::F64,
2011 ast::FloatTy::F128 => PrimitiveType::F128,
2012 }
2013 }
2014}
2015
2016impl From<ty::IntTy> for PrimitiveType {
2017 fn from(int_ty: ty::IntTy) -> PrimitiveType {
2018 match int_ty {
2019 ty::IntTy::Isize => PrimitiveType::Isize,
2020 ty::IntTy::I8 => PrimitiveType::I8,
2021 ty::IntTy::I16 => PrimitiveType::I16,
2022 ty::IntTy::I32 => PrimitiveType::I32,
2023 ty::IntTy::I64 => PrimitiveType::I64,
2024 ty::IntTy::I128 => PrimitiveType::I128,
2025 }
2026 }
2027}
2028
2029impl From<ty::UintTy> for PrimitiveType {
2030 fn from(uint_ty: ty::UintTy) -> PrimitiveType {
2031 match uint_ty {
2032 ty::UintTy::Usize => PrimitiveType::Usize,
2033 ty::UintTy::U8 => PrimitiveType::U8,
2034 ty::UintTy::U16 => PrimitiveType::U16,
2035 ty::UintTy::U32 => PrimitiveType::U32,
2036 ty::UintTy::U64 => PrimitiveType::U64,
2037 ty::UintTy::U128 => PrimitiveType::U128,
2038 }
2039 }
2040}
2041
2042impl From<ty::FloatTy> for PrimitiveType {
2043 fn from(float_ty: ty::FloatTy) -> PrimitiveType {
2044 match float_ty {
2045 ty::FloatTy::F16 => PrimitiveType::F16,
2046 ty::FloatTy::F32 => PrimitiveType::F32,
2047 ty::FloatTy::F64 => PrimitiveType::F64,
2048 ty::FloatTy::F128 => PrimitiveType::F128,
2049 }
2050 }
2051}
2052
2053impl From<hir::PrimTy> for PrimitiveType {
2054 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
2055 match prim_ty {
2056 hir::PrimTy::Int(int_ty) => int_ty.into(),
2057 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
2058 hir::PrimTy::Float(float_ty) => float_ty.into(),
2059 hir::PrimTy::Str => PrimitiveType::Str,
2060 hir::PrimTy::Bool => PrimitiveType::Bool,
2061 hir::PrimTy::Char => PrimitiveType::Char,
2062 }
2063 }
2064}
2065
2066#[derive(Clone, Debug)]
2067pub(crate) struct Struct {
2068 pub(crate) ctor_kind: Option<CtorKind>,
2069 pub(crate) generics: Generics,
2070 pub(crate) fields: ThinVec<Item>,
2071}
2072
2073impl Struct {
2074 pub(crate) fn has_stripped_entries(&self) -> bool {
2075 self.fields.iter().any(|f| f.is_stripped())
2076 }
2077}
2078
2079#[derive(Clone, Debug)]
2080pub(crate) struct Union {
2081 pub(crate) generics: Generics,
2082 pub(crate) fields: Vec<Item>,
2083}
2084
2085impl Union {
2086 pub(crate) fn has_stripped_entries(&self) -> bool {
2087 self.fields.iter().any(|f| f.is_stripped())
2088 }
2089}
2090
2091#[derive(Clone, Debug)]
2095pub(crate) struct VariantStruct {
2096 pub(crate) fields: ThinVec<Item>,
2097}
2098
2099impl VariantStruct {
2100 pub(crate) fn has_stripped_entries(&self) -> bool {
2101 self.fields.iter().any(|f| f.is_stripped())
2102 }
2103}
2104
2105#[derive(Clone, Debug)]
2106pub(crate) struct Enum {
2107 pub(crate) variants: IndexVec<VariantIdx, Item>,
2108 pub(crate) generics: Generics,
2109}
2110
2111impl Enum {
2112 pub(crate) fn has_stripped_entries(&self) -> bool {
2113 self.variants.iter().any(|f| f.is_stripped())
2114 }
2115
2116 pub(crate) fn variants(&self) -> impl Iterator<Item = &Item> {
2117 self.variants.iter().filter(|v| !v.is_stripped())
2118 }
2119}
2120
2121#[derive(Clone, Debug)]
2122pub(crate) struct Variant {
2123 pub kind: VariantKind,
2124 pub discriminant: Option<Discriminant>,
2125}
2126
2127#[derive(Clone, Debug)]
2128pub(crate) enum VariantKind {
2129 CLike,
2130 Tuple(ThinVec<Item>),
2131 Struct(VariantStruct),
2132}
2133
2134impl Variant {
2135 pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
2136 match &self.kind {
2137 VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()),
2138 VariantKind::CLike | VariantKind::Tuple(_) => None,
2139 }
2140 }
2141}
2142
2143#[derive(Clone, Debug)]
2144pub(crate) struct Discriminant {
2145 pub(super) expr: Option<BodyId>,
2148 pub(super) value: DefId,
2149}
2150
2151impl Discriminant {
2152 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
2155 self.expr
2156 .map(|body| rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body)))
2157 }
2158 pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String {
2159 print_evaluated_const(tcx, self.value, with_underscores, false).unwrap()
2160 }
2161}
2162
2163#[derive(Copy, Clone, Debug)]
2166pub(crate) struct Span(rustc_span::Span);
2167
2168impl Span {
2169 pub(crate) fn new(sp: rustc_span::Span) -> Self {
2174 Self(sp.source_callsite())
2175 }
2176
2177 pub(crate) fn inner(&self) -> rustc_span::Span {
2178 self.0
2179 }
2180
2181 pub(crate) fn filename(&self, sess: &Session) -> FileName {
2182 sess.source_map().span_to_filename(self.0)
2183 }
2184
2185 pub(crate) fn lo(&self, sess: &Session) -> Loc {
2186 sess.source_map().lookup_char_pos(self.0.lo())
2187 }
2188
2189 pub(crate) fn hi(&self, sess: &Session) -> Loc {
2190 sess.source_map().lookup_char_pos(self.0.hi())
2191 }
2192
2193 pub(crate) fn cnum(&self, sess: &Session) -> CrateNum {
2194 self.lo(sess).file.cnum
2196 }
2197}
2198
2199#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2200pub(crate) struct Path {
2201 pub(crate) res: Res,
2202 pub(crate) segments: ThinVec<PathSegment>,
2203}
2204
2205impl Path {
2206 pub(crate) fn def_id(&self) -> DefId {
2207 self.res.def_id()
2208 }
2209
2210 pub(crate) fn last_opt(&self) -> Option<Symbol> {
2211 self.segments.last().map(|s| s.name)
2212 }
2213
2214 pub(crate) fn last(&self) -> Symbol {
2215 self.last_opt().expect("segments were empty")
2216 }
2217
2218 pub(crate) fn whole_name(&self) -> String {
2219 self.segments
2220 .iter()
2221 .map(|s| if s.name == kw::PathRoot { "" } else { s.name.as_str() })
2222 .intersperse("::")
2223 .collect()
2224 }
2225
2226 pub(crate) fn is_assoc_ty(&self) -> bool {
2228 match self.res {
2229 Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _)
2230 if self.segments.len() != 1 =>
2231 {
2232 true
2233 }
2234 Res::Def(DefKind::AssocTy, _) => true,
2235 _ => false,
2236 }
2237 }
2238
2239 pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
2240 self.segments.last().map(|seg| &seg.args)
2241 }
2242
2243 pub(crate) fn generics(&self) -> Option<Vec<&Type>> {
2244 self.segments.last().and_then(|seg| {
2245 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2246 Some(
2247 args.iter()
2248 .filter_map(|arg| match arg {
2249 GenericArg::Type(ty) => Some(ty),
2250 _ => None,
2251 })
2252 .collect(),
2253 )
2254 } else {
2255 None
2256 }
2257 })
2258 }
2259}
2260
2261#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2262pub(crate) enum GenericArg {
2263 Lifetime(Lifetime),
2264 Type(Type),
2265 Const(Box<ConstantKind>),
2266 Infer,
2267}
2268
2269impl GenericArg {
2270 pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
2271 if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2272 }
2273
2274 pub(crate) fn as_ty(&self) -> Option<&Type> {
2275 if let Self::Type(ty) = self { Some(ty) } else { None }
2276 }
2277}
2278
2279#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2280pub(crate) enum GenericArgs {
2281 AngleBracketed { args: ThinVec<GenericArg>, constraints: ThinVec<AssocItemConstraint> },
2283 Parenthesized { inputs: ThinVec<Type>, output: Option<Box<Type>> },
2285 ReturnTypeNotation,
2287}
2288
2289impl GenericArgs {
2290 pub(crate) fn is_empty(&self) -> bool {
2291 match self {
2292 GenericArgs::AngleBracketed { args, constraints } => {
2293 args.is_empty() && constraints.is_empty()
2294 }
2295 GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
2296 GenericArgs::ReturnTypeNotation => false,
2297 }
2298 }
2299 pub(crate) fn constraints(&self) -> Box<dyn Iterator<Item = AssocItemConstraint> + '_> {
2300 match self {
2301 GenericArgs::AngleBracketed { constraints, .. } => {
2302 Box::new(constraints.iter().cloned())
2303 }
2304 GenericArgs::Parenthesized { output, .. } => Box::new(
2305 output
2306 .as_ref()
2307 .map(|ty| AssocItemConstraint {
2308 assoc: PathSegment {
2309 name: sym::Output,
2310 args: GenericArgs::AngleBracketed {
2311 args: ThinVec::new(),
2312 constraints: ThinVec::new(),
2313 },
2314 },
2315 kind: AssocItemConstraintKind::Equality {
2316 term: Term::Type((**ty).clone()),
2317 },
2318 })
2319 .into_iter(),
2320 ),
2321 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2322 }
2323 }
2324}
2325
2326impl<'a> IntoIterator for &'a GenericArgs {
2327 type IntoIter = Box<dyn Iterator<Item = GenericArg> + 'a>;
2328 type Item = GenericArg;
2329 fn into_iter(self) -> Self::IntoIter {
2330 match self {
2331 GenericArgs::AngleBracketed { args, .. } => Box::new(args.iter().cloned()),
2332 GenericArgs::Parenthesized { inputs, .. } => {
2333 Box::new(inputs.iter().cloned().map(GenericArg::Type))
2335 }
2336 GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2337 }
2338 }
2339}
2340
2341#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2342pub(crate) struct PathSegment {
2343 pub(crate) name: Symbol,
2344 pub(crate) args: GenericArgs,
2345}
2346
2347#[derive(Clone, Debug)]
2348pub(crate) enum TypeAliasInnerType {
2349 Enum { variants: IndexVec<VariantIdx, Item>, is_non_exhaustive: bool },
2350 Union { fields: Vec<Item> },
2351 Struct { ctor_kind: Option<CtorKind>, fields: Vec<Item> },
2352}
2353
2354#[derive(Clone, Debug)]
2355pub(crate) struct TypeAlias {
2356 pub(crate) type_: Type,
2357 pub(crate) generics: Generics,
2358 pub(crate) inner_type: Option<TypeAliasInnerType>,
2361 pub(crate) item_type: Option<Type>,
2368}
2369
2370#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2371pub(crate) struct BareFunctionDecl {
2372 pub(crate) safety: hir::Safety,
2373 pub(crate) generic_params: Vec<GenericParamDef>,
2374 pub(crate) decl: FnDecl,
2375 pub(crate) abi: ExternAbi,
2376}
2377
2378#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2379pub(crate) struct UnsafeBinderTy {
2380 pub(crate) generic_params: Vec<GenericParamDef>,
2381 pub(crate) ty: Type,
2382}
2383
2384#[derive(Clone, Debug)]
2385pub(crate) struct Static {
2386 pub(crate) type_: Box<Type>,
2387 pub(crate) mutability: Mutability,
2388 pub(crate) expr: Option<BodyId>,
2389}
2390
2391#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2392pub(crate) struct Constant {
2393 pub(crate) generics: Generics,
2394 pub(crate) kind: ConstantKind,
2395 pub(crate) type_: Type,
2396}
2397
2398#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2399pub(crate) enum Term {
2400 Type(Type),
2401 Constant(ConstantKind),
2402}
2403
2404impl Term {
2405 pub(crate) fn ty(&self) -> Option<&Type> {
2406 if let Term::Type(ty) = self { Some(ty) } else { None }
2407 }
2408}
2409
2410impl From<Type> for Term {
2411 fn from(ty: Type) -> Self {
2412 Term::Type(ty)
2413 }
2414}
2415
2416#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2417pub(crate) enum ConstantKind {
2418 TyConst { expr: Box<str> },
2424 Path { path: Box<str> },
2427 Anonymous { body: BodyId },
2431 Extern { def_id: DefId },
2433 Local { def_id: DefId, body: BodyId },
2435 Infer,
2437}
2438
2439impl Constant {
2440 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2441 self.kind.expr(tcx)
2442 }
2443
2444 pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2445 self.kind.value(tcx)
2446 }
2447
2448 pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2449 self.kind.is_literal(tcx)
2450 }
2451}
2452
2453impl ConstantKind {
2454 pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2455 match *self {
2456 ConstantKind::TyConst { ref expr } => expr.to_string(),
2457 ConstantKind::Path { ref path } => path.to_string(),
2458 ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2459 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2460 rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body))
2461 }
2462 ConstantKind::Infer => "_".to_string(),
2463 }
2464 }
2465
2466 pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2467 match *self {
2468 ConstantKind::TyConst { .. }
2469 | ConstantKind::Path { .. }
2470 | ConstantKind::Anonymous { .. }
2471 | ConstantKind::Infer => None,
2472 ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2473 print_evaluated_const(tcx, def_id, true, true)
2474 }
2475 }
2476 }
2477
2478 pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2479 match *self {
2480 ConstantKind::TyConst { .. }
2481 | ConstantKind::Extern { .. }
2482 | ConstantKind::Path { .. }
2483 | ConstantKind::Infer => false,
2484 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2485 is_literal_expr(tcx, body.hir_id)
2486 }
2487 }
2488 }
2489}
2490
2491#[derive(Clone, Debug)]
2492pub(crate) struct Impl {
2493 pub(crate) safety: hir::Safety,
2494 pub(crate) generics: Generics,
2495 pub(crate) trait_: Option<Path>,
2496 pub(crate) for_: Type,
2497 pub(crate) items: Vec<Item>,
2498 pub(crate) polarity: ty::ImplPolarity,
2499 pub(crate) kind: ImplKind,
2500}
2501
2502impl Impl {
2503 pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxIndexSet<Symbol> {
2504 self.trait_
2505 .as_ref()
2506 .map(|t| t.def_id())
2507 .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name).collect())
2508 .unwrap_or_default()
2509 }
2510
2511 pub(crate) fn is_negative_trait_impl(&self) -> bool {
2512 matches!(self.polarity, ty::ImplPolarity::Negative)
2513 }
2514}
2515
2516#[derive(Clone, Debug)]
2517pub(crate) enum ImplKind {
2518 Normal,
2519 Auto,
2520 FakeVariadic,
2521 Blanket(Box<Type>),
2522}
2523
2524impl ImplKind {
2525 pub(crate) fn is_auto(&self) -> bool {
2526 matches!(self, ImplKind::Auto)
2527 }
2528
2529 pub(crate) fn is_blanket(&self) -> bool {
2530 matches!(self, ImplKind::Blanket(_))
2531 }
2532
2533 pub(crate) fn is_fake_variadic(&self) -> bool {
2534 matches!(self, ImplKind::FakeVariadic)
2535 }
2536
2537 pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
2538 match self {
2539 ImplKind::Blanket(ty) => Some(ty),
2540 _ => None,
2541 }
2542 }
2543}
2544
2545#[derive(Clone, Debug)]
2546pub(crate) struct Import {
2547 pub(crate) kind: ImportKind,
2548 pub(crate) source: ImportSource,
2550 pub(crate) should_be_displayed: bool,
2551}
2552
2553impl Import {
2554 pub(crate) fn new_simple(
2555 name: Symbol,
2556 source: ImportSource,
2557 should_be_displayed: bool,
2558 ) -> Self {
2559 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2560 }
2561
2562 pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2563 Self { kind: ImportKind::Glob, source, should_be_displayed }
2564 }
2565
2566 pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool {
2567 self.source.did.is_some_and(|did| tcx.is_doc_hidden(did))
2568 }
2569}
2570
2571#[derive(Clone, Debug)]
2572pub(crate) enum ImportKind {
2573 Simple(Symbol),
2575 Glob,
2577}
2578
2579#[derive(Clone, Debug)]
2580pub(crate) struct ImportSource {
2581 pub(crate) path: Path,
2582 pub(crate) did: Option<DefId>,
2583}
2584
2585#[derive(Clone, Debug)]
2586pub(crate) struct Macro {
2587 pub(crate) source: String,
2588 pub(crate) macro_rules: bool,
2590}
2591
2592#[derive(Clone, Debug)]
2593pub(crate) struct ProcMacro {
2594 pub(crate) kind: MacroKind,
2595 pub(crate) helpers: Vec<Symbol>,
2596}
2597
2598#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2609pub(crate) struct AssocItemConstraint {
2610 pub(crate) assoc: PathSegment,
2611 pub(crate) kind: AssocItemConstraintKind,
2612}
2613
2614#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2616pub(crate) enum AssocItemConstraintKind {
2617 Equality { term: Term },
2618 Bound { bounds: Vec<GenericBound> },
2619}
2620
2621#[cfg(target_pointer_width = "64")]
2623mod size_asserts {
2624 use rustc_data_structures::static_assert_size;
2625
2626 use super::*;
2627 static_assert_size!(Crate, 16); static_assert_size!(DocFragment, 32);
2630 static_assert_size!(GenericArg, 32);
2631 static_assert_size!(GenericArgs, 24);
2632 static_assert_size!(GenericParamDef, 40);
2633 static_assert_size!(Generics, 16);
2634 static_assert_size!(Item, 8);
2635 static_assert_size!(ItemInner, 136);
2636 static_assert_size!(ItemKind, 48);
2637 static_assert_size!(PathSegment, 32);
2638 static_assert_size!(Type, 32);
2639 }