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