Skip to main content

rustdoc/clean/
types.rs

1use std::fmt::Write;
2use std::hash::Hash;
3use std::path::PathBuf;
4use std::sync::{Arc, OnceLock as OnceCell};
5use std::{fmt, iter};
6
7use arrayvec::ArrayVec;
8use itertools::Either;
9use rustc_abi::{ExternAbi, VariantIdx};
10use rustc_ast as ast;
11use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
12use rustc_data_structures::thin_vec::ThinVec;
13use rustc_hir as hir;
14use rustc_hir::attrs::lang_items::LangItem;
15use rustc_hir::attrs::{AttributeKind, DeprecatedSince, Deprecation, DocAttribute};
16use rustc_hir::def::{CtorKind, DefKind, MacroKinds, Res};
17use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
18use rustc_hir::{Attribute, BodyId, ConstStability, Mutability, Stability, StableSince, find_attr};
19use rustc_index::IndexVec;
20use rustc_metadata::rendered_const;
21use rustc_middle::ty::fast_reject::SimplifiedType;
22use rustc_middle::ty::{self, Ty, TyCtxt, Visibility};
23use rustc_resolve::rustdoc::{
24    DocFragment, add_doc_fragment, attrs_to_doc_fragments, inner_docs, span_of_fragments,
25};
26use rustc_session::Session;
27use rustc_span::def_id::{CRATE_DEF_ID, ModId};
28use rustc_span::hygiene::MacroKind;
29use rustc_span::symbol::{Symbol, kw, sym};
30use rustc_span::{DUMMY_SP, FileName, Ident, Loc, RemapPathScopeComponents, span_bug};
31use tracing::{debug, trace};
32
33pub(crate) use self::ItemKind::*;
34pub(crate) use self::Type::{
35    Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath,
36    RawPointer, SelfTy, Slice, Tuple, UnsafeBinder,
37};
38use crate::clean::cfg::Cfg;
39use crate::clean::clean_middle_path;
40use crate::clean::inline::{self, print_inlined_const};
41use crate::clean::utils::{is_literal_expr, print_evaluated_const};
42use crate::core::DocContext;
43use crate::formats::cache::Cache;
44use crate::formats::item_type::ItemType;
45use crate::html::format::HrefInfo;
46use crate::html::render::Context;
47use crate::passes::collect_intra_doc_links::UrlFragment;
48
49#[cfg(test)]
50mod tests;
51
52pub(crate) type ItemIdSet = FxHashSet<ItemId>;
53
54#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
55pub(crate) enum ItemId {
56    /// A "normal" item that uses a [`DefId`] for identification.
57    DefId(DefId),
58    /// Identifier that is used for auto traits.
59    Auto { trait_: DefId, for_: DefId },
60    /// Identifier that is used for blanket implementations.
61    Blanket { impl_id: DefId, for_: DefId },
62}
63
64#[derive(Debug, Copy, Clone, PartialEq, Eq)]
65pub(crate) enum Defaultness {
66    Implicit,
67    Default,
68    Final,
69}
70
71impl Defaultness {
72    pub(crate) fn from_trait_item(defaultness: hir::Defaultness) -> Self {
73        match defaultness {
74            hir::Defaultness::Default { .. } => Self::Implicit,
75            hir::Defaultness::Final => Self::Final,
76        }
77    }
78
79    pub(crate) fn from_impl_item(defaultness: hir::Defaultness) -> Self {
80        match defaultness {
81            hir::Defaultness::Default { .. } => Self::Default,
82            hir::Defaultness::Final => Self::Implicit,
83        }
84    }
85}
86
87impl ItemId {
88    #[inline]
89    pub(crate) fn is_local(self) -> bool {
90        match self {
91            ItemId::Auto { for_: id, .. }
92            | ItemId::Blanket { for_: id, .. }
93            | ItemId::DefId(id) => id.is_local(),
94        }
95    }
96
97    #[inline]
98    #[track_caller]
99    pub(crate) fn expect_def_id(self) -> DefId {
100        self.as_def_id()
101            .unwrap_or_else(|| panic!("ItemId::expect_def_id: `{self:?}` isn't a DefId"))
102    }
103
104    #[inline]
105    pub(crate) fn as_def_id(self) -> Option<DefId> {
106        match self {
107            ItemId::DefId(id) => Some(id),
108            _ => None,
109        }
110    }
111
112    #[inline]
113    pub(crate) fn as_local_def_id(self) -> Option<LocalDefId> {
114        self.as_def_id().and_then(|id| id.as_local())
115    }
116
117    #[inline]
118    pub(crate) fn krate(self) -> CrateNum {
119        match self {
120            ItemId::Auto { for_: id, .. }
121            | ItemId::Blanket { for_: id, .. }
122            | ItemId::DefId(id) => id.krate,
123        }
124    }
125}
126
127impl From<DefId> for ItemId {
128    fn from(id: DefId) -> Self {
129        Self::DefId(id)
130    }
131}
132
133/// The crate currently being documented.
134#[derive(Debug)]
135pub(crate) struct Crate {
136    pub(crate) module: Item,
137    /// Only here so that they can be filtered through the rustdoc passes.
138    pub(crate) external_traits: Box<FxIndexMap<DefId, Trait>>,
139}
140
141impl Crate {
142    pub(crate) fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
143        ExternalCrate::LOCAL.name(tcx)
144    }
145
146    pub(crate) fn src(&self, tcx: TyCtxt<'_>) -> FileName {
147        ExternalCrate::LOCAL.src(tcx)
148    }
149}
150
151#[derive(Copy, Clone, Debug)]
152pub(crate) struct ExternalCrate {
153    pub(crate) crate_num: CrateNum,
154}
155
156impl ExternalCrate {
157    const LOCAL: Self = Self { crate_num: LOCAL_CRATE };
158
159    #[inline]
160    pub(crate) fn def_id(&self) -> DefId {
161        self.crate_num.as_def_id()
162    }
163
164    pub(crate) fn src(&self, tcx: TyCtxt<'_>) -> FileName {
165        let krate_span = tcx.def_span(self.def_id());
166        tcx.sess.source_map().span_to_filename(krate_span)
167    }
168
169    pub(crate) fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
170        tcx.crate_name(self.crate_num)
171    }
172
173    pub(crate) fn src_root(&self, tcx: TyCtxt<'_>) -> PathBuf {
174        match self.src(tcx) {
175            FileName::Real(ref p) => {
176                match p
177                    .local_path()
178                    .or(Some(p.path(RemapPathScopeComponents::DOCUMENTATION)))
179                    .unwrap()
180                    .parent()
181                {
182                    Some(p) => p.to_path_buf(),
183                    None => PathBuf::new(),
184                }
185            }
186            _ => PathBuf::new(),
187        }
188    }
189
190    /// Attempts to find where an external crate is located, given that we're
191    /// rendering into the specified source destination.
192    pub(crate) fn location(
193        &self,
194        extern_url: Option<&str>,
195        extern_url_takes_precedence: bool,
196        dst: &std::path::Path,
197        tcx: TyCtxt<'_>,
198    ) -> ExternalLocation {
199        use ExternalLocation::*;
200
201        fn to_remote(url: impl ToString) -> ExternalLocation {
202            let mut url = url.to_string();
203            if !url.ends_with('/') {
204                url.push('/');
205            }
206            let is_absolute = url.starts_with('/')
207                || url.split_once(':').is_some_and(|(scheme, _)| {
208                    scheme.bytes().next().is_some_and(|b| b.is_ascii_alphabetic())
209                        && scheme
210                            .bytes()
211                            .all(|b| b.is_ascii_alphanumeric() || matches!(b, b'+' | b'-' | b'.'))
212                });
213            Remote { url, is_absolute }
214        }
215
216        // See if there's documentation generated into the local directory
217        // WARNING: since rustdoc creates these directories as it generates documentation, this check is only accurate before rendering starts.
218        // Make sure to call `location()` by that time.
219        let local_location = dst.join(self.name(tcx).as_str());
220        if local_location.is_dir() {
221            return Local;
222        }
223
224        if extern_url_takes_precedence && let Some(url) = extern_url {
225            return to_remote(url);
226        }
227
228        // Failing that, see if there's an attribute specifying where to find this
229        // external crate
230        let did = self.crate_num.as_def_id();
231        find_attr!(tcx, did, Doc(d) =>d.html_root_url.map(|(url, _)| url))
232            .flatten()
233            .map(to_remote)
234            .or_else(|| extern_url.map(to_remote)) // NOTE: only matters if `extern_url_takes_precedence` is false
235            .unwrap_or(Unknown) // Well, at least we tried.
236    }
237
238    fn fake_doc_items<T>(
239        &self,
240        tcx: TyCtxt<'_>,
241        f: impl Fn(DefId, TyCtxt<'_>) -> Option<(DefId, T)>,
242    ) -> impl Iterator<Item = (DefId, T)> {
243        tcx.fake_doc_items(self.crate_num).into_iter().filter_map(move |did| f(*did, tcx))
244    }
245
246    pub(crate) fn keywords(&self, tcx: TyCtxt<'_>) -> impl Iterator<Item = (DefId, Symbol)> {
247        self.retrieve_keywords_or_documented_attributes(tcx, |d| d.keyword.map(|(v, _)| v))
248    }
249    pub(crate) fn documented_attributes(
250        &self,
251        tcx: TyCtxt<'_>,
252    ) -> impl Iterator<Item = (DefId, Symbol)> {
253        self.retrieve_keywords_or_documented_attributes(tcx, |d| d.attribute.map(|(v, _)| v))
254    }
255
256    fn retrieve_keywords_or_documented_attributes<F: Fn(&DocAttribute) -> Option<Symbol>>(
257        &self,
258        tcx: TyCtxt<'_>,
259        callback: F,
260    ) -> impl Iterator<Item = (DefId, Symbol)> {
261        let as_target = move |did: DefId, tcx: TyCtxt<'_>| -> Option<(DefId, Symbol)> {
262            find_attr!(tcx, did, Doc(d) => callback(d)).flatten().map(|value| (did, value))
263        };
264        self.fake_doc_items(tcx, as_target)
265    }
266
267    pub(crate) fn primitives(
268        &self,
269        tcx: TyCtxt<'_>,
270    ) -> impl Iterator<Item = (DefId, PrimitiveType)> {
271        // Collect all inner modules which are tagged as implementations of
272        // primitives.
273        //
274        // Note that this loop only searches the top-level items of the crate,
275        // and this is intentional. If we were to search the entire crate for an
276        // item tagged with `#[rustc_doc_primitive]` then we would also have to
277        // search the entirety of external modules for items tagged
278        // `#[rustc_doc_primitive]`, which is a pretty inefficient process (decoding
279        // all that metadata unconditionally).
280        //
281        // In order to keep the metadata load under control, the
282        // `#[rustc_doc_primitive]` feature is explicitly designed to only allow the
283        // primitive tags to show up as the top level items in a crate.
284        //
285        // Also note that this does not attempt to deal with modules tagged
286        // duplicately for the same primitive. This is handled later on when
287        // rendering by delegating everything to a hash map.
288        fn as_primitive(def_id: DefId, tcx: TyCtxt<'_>) -> Option<(DefId, PrimitiveType)> {
289            let (attr_span, prim_sym) = find_attr!(
290                tcx, def_id,
291                RustcDocPrimitive(span, prim) => (*span, *prim)
292            )?;
293            let Some(prim) = PrimitiveType::from_symbol(prim_sym) else {
294                span_bug!(attr_span, "primitive `{prim_sym}` is not a member of `PrimitiveType`");
295            };
296            Some((def_id, prim))
297        }
298
299        self.fake_doc_items(tcx, as_primitive)
300    }
301}
302
303/// Indicates where an external crate can be found.
304#[derive(Debug)]
305pub(crate) enum ExternalLocation {
306    /// Remote URL root of the external crate
307    Remote { url: String, is_absolute: bool },
308    /// This external crate can be found in the local doc/ folder
309    Local,
310    /// The external crate could not be found.
311    Unknown,
312}
313
314/// Anything with a source location and set of attributes and, optionally, a
315/// name. That is, anything that can be documented. This doesn't correspond
316/// directly to the AST's concept of an item; it's a strict superset.
317#[derive(Clone)]
318pub(crate) struct Item {
319    pub(crate) inner: Box<ItemInner>,
320}
321
322// Why does the `Item`/`ItemInner` split exist? `Vec<Item>`s are common, and
323// without the split `Item` would be a large type (100+ bytes) which results in
324// lots of wasted space in the unused parts of a `Vec<Item>`. With the split,
325// `Item` is just 8 bytes, and the wasted space is avoided, at the cost of an
326// extra allocation per item. This is a performance win.
327#[derive(Clone)]
328pub(crate) struct ItemInner {
329    /// The name of this item.
330    /// Optional because not every item has a name, e.g. impls.
331    pub(crate) name: Option<Symbol>,
332    /// Information about this item that is specific to what kind of item it is.
333    /// E.g., struct vs enum vs function.
334    pub(crate) kind: ItemKind,
335    pub(crate) attrs: Attributes,
336    /// The effective stability, filled out by the `propagate-stability` pass.
337    pub(crate) stability: Option<Stability>,
338    pub(crate) item_id: ItemId,
339    /// This is the `LocalDefId` of the `use` statement if the item was inlined.
340    /// The crate metadata doesn't hold this information, so the `use` statement
341    /// always belongs to the current crate.
342    pub(crate) inline_stmt_id: Option<LocalDefId>,
343    pub(crate) cfg: Option<Arc<Cfg>>,
344}
345
346impl std::ops::Deref for Item {
347    type Target = ItemInner;
348    fn deref(&self) -> &ItemInner {
349        &self.inner
350    }
351}
352
353/// NOTE: this does NOT unconditionally print every item, to avoid thousands of lines of logs.
354/// If you want to see the debug output for attributes and the `kind` as well, use `{:#?}` instead of `{:?}`.
355impl fmt::Debug for Item {
356    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
357        let alternate = f.alternate();
358        // hand-picked fields that don't bloat the logs too much
359        let mut fmt = f.debug_struct("Item");
360        fmt.field("name", &self.name).field("item_id", &self.item_id);
361        // allow printing the full item if someone really wants to
362        if alternate {
363            fmt.field("attrs", &self.attrs).field("kind", &self.kind).field("cfg", &self.cfg);
364        } else {
365            fmt.field("kind", &self.type_());
366            fmt.field("docs", &self.doc_value());
367        }
368        fmt.finish()
369    }
370}
371
372pub(crate) fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
373    Span::new(def_id.as_local().map_or_else(
374        || tcx.def_span(def_id),
375        |local| tcx.hir_span_with_body(tcx.local_def_id_to_hir_id(local)),
376    ))
377}
378
379fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
380    let parent = tcx.parent(def_id);
381    match tcx.def_kind(parent) {
382        DefKind::Struct | DefKind::Union => false,
383        DefKind::Variant => true,
384        parent_kind => panic!("unexpected parent kind: {parent_kind:?}"),
385    }
386}
387
388impl Item {
389    pub(crate) fn cfg_parent_ids_for_detached_item(&self, tcx: TyCtxt<'_>) -> Vec<LocalDefId> {
390        let Some(def_id) = self.inline_stmt_id.or(self.item_id.as_local_def_id()) else {
391            return Vec::new();
392        };
393        let mut ids = Vec::new();
394        let mut next = def_id;
395        while let Some(parent) = tcx.opt_local_parent(next) {
396            if parent == CRATE_DEF_ID {
397                break;
398            }
399            ids.push(parent);
400            next = parent;
401        }
402        ids.reverse();
403        ids
404    }
405
406    /// Returns the effective stability of the item.
407    ///
408    /// This method should only be called after the `propagate-stability` pass has been run.
409    pub(crate) fn stability(&self, tcx: TyCtxt<'_>) -> Option<Stability> {
410        let stability = self.inner.stability;
411        debug_assert!(
412            stability.is_some()
413                || self.def_id().is_none_or(|did| tcx.lookup_stability(did).is_none()),
414            "missing stability for cleaned item: {self:?}",
415        );
416        stability
417    }
418
419    pub(crate) fn const_stability(&self, tcx: TyCtxt<'_>) -> Option<ConstStability> {
420        self.def_id().and_then(|did| tcx.lookup_const_stability(did))
421    }
422
423    pub(crate) fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
424        self.def_id().and_then(|did| tcx.lookup_deprecation(did)).or_else(|| {
425            // `allowed_through_unstable_modules` is a bug-compatibility hack for old rustc
426            // versions; the paths that are exposed through it are "deprecated" because they
427            // were never supposed to work at all.
428            let stab = self.stability(tcx)?;
429            if let rustc_hir::StabilityLevel::Stable {
430                allowed_through_unstable_modules: Some((note, _)),
431                ..
432            } = stab.level
433            {
434                Some(Deprecation {
435                    since: DeprecatedSince::Unspecified,
436                    note: Some(Ident { name: note, span: DUMMY_SP }),
437                    suggestion: None,
438                })
439            } else {
440                None
441            }
442        })
443    }
444
445    pub(crate) fn is_deprecated(&self, tcx: TyCtxt<'_>) -> bool {
446        self.deprecation(tcx).is_some_and(|deprecation| deprecation.is_in_effect())
447    }
448
449    pub(crate) fn is_unstable(&self) -> bool {
450        self.stability.is_some_and(|x| x.is_unstable())
451    }
452
453    pub(crate) fn is_exported_macro(&self) -> bool {
454        match self.kind {
455            ItemKind::MacroItem(..) => find_attr!(&self.attrs.other_attrs, MacroExport { .. }),
456            _ => false,
457        }
458    }
459
460    pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
461        self.item_id
462            .as_def_id()
463            .map(|did| {
464                inner_docs(
465                    #[allow(deprecated)]
466                    tcx.get_all_attrs(did),
467                )
468            })
469            .unwrap_or(false)
470    }
471
472    /// Returns true if item is an associated function with a `self` parameter.
473    pub(crate) fn has_self_param(&self) -> bool {
474        if let ItemKind::MethodItem(Function { decl, .. }, _) = &self.inner.kind {
475            decl.receiver_type().is_some()
476        } else {
477            false
478        }
479    }
480
481    pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option<Span> {
482        let kind = match &self.kind {
483            ItemKind::StrippedItem(k) => k,
484            _ => &self.kind,
485        };
486        match kind {
487            ItemKind::ModuleItem(Module { span, .. }) => Some(*span),
488            ItemKind::ImplItem(Impl { kind: ImplKind::Auto, .. }) => None,
489            ItemKind::ImplItem(Impl { kind: ImplKind::Blanket(_), .. }) => {
490                if let ItemId::Blanket { impl_id, .. } = self.item_id {
491                    Some(rustc_span(impl_id, tcx))
492                } else {
493                    panic!("blanket impl item has non-blanket ID")
494                }
495            }
496            _ => self.def_id().map(|did| rustc_span(did, tcx)),
497        }
498    }
499
500    pub(crate) fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
501        let deprecation_notes = find_attr!(&self.attrs.other_attrs, Deprecated { deprecation, .. } => deprecation.note.map(|note| note.span)).flatten();
502
503        span_of_fragments(&self.attrs.doc_strings)
504            .into_iter()
505            .chain(deprecation_notes)
506            .reduce(|a, b| a.to(b))
507            .unwrap_or_else(|| self.span(tcx).map_or(DUMMY_SP, |span| span.inner()))
508    }
509
510    /// Combine all doc strings into a single value handling indentation and newlines as needed.
511    pub(crate) fn doc_value(&self) -> String {
512        self.attrs.doc_value()
513    }
514
515    /// Combine all doc strings into a single value handling indentation and newlines as needed.
516    /// Returns `None` is there's no documentation at all, and `Some("")` if there is some
517    /// documentation but it is empty (e.g. `#[doc = ""]`).
518    pub(crate) fn opt_doc_value(&self) -> Option<String> {
519        self.attrs.opt_doc_value()
520    }
521
522    pub(crate) fn from_def_id_and_parts(
523        def_id: DefId,
524        name: Option<Symbol>,
525        kind: ItemKind,
526        tcx: TyCtxt<'_>,
527    ) -> Item {
528        #[allow(deprecated)]
529        let hir_attrs = tcx.get_all_attrs(def_id);
530
531        Self::from_def_id_and_attrs_and_parts(
532            def_id,
533            name,
534            kind,
535            Attributes::from_hir(hir_attrs),
536            None,
537        )
538    }
539
540    pub(crate) fn from_def_id_and_attrs_and_parts(
541        def_id: DefId,
542        name: Option<Symbol>,
543        kind: ItemKind,
544        attrs: Attributes,
545        cfg: Option<Arc<Cfg>>,
546    ) -> Item {
547        trace!("name={name:?}, def_id={def_id:?} cfg={cfg:?}");
548
549        Item {
550            inner: Box::new(ItemInner {
551                item_id: def_id.into(),
552                kind,
553                attrs,
554                stability: None,
555                name,
556                cfg,
557                inline_stmt_id: None,
558            }),
559        }
560    }
561
562    /// If the item has doc comments from a reexport, returns the item id of that reexport,
563    /// otherwise returns returns the item id.
564    ///
565    /// This is used as a key for caching intra-doc link resolution,
566    /// to prevent two reexports of the same item from using the same cache.
567    pub(crate) fn item_or_reexport_id(&self) -> ItemId {
568        // added documentation on a reexport is always prepended.
569        self.attrs
570            .doc_strings
571            .first()
572            .map(|x| x.item_id)
573            .flatten()
574            .map(ItemId::from)
575            .unwrap_or(self.item_id)
576    }
577
578    pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
579        use crate::html::format::{href_with_path_check, link_tooltip};
580
581        let Some(links) = cx.cache().intra_doc_links.get(&self.item_or_reexport_id()) else {
582            return vec![];
583        };
584        links
585            .iter()
586            .filter_map(|ItemLink { link: s, link_text, page_id: id, fragment }| {
587                debug!(?id);
588                if let Ok(HrefInfo { mut url, .. }) = href_with_path_check(*id, cx, link_text) {
589                    debug!(?url);
590                    match fragment {
591                        Some(UrlFragment::Item(def_id)) => {
592                            write!(url, "{}", crate::html::format::fragment(*def_id, cx.tcx()))
593                                .unwrap();
594                        }
595                        Some(UrlFragment::UserWritten(raw)) => {
596                            url.push('#');
597                            url.push_str(raw);
598                        }
599                        None => {}
600                    }
601                    Some(RenderedLink {
602                        original_text: s.clone(),
603                        new_text: link_text.clone(),
604                        tooltip: link_tooltip(*id, fragment, cx, Some(link_text)).to_string(),
605                        href: url,
606                    })
607                } else {
608                    None
609                }
610            })
611            .collect()
612    }
613
614    /// Find a list of all link names, without finding their href.
615    ///
616    /// This is used for generating summary text, which does not include
617    /// the link text, but does need to know which `[]`-bracketed names
618    /// are actually links.
619    pub(crate) fn link_names(&self, cache: &Cache) -> Vec<RenderedLink> {
620        let Some(links) = cache.intra_doc_links.get(&self.item_id) else {
621            return vec![];
622        };
623        links
624            .iter()
625            .map(|ItemLink { link: s, link_text, .. }| RenderedLink {
626                original_text: s.clone(),
627                new_text: link_text.clone(),
628                href: String::new(),
629                tooltip: String::new(),
630            })
631            .collect()
632    }
633
634    pub(crate) fn is_crate(&self) -> bool {
635        self.is_mod() && self.def_id().is_some_and(|did| did.is_crate_root())
636    }
637    pub(crate) fn is_mod(&self) -> bool {
638        self.type_() == ItemType::Module
639    }
640    pub(crate) fn is_struct(&self) -> bool {
641        self.type_() == ItemType::Struct
642    }
643    pub(crate) fn is_enum(&self) -> bool {
644        self.type_() == ItemType::Enum
645    }
646    pub(crate) fn is_variant(&self) -> bool {
647        self.type_() == ItemType::Variant
648    }
649    pub(crate) fn is_associated_type(&self) -> bool {
650        matches!(self.kind, AssocTypeItem(..) | StrippedItem(AssocTypeItem(..)))
651    }
652    pub(crate) fn is_required_associated_type(&self) -> bool {
653        matches!(self.kind, RequiredAssocTypeItem(..) | StrippedItem(RequiredAssocTypeItem(..)))
654    }
655    pub(crate) fn is_associated_const(&self) -> bool {
656        matches!(
657            self.kind,
658            ProvidedAssocConstItem(..)
659                | ImplAssocConstItem(..)
660                | StrippedItem(ProvidedAssocConstItem(..) | ImplAssocConstItem(..))
661        )
662    }
663    pub(crate) fn is_required_associated_const(&self) -> bool {
664        matches!(self.kind, RequiredAssocConstItem(..) | StrippedItem(RequiredAssocConstItem(..)))
665    }
666    pub(crate) fn is_method(&self) -> bool {
667        self.type_() == ItemType::Method
668    }
669    pub(crate) fn is_ty_method(&self) -> bool {
670        self.type_() == ItemType::TyMethod
671    }
672    pub(crate) fn is_primitive(&self) -> bool {
673        self.type_() == ItemType::Primitive
674    }
675    pub(crate) fn is_union(&self) -> bool {
676        self.type_() == ItemType::Union
677    }
678    pub(crate) fn is_import(&self) -> bool {
679        self.type_() == ItemType::Import
680    }
681    pub(crate) fn is_extern_crate(&self) -> bool {
682        self.type_() == ItemType::ExternCrate
683    }
684    pub(crate) fn is_keyword(&self) -> bool {
685        self.type_() == ItemType::Keyword
686    }
687    pub(crate) fn is_attribute(&self) -> bool {
688        self.type_() == ItemType::Attribute
689    }
690    /// Returns `true` if the item kind is one of the following:
691    ///
692    /// * `ItemType::Primitive`
693    /// * `ItemType::Keyword`
694    /// * `ItemType::Attribute`
695    ///
696    /// They are considered fake because they only exist thanks to their
697    /// `#[doc(primitive|keyword|attribute)]` attribute.
698    pub(crate) fn is_fake_item(&self) -> bool {
699        matches!(self.type_(), ItemType::Primitive | ItemType::Keyword | ItemType::Attribute)
700    }
701    pub(crate) fn is_stripped(&self) -> bool {
702        match self.kind {
703            StrippedItem(..) => true,
704            ImportItem(ref i) => !i.should_be_displayed,
705            _ => false,
706        }
707    }
708    pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
709        match self.kind {
710            StructItem(ref struct_) => Some(struct_.has_stripped_entries()),
711            UnionItem(ref union_) => Some(union_.has_stripped_entries()),
712            EnumItem(ref enum_) => Some(enum_.has_stripped_entries()),
713            VariantItem(ref v) => v.has_stripped_entries(),
714            TypeAliasItem(ref type_alias) => {
715                type_alias.inner_type.as_ref().and_then(|t| t.has_stripped_entries())
716            }
717            _ => None,
718        }
719    }
720
721    pub(crate) fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
722        self.stability(tcx).as_ref().and_then(|s| {
723            let mut classes = Vec::with_capacity(2);
724
725            if s.is_unstable() {
726                classes.push("unstable");
727            }
728
729            // FIXME: what about non-staged API items that are deprecated?
730            if self.deprecation(tcx).is_some() {
731                classes.push("deprecated");
732            }
733
734            if !classes.is_empty() { Some(classes.join(" ")) } else { None }
735        })
736    }
737
738    pub(crate) fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<StableSince> {
739        self.stability(tcx).and_then(|stability| stability.stable_since())
740    }
741
742    pub(crate) fn is_non_exhaustive(&self) -> bool {
743        find_attr!(&self.attrs.other_attrs, NonExhaustive(..))
744    }
745
746    /// Returns a documentation-level item type from the item. In case of a `macro_rules!` which
747    /// contains an attr/derive kind, it will always return `ItemType::Macro`. If you want all
748    /// kinds, you need to use [`Item::types`].
749    pub(crate) fn type_(&self) -> ItemType {
750        ItemType::from(self)
751    }
752
753    /// Returns an item types. There is only one case where it can return more than one kind:
754    /// for `macro_rules!` items which contain an attr/derive kind.
755    pub(crate) fn types(&self) -> impl Iterator<Item = ItemType> {
756        if let ItemKind::MacroItem(_, macro_kinds) = self.kind {
757            Either::Right(macro_kinds.iter().map(|kind| match kind {
758                MacroKinds::ATTR => ItemType::DeclMacroAttribute,
759                MacroKinds::DERIVE => ItemType::DeclMacroDerive,
760                MacroKinds::BANG => ItemType::Macro,
761                _ => panic!("unsupported macro kind {kind:?}"),
762            }))
763        } else {
764            Either::Left(std::iter::once(self.type_()))
765        }
766    }
767
768    /// Returns true if this a macro declared with the `macro` keyword or with `macro_rules!.
769    pub(crate) fn is_decl_macro(&self) -> bool {
770        matches!(self.kind, ItemKind::MacroItem(..))
771    }
772
773    pub(crate) fn defaultness(&self) -> Option<Defaultness> {
774        match self.kind {
775            ItemKind::MethodItem(_, defaultness) | ItemKind::RequiredMethodItem(_, defaultness) => {
776                Some(defaultness)
777            }
778            _ => None,
779        }
780    }
781
782    /// Generates the HTML file name based on the item kind.
783    pub(crate) fn html_filename(&self) -> String {
784        format!("{type_}.{name}.html", type_ = self.type_(), name = self.name.unwrap())
785    }
786
787    /// Returns a `FnHeader` if `self` is a function item, otherwise returns `None`.
788    pub(crate) fn fn_header(&self, tcx: TyCtxt<'_>) -> Option<hir::FnHeader> {
789        fn build_fn_header(
790            def_id: DefId,
791            tcx: TyCtxt<'_>,
792            asyncness: ty::Asyncness,
793        ) -> hir::FnHeader {
794            let sig = tcx.fn_sig(def_id).skip_binder();
795            let constness = if tcx.is_const_fn(def_id) {
796                // rustc's `is_const_fn` returns `true` for associated functions that have an `impl const` parent
797                // or that have a `const trait` parent. Do not display those as `const` in rustdoc because we
798                // won't be printing correct syntax plus the syntax is unstable.
799                if let Some(assoc) = tcx.opt_associated_item(def_id)
800                    && let ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) =
801                        assoc.container
802                {
803                    hir::Constness::NotConst
804                } else {
805                    hir::Constness::Const { always: false }
806                }
807            } else {
808                hir::Constness::NotConst
809            };
810            let asyncness = match asyncness {
811                ty::Asyncness::Yes => hir::IsAsync::Async(DUMMY_SP),
812                ty::Asyncness::No => hir::IsAsync::NotAsync,
813            };
814            hir::FnHeader {
815                safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
816                    hir::HeaderSafety::SafeTargetFeatures
817                } else {
818                    sig.safety().into()
819                },
820                abi: sig.abi(),
821                constness,
822                asyncness,
823            }
824        }
825        let header = match self.kind {
826            ItemKind::ForeignFunctionItem(_, safety) => {
827                let def_id = self.def_id().unwrap();
828                let abi = tcx.fn_sig(def_id).skip_binder().abi();
829                hir::FnHeader {
830                    safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
831                        hir::HeaderSafety::SafeTargetFeatures
832                    } else {
833                        safety.into()
834                    },
835                    abi,
836                    // Foreign functions can never be const or comptime
837                    constness: hir::Constness::NotConst,
838                    asyncness: hir::IsAsync::NotAsync,
839                }
840            }
841            ItemKind::FunctionItem(_)
842            | ItemKind::MethodItem(..)
843            | ItemKind::RequiredMethodItem(..) => {
844                let def_id = self.def_id().unwrap();
845                build_fn_header(def_id, tcx, tcx.asyncness(def_id))
846            }
847            _ => return None,
848        };
849        Some(header)
850    }
851
852    /// Returns the visibility of the current item. If the visibility is "inherited", then `None`
853    /// is returned.
854    pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option<Visibility<ModId>> {
855        let def_id = match self.item_id {
856            // Anything but DefId *shouldn't* matter, but return a reasonable value anyway.
857            ItemId::Auto { .. } | ItemId::Blanket { .. } => return None,
858            ItemId::DefId(def_id) => def_id,
859        };
860
861        match self.kind {
862            // Primitives and Keywords are written in the source code as private modules.
863            // The modules need to be private so that nobody actually uses them, but the
864            // keywords and primitives that they are documenting are public.
865            ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) | ItemKind::AttributeItem => {
866                return Some(Visibility::Public);
867            }
868            // Variant fields inherit their enum's visibility.
869            StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => {
870                return None;
871            }
872            // Variants always inherit visibility
873            VariantItem(..) | ImplItem(..) => return None,
874            // Trait items inherit the trait's visibility
875            RequiredAssocConstItem(..)
876            | ProvidedAssocConstItem(..)
877            | ImplAssocConstItem(..)
878            | AssocTypeItem(..)
879            | RequiredAssocTypeItem(..)
880            | RequiredMethodItem(..)
881            | MethodItem(..) => {
882                match tcx.associated_item(def_id).container {
883                    // Trait impl items always inherit the impl's visibility --
884                    // we don't want to show `pub`.
885                    ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) => {
886                        return None;
887                    }
888                    ty::AssocContainer::InherentImpl => {}
889                }
890            }
891            _ => {}
892        }
893        let def_id = match self.inline_stmt_id {
894            Some(inlined) => inlined.to_def_id(),
895            None => def_id,
896        };
897        Some(tcx.visibility(def_id))
898    }
899
900    pub fn is_doc_hidden(&self) -> bool {
901        self.attrs.is_doc_hidden()
902    }
903
904    pub fn def_id(&self) -> Option<DefId> {
905        self.item_id.as_def_id()
906    }
907}
908
909#[derive(Clone, Debug)]
910pub(crate) enum ItemKind {
911    ExternCrateItem {
912        /// The crate's name, *not* the name it's imported as.
913        src: Option<Symbol>,
914    },
915    ImportItem(Import),
916    StructItem(Struct),
917    UnionItem(Union),
918    EnumItem(Enum),
919    FunctionItem(Box<Function>),
920    ModuleItem(Module),
921    TypeAliasItem(Box<TypeAlias>),
922    StaticItem(Static),
923    TraitItem(Box<Trait>),
924    TraitAliasItem(TraitAlias),
925    ImplItem(Box<Impl>),
926    /// This variant is used only as a placeholder for trait impls in order to correctly compute
927    /// `doc_cfg` as trait impls are added to `clean::Crate` after we went through the whole tree.
928    PlaceholderImplItem,
929    /// A required method in a trait declaration meaning it's only a function signature.
930    RequiredMethodItem(Box<Function>, Defaultness),
931    /// A method in a trait impl or a provided method in a trait declaration.
932    ///
933    /// Compared to [RequiredMethodItem], it also contains a method body.
934    MethodItem(Box<Function>, Defaultness),
935    StructFieldItem(Type),
936    VariantItem(Variant),
937    /// `fn`s from an extern block
938    ForeignFunctionItem(Box<Function>, hir::Safety),
939    /// `static`s from an extern block
940    ForeignStaticItem(Static, hir::Safety),
941    /// `type`s from an extern block
942    ForeignTypeItem,
943    /// A macro defined with `macro_rules` or the `macro` keyword. It can be multiple things (macro,
944    /// derive and attribute, potentially multiple at once). Don't forget to look into the
945    ///`MacroKinds` values.
946    ///
947    /// If a `macro_rules!` only contains a `attr`/`derive` branch, then it's not stored in this
948    /// variant but in the `ProcMacroItem` variant.
949    MacroItem(Macro, MacroKinds),
950    ProcMacroItem(ProcMacro),
951    PrimitiveItem(PrimitiveType),
952    /// A required associated constant in a trait declaration.
953    RequiredAssocConstItem(Generics, Box<Type>),
954    ConstantItem(Box<Constant>),
955    /// An associated constant in a trait declaration with provided default value.
956    ProvidedAssocConstItem(Box<Constant>),
957    /// An associated constant in an inherent impl or trait impl.
958    ImplAssocConstItem(Box<Constant>),
959    /// A required associated type in a trait declaration.
960    ///
961    /// The bounds may be non-empty if there is a `where` clause.
962    RequiredAssocTypeItem(Generics, Vec<GenericBound>),
963    /// An associated type in a trait impl or a provided one in a trait declaration.
964    AssocTypeItem(Box<TypeAlias>, Vec<GenericBound>),
965    /// An item that has been stripped by a rustdoc pass
966    StrippedItem(Box<ItemKind>),
967    /// This item represents an anonymous constant with a `#[doc(keyword = "...")]` attribute which is used
968    /// to generate documentation for Rust keywords.
969    KeywordItem,
970    /// This item represents an anonymous constant with a `#[doc(attribute = "...")]` attribute which is used
971    /// to generate documentation for Rust builtin attributes.
972    AttributeItem,
973}
974
975impl ItemKind {
976    /// Some items contain others such as structs (for their fields) and Enums
977    /// (for their variants). This method returns those contained items.
978    pub(crate) fn inner_items(&self) -> impl Iterator<Item = &Item> {
979        match self {
980            StructItem(s) => s.fields.iter(),
981            UnionItem(u) => u.fields.iter(),
982            VariantItem(v) => match &v.kind {
983                VariantKind::CLike => [].iter(),
984                VariantKind::Tuple(t) => t.iter(),
985                VariantKind::Struct(s) => s.fields.iter(),
986            },
987            EnumItem(e) => e.variants.iter(),
988            TraitItem(t) => t.items.iter(),
989            ImplItem(i) => i.items.iter(),
990            ModuleItem(m) => m.items.iter(),
991            ExternCrateItem { .. }
992            | ImportItem(_)
993            | FunctionItem(_)
994            | TypeAliasItem(_)
995            | StaticItem(_)
996            | ConstantItem(_)
997            | TraitAliasItem(_)
998            | RequiredMethodItem(..)
999            | MethodItem(..)
1000            | StructFieldItem(_)
1001            | ForeignFunctionItem(_, _)
1002            | ForeignStaticItem(_, _)
1003            | ForeignTypeItem
1004            | MacroItem(..)
1005            | ProcMacroItem(_)
1006            | PrimitiveItem(_)
1007            | RequiredAssocConstItem(..)
1008            | ProvidedAssocConstItem(..)
1009            | ImplAssocConstItem(..)
1010            | RequiredAssocTypeItem(..)
1011            | AssocTypeItem(..)
1012            | StrippedItem(_)
1013            | KeywordItem
1014            | AttributeItem
1015            | PlaceholderImplItem => [].iter(),
1016        }
1017    }
1018}
1019
1020#[derive(Clone, Debug)]
1021pub(crate) struct Module {
1022    pub(crate) items: Vec<Item>,
1023    pub(crate) span: Span,
1024}
1025
1026/// A link that has not yet been rendered.
1027///
1028/// This link will be turned into a rendered link by [`Item::links`].
1029#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1030pub(crate) struct ItemLink {
1031    /// The original link written in the markdown
1032    pub(crate) link: Box<str>,
1033    /// The link text displayed in the HTML.
1034    ///
1035    /// This may not be the same as `link` if there was a disambiguator
1036    /// in an intra-doc link (e.g. \[`fn@f`\])
1037    pub(crate) link_text: Box<str>,
1038    /// The `DefId` of the Item whose **HTML Page** contains the item being
1039    /// linked to. This will be different to `item_id` on item's that don't
1040    /// have their own page, such as struct fields and enum variants.
1041    pub(crate) page_id: DefId,
1042    /// The url fragment to append to the link
1043    pub(crate) fragment: Option<UrlFragment>,
1044}
1045
1046pub struct RenderedLink {
1047    /// The text the link was original written as.
1048    ///
1049    /// This could potentially include disambiguators and backticks.
1050    pub(crate) original_text: Box<str>,
1051    /// The text to display in the HTML
1052    pub(crate) new_text: Box<str>,
1053    /// The URL to put in the `href`
1054    pub(crate) href: String,
1055    /// The tooltip.
1056    pub(crate) tooltip: String,
1057}
1058
1059/// The attributes on an [`Item`], including attributes like `#[derive(...)]` and `#[inline]`,
1060/// as well as doc comments.
1061#[derive(Clone, Debug, Default)]
1062pub(crate) struct Attributes {
1063    pub(crate) doc_strings: Vec<DocFragment>,
1064    pub(crate) other_attrs: ThinVec<hir::Attribute>,
1065}
1066
1067impl Attributes {
1068    pub(crate) fn has_doc_flag<F: Fn(&DocAttribute) -> bool>(&self, callback: F) -> bool {
1069        find_attr!(&self.other_attrs, Doc(d) if callback(d))
1070    }
1071
1072    pub(crate) fn is_doc_hidden(&self) -> bool {
1073        find_attr!(&self.other_attrs, Doc(d) if d.hidden.is_some())
1074    }
1075
1076    pub(crate) fn from_hir(attrs: &[hir::Attribute]) -> Attributes {
1077        Attributes::from_hir_iter(attrs.iter().map(|attr| (attr, None)), false)
1078    }
1079
1080    pub(crate) fn from_hir_with_additional(
1081        attrs: &[hir::Attribute],
1082        (additional_attrs, def_id): (&[hir::Attribute], DefId),
1083    ) -> Attributes {
1084        // Additional documentation should be shown before the original documentation.
1085        let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id)));
1086        let attrs2 = attrs.iter().map(|attr| (attr, None));
1087        Attributes::from_hir_iter(attrs1.chain(attrs2), false)
1088    }
1089
1090    pub(crate) fn from_hir_iter<'a>(
1091        attrs: impl Iterator<Item = (&'a hir::Attribute, Option<DefId>)>,
1092        doc_only: bool,
1093    ) -> Attributes {
1094        let (doc_strings, other_attrs) = attrs_to_doc_fragments(attrs, doc_only);
1095        Attributes { doc_strings, other_attrs }
1096    }
1097
1098    /// Combine all doc strings into a single value handling indentation and newlines as needed.
1099    pub(crate) fn doc_value(&self) -> String {
1100        self.opt_doc_value().unwrap_or_default()
1101    }
1102
1103    /// Combine all doc strings into a single value handling indentation and newlines as needed.
1104    /// Returns `None` is there's no documentation at all, and `Some("")` if there is some
1105    /// documentation but it is empty (e.g. `#[doc = ""]`).
1106    pub(crate) fn opt_doc_value(&self) -> Option<String> {
1107        (!self.doc_strings.is_empty()).then(|| {
1108            let mut res = String::new();
1109            for frag in &self.doc_strings {
1110                add_doc_fragment(&mut res, frag);
1111            }
1112            res.pop();
1113            res
1114        })
1115    }
1116
1117    pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> {
1118        let mut aliases = FxIndexSet::default();
1119
1120        for attr in &self.other_attrs {
1121            if let Attribute::Parsed(AttributeKind::Doc(d)) = attr {
1122                for (alias, _) in &d.aliases {
1123                    aliases.insert(*alias);
1124                }
1125            }
1126        }
1127        aliases.into_iter().collect::<Vec<_>>().into()
1128    }
1129
1130    pub(crate) fn merge_with(&mut self, other: Self) {
1131        let Self { doc_strings, other_attrs } = other;
1132        self.doc_strings.extend(doc_strings);
1133        self.other_attrs.extend(other_attrs);
1134    }
1135}
1136
1137#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1138pub(crate) enum GenericBound {
1139    TraitBound(PolyTrait, hir::TraitBoundModifiers),
1140    Outlives(Lifetime),
1141    /// `use<'a, T>` precise-capturing bound syntax
1142    Use(Vec<PreciseCapturingArg>),
1143}
1144
1145impl GenericBound {
1146    pub(crate) fn sized(cx: &mut DocContext<'_>) -> GenericBound {
1147        Self::sized_with(cx, hir::TraitBoundModifiers::NONE)
1148    }
1149
1150    pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1151        Self::sized_with(
1152            cx,
1153            hir::TraitBoundModifiers {
1154                polarity: hir::BoundPolarity::Maybe(DUMMY_SP),
1155                constness: hir::BoundConstness::Never,
1156            },
1157        )
1158    }
1159
1160    fn sized_with(cx: &mut DocContext<'_>, modifiers: hir::TraitBoundModifiers) -> GenericBound {
1161        let did = cx.tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
1162        let empty = ty::Binder::dummy(ty::GenericArgs::empty());
1163        let path = clean_middle_path(cx, did, false, ThinVec::new(), empty);
1164        inline::record_extern_fqn(cx, did, ItemType::Trait);
1165        GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifiers)
1166    }
1167
1168    pub(crate) fn is_trait_bound(&self) -> bool {
1169        matches!(self, Self::TraitBound(..))
1170    }
1171
1172    pub(crate) fn is_sized_bound(&self, tcx: TyCtxt<'_>) -> bool {
1173        self.is_bounded_by_lang_item(tcx, LangItem::Sized)
1174    }
1175
1176    pub(crate) fn is_meta_sized_bound(&self, tcx: TyCtxt<'_>) -> bool {
1177        self.is_bounded_by_lang_item(tcx, LangItem::MetaSized)
1178    }
1179
1180    fn is_bounded_by_lang_item(&self, tcx: TyCtxt<'_>, lang_item: LangItem) -> bool {
1181        if let GenericBound::TraitBound(poly_trait_ref, rustc_hir::TraitBoundModifiers::NONE) = self
1182            && tcx.is_lang_item(poly_trait_ref.trait_.def_id(), lang_item)
1183        {
1184            return true;
1185        }
1186        false
1187    }
1188
1189    pub(crate) fn get_trait_path(&self) -> Option<Path> {
1190        if let GenericBound::TraitBound(poly_trait_ref, _) = self {
1191            Some(poly_trait_ref.trait_.clone())
1192        } else {
1193            None
1194        }
1195    }
1196}
1197
1198#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1199pub(crate) struct Lifetime(pub Symbol);
1200
1201impl Lifetime {
1202    pub(crate) fn statik() -> Lifetime {
1203        Lifetime(kw::StaticLifetime)
1204    }
1205
1206    pub(crate) fn elided() -> Lifetime {
1207        Lifetime(kw::UnderscoreLifetime)
1208    }
1209}
1210
1211#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
1212pub(crate) enum PreciseCapturingArg {
1213    Lifetime(Lifetime),
1214    Param(Symbol),
1215}
1216
1217impl PreciseCapturingArg {
1218    pub(crate) fn name(self) -> Symbol {
1219        match self {
1220            PreciseCapturingArg::Lifetime(lt) => lt.0,
1221            PreciseCapturingArg::Param(param) => param,
1222        }
1223    }
1224}
1225
1226#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1227pub(crate) enum WherePredicate {
1228    BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
1229    RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1230    ProjectionPredicate { lhs: QPathData, rhs: Term },
1231}
1232
1233impl WherePredicate {
1234    pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1235        match self {
1236            WherePredicate::BoundPredicate { bounds, .. } => Some(bounds),
1237            WherePredicate::RegionPredicate { bounds, .. } => Some(bounds),
1238            _ => None,
1239        }
1240    }
1241}
1242
1243#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1244pub(crate) enum GenericParamDefKind {
1245    Lifetime { outlives: ThinVec<Lifetime> },
1246    Type { bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
1247    // Option<Box<String>> makes this type smaller than `Option<String>` would.
1248    Const { ty: Box<Type>, default: Option<Box<String>> },
1249}
1250
1251impl GenericParamDefKind {
1252    pub(crate) fn is_type(&self) -> bool {
1253        matches!(self, GenericParamDefKind::Type { .. })
1254    }
1255}
1256
1257#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1258pub(crate) struct GenericParamDef {
1259    pub(crate) name: Symbol,
1260    pub(crate) def_id: DefId,
1261    pub(crate) kind: GenericParamDefKind,
1262}
1263
1264impl GenericParamDef {
1265    pub(crate) fn lifetime(def_id: DefId, name: Symbol) -> Self {
1266        Self { name, def_id, kind: GenericParamDefKind::Lifetime { outlives: ThinVec::new() } }
1267    }
1268
1269    pub(crate) fn is_synthetic_param(&self) -> bool {
1270        match self.kind {
1271            GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
1272            GenericParamDefKind::Type { synthetic, .. } => synthetic,
1273        }
1274    }
1275
1276    pub(crate) fn is_type(&self) -> bool {
1277        self.kind.is_type()
1278    }
1279
1280    pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1281        match self.kind {
1282            GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1283            _ => None,
1284        }
1285    }
1286}
1287
1288// maybe use a Generic enum and use Vec<Generic>?
1289#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
1290pub(crate) struct Generics {
1291    pub(crate) params: ThinVec<GenericParamDef>,
1292    pub(crate) where_predicates: ThinVec<WherePredicate>,
1293}
1294
1295impl Generics {
1296    pub(crate) fn is_empty(&self) -> bool {
1297        self.params.is_empty() && self.where_predicates.is_empty()
1298    }
1299}
1300
1301#[derive(Clone, Debug)]
1302pub(crate) struct Function {
1303    pub(crate) decl: FnDecl,
1304    pub(crate) generics: Generics,
1305}
1306
1307#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1308pub(crate) struct FnDecl {
1309    pub(crate) inputs: Vec<Parameter>,
1310    pub(crate) output: Type,
1311    pub(crate) c_variadic: bool,
1312}
1313
1314impl FnDecl {
1315    pub(crate) fn receiver_type(&self) -> Option<&Type> {
1316        self.inputs.first().and_then(|v| v.to_receiver())
1317    }
1318}
1319
1320/// A function parameter.
1321#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1322pub(crate) struct Parameter {
1323    pub(crate) name: Option<Symbol>,
1324    pub(crate) type_: Type,
1325    /// This field is used to represent "const" arguments from the `rustc_legacy_const_generics`
1326    /// feature. More information in <https://github.com/rust-lang/rust/issues/83167>.
1327    pub(crate) is_const: bool,
1328    /// Flags whether this parameter is actually a splat (e.g., `#[rustc_splat]`).
1329    /// Refer to <github.com/rust-lang/rust/issues/153629>
1330    pub(crate) is_splat: bool,
1331}
1332
1333impl Parameter {
1334    pub(crate) fn to_receiver(&self) -> Option<&Type> {
1335        if self.name == Some(kw::SelfLower) { Some(&self.type_) } else { None }
1336    }
1337}
1338
1339#[derive(Clone, Debug)]
1340pub(crate) struct Trait {
1341    pub(crate) def_id: DefId,
1342    pub(crate) items: Vec<Item>,
1343    pub(crate) generics: Generics,
1344    pub(crate) bounds: Vec<GenericBound>,
1345}
1346
1347impl Trait {
1348    pub(crate) fn is_auto(&self, tcx: TyCtxt<'_>) -> bool {
1349        tcx.trait_is_auto(self.def_id)
1350    }
1351    pub(crate) fn is_notable_trait(&self, tcx: TyCtxt<'_>) -> bool {
1352        tcx.is_doc_notable_trait(self.def_id)
1353    }
1354    pub(crate) fn safety(&self, tcx: TyCtxt<'_>) -> hir::Safety {
1355        tcx.trait_def(self.def_id).safety
1356    }
1357    pub(crate) fn is_dyn_compatible(&self, tcx: TyCtxt<'_>) -> bool {
1358        tcx.is_dyn_compatible(self.def_id)
1359    }
1360    pub(crate) fn is_deprecated(&self, tcx: TyCtxt<'_>) -> bool {
1361        tcx.lookup_deprecation(self.def_id).is_some_and(|deprecation| deprecation.is_in_effect())
1362    }
1363}
1364
1365#[derive(Clone, Debug)]
1366pub(crate) struct TraitAlias {
1367    pub(crate) generics: Generics,
1368    pub(crate) bounds: Vec<GenericBound>,
1369}
1370
1371/// A trait reference, which may have higher ranked lifetimes.
1372#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1373pub(crate) struct PolyTrait {
1374    pub(crate) trait_: Path,
1375    pub(crate) generic_params: Vec<GenericParamDef>,
1376}
1377
1378/// Rustdoc's representation of types, mostly based on the [`hir::Ty`].
1379#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1380pub(crate) enum Type {
1381    /// A named type, which could be a trait.
1382    ///
1383    /// This is mostly Rustdoc's version of [`hir::Path`].
1384    /// It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics.
1385    Path {
1386        path: Path,
1387    },
1388    /// A `dyn Trait` object: `dyn for<'a> Trait<'a> + Send + 'static`
1389    DynTrait(Vec<PolyTrait>, Option<Lifetime>),
1390    /// A type parameter.
1391    Generic(Symbol),
1392    /// The `Self` type.
1393    SelfTy,
1394    /// A primitive (aka, builtin) type.
1395    Primitive(PrimitiveType),
1396    /// A function pointer: `extern "ABI" fn(...) -> ...`
1397    BareFunction(Box<BareFunctionDecl>),
1398    /// A tuple type: `(i32, &str)`.
1399    Tuple(Vec<Type>),
1400    /// A slice type (does *not* include the `&`): `[i32]`
1401    Slice(Box<Type>),
1402    /// An array type.
1403    ///
1404    /// The `String` field is a stringified version of the array's length parameter.
1405    Array(Box<Type>, Box<str>),
1406    Pat(Box<Type>, Box<str>),
1407    FieldOf(Box<Type>, Box<str>),
1408    /// A raw pointer type: `*const i32`, `*mut i32`
1409    RawPointer(Mutability, Box<Type>),
1410    /// A reference type: `&i32`, `&'a mut Foo`
1411    BorrowedRef {
1412        lifetime: Option<Lifetime>,
1413        mutability: Mutability,
1414        type_: Box<Type>,
1415    },
1416
1417    /// A qualified path to an associated item: `<Type as Trait>::Name`
1418    QPath(Box<QPathData>),
1419
1420    /// A type that is inferred: `_`
1421    Infer,
1422
1423    /// An `impl Trait`: `impl TraitA + TraitB + ...`
1424    ImplTrait(Vec<GenericBound>),
1425
1426    UnsafeBinder(Box<UnsafeBinderTy>),
1427}
1428
1429impl Type {
1430    /// When comparing types for equality, it can help to ignore `&` wrapping.
1431    pub(crate) fn without_borrowed_ref(&self) -> &Type {
1432        let mut result = self;
1433        while let Type::BorrowedRef { type_, .. } = result {
1434            result = type_;
1435        }
1436        result
1437    }
1438
1439    pub(crate) fn is_borrowed_ref(&self) -> bool {
1440        matches!(self, Type::BorrowedRef { .. })
1441    }
1442
1443    fn is_type_alias(&self) -> bool {
1444        matches!(self, Type::Path { path: Path { res: Res::Def(DefKind::TyAlias, _), .. } })
1445    }
1446
1447    /// Check if this type is a subtype of another type for documentation purposes.
1448    ///
1449    /// This is different from `Eq`, because it knows that things like
1450    /// `Infer` and generics have special subtyping rules.
1451    ///
1452    /// This relation is not commutative when generics are involved:
1453    ///
1454    /// ```ignore(private)
1455    /// # // see types/tests.rs:is_same_generic for the real test
1456    /// use rustdoc::format::cache::Cache;
1457    /// use rustdoc::clean::types::{Type, PrimitiveType};
1458    /// let cache = Cache::new(false);
1459    /// let generic = Type::Generic(Symbol::intern("T"));
1460    /// let unit = Type::Primitive(PrimitiveType::Unit);
1461    /// assert!(!generic.is_doc_subtype_of(&unit, &cache));
1462    /// assert!(unit.is_doc_subtype_of(&generic, &cache));
1463    /// ```
1464    ///
1465    /// An owned type is also the same as its borrowed variants (this is commutative),
1466    /// but `&T` is not the same as `&mut T`.
1467    pub(crate) fn is_doc_subtype_of(&self, other: &Self, cache: &Cache) -> bool {
1468        // Strip the references so that it can compare the actual types, unless both are references.
1469        // If both are references, leave them alone and compare the mutabilities later.
1470        let (self_cleared, other_cleared) = if !self.is_borrowed_ref() || !other.is_borrowed_ref() {
1471            (self.without_borrowed_ref(), other.without_borrowed_ref())
1472        } else {
1473            (self, other)
1474        };
1475
1476        // FIXME: `Cache` does not have the data required to unwrap type aliases,
1477        // so we just assume they are equal.
1478        // This is only remotely acceptable because we were previously
1479        // assuming all types were equal when used
1480        // as a generic parameter of a type in `Deref::Target`.
1481        if self_cleared.is_type_alias() || other_cleared.is_type_alias() {
1482            return true;
1483        }
1484
1485        match (self_cleared, other_cleared) {
1486            // Recursive cases.
1487            (Type::Tuple(a), Type::Tuple(b)) => {
1488                a.iter().eq_by(b, |a, b| a.is_doc_subtype_of(b, cache))
1489            }
1490            (Type::Slice(a), Type::Slice(b)) => a.is_doc_subtype_of(b, cache),
1491            (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_doc_subtype_of(b, cache),
1492            (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
1493                mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache)
1494            }
1495            (
1496                Type::BorrowedRef { mutability, type_, .. },
1497                Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
1498            ) => mutability == b_mutability && type_.is_doc_subtype_of(b_type_, cache),
1499            // Placeholders are equal to all other types.
1500            (Type::Infer, _) | (_, Type::Infer) => true,
1501            // Generics match everything on the right, but not on the left.
1502            // If both sides are generic, this returns true.
1503            (_, Type::Generic(_)) => true,
1504            (Type::Generic(_), _) => false,
1505            // `Self` only matches itself.
1506            (Type::SelfTy, Type::SelfTy) => true,
1507            // Paths account for both the path itself and its generics.
1508            (Type::Path { path: a }, Type::Path { path: b }) => {
1509                a.def_id() == b.def_id()
1510                    && a.generics()
1511                        .zip(b.generics())
1512                        .map(|(ag, bg)| ag.zip(bg).all(|(at, bt)| at.is_doc_subtype_of(bt, cache)))
1513                        .unwrap_or(true)
1514            }
1515            // Other cases, such as primitives, just use recursion.
1516            (a, b) => a
1517                .def_id(cache)
1518                .and_then(|a| Some((a, b.def_id(cache)?)))
1519                .map(|(a, b)| a == b)
1520                .unwrap_or(false),
1521        }
1522    }
1523
1524    pub(crate) fn primitive_type(&self) -> Option<PrimitiveType> {
1525        match *self {
1526            Primitive(p) | BorrowedRef { type_: Primitive(p), .. } => Some(p),
1527            Slice(..) | BorrowedRef { type_: Slice(..), .. } => Some(PrimitiveType::Slice),
1528            Array(..) | BorrowedRef { type_: Array(..), .. } => Some(PrimitiveType::Array),
1529            Tuple(ref tys) => {
1530                if tys.is_empty() {
1531                    Some(PrimitiveType::Unit)
1532                } else {
1533                    Some(PrimitiveType::Tuple)
1534                }
1535            }
1536            RawPointer(..) => Some(PrimitiveType::RawPointer),
1537            BareFunction(..) => Some(PrimitiveType::Fn),
1538            _ => None,
1539        }
1540    }
1541
1542    /// Returns the sugared return type for an async function.
1543    ///
1544    /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
1545    /// will return `i32`.
1546    ///
1547    /// # Panics
1548    ///
1549    /// This function will panic if the return type does not match the expected sugaring for async
1550    /// functions.
1551    pub(crate) fn sugared_async_return_type(self) -> Type {
1552        if let Type::ImplTrait(mut v) = self
1553            && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = v.pop()
1554            && let Some(segment) = trait_.segments.pop()
1555            && let GenericArgs::AngleBracketed { mut constraints, .. } = segment.args
1556            && let Some(constraint) = constraints.pop()
1557            && let AssocItemConstraintKind::Equality { term } = constraint.kind
1558            && let Term::Type(ty) = term
1559        {
1560            ty
1561        } else {
1562            panic!("unexpected async fn return type")
1563        }
1564    }
1565
1566    /// Checks if this is a `T::Name` path for an associated type.
1567    pub(crate) fn is_assoc_ty(&self) -> bool {
1568        match self {
1569            Type::Path { path, .. } => path.is_assoc_ty(),
1570            _ => false,
1571        }
1572    }
1573
1574    pub(crate) fn is_self_type(&self) -> bool {
1575        matches!(*self, Type::SelfTy)
1576    }
1577
1578    pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
1579        match self {
1580            Type::Path { path, .. } => path.generic_args(),
1581            _ => None,
1582        }
1583    }
1584
1585    pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
1586        match self {
1587            Type::Path { path, .. } => path.generics(),
1588            _ => None,
1589        }
1590    }
1591
1592    pub(crate) fn is_full_generic(&self) -> bool {
1593        matches!(self, Type::Generic(_))
1594    }
1595
1596    pub(crate) fn is_unit(&self) -> bool {
1597        matches!(self, Type::Tuple(v) if v.is_empty())
1598    }
1599
1600    /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s.
1601    ///
1602    /// [clean]: crate::clean
1603    pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
1604        let t: PrimitiveType = match self {
1605            Type::Path { path } => return Some(path.def_id()),
1606            DynTrait(bounds, _) => return bounds.first().map(|b| b.trait_.def_id()),
1607            Primitive(p) => return cache.primitive_locations.get(p).cloned(),
1608            BorrowedRef { type_: Generic(..), .. } => PrimitiveType::Reference,
1609            BorrowedRef { type_, .. } => return type_.def_id(cache),
1610            Tuple(tys) => {
1611                if tys.is_empty() {
1612                    PrimitiveType::Unit
1613                } else {
1614                    PrimitiveType::Tuple
1615                }
1616            }
1617            BareFunction(..) => PrimitiveType::Fn,
1618            Slice(..) => PrimitiveType::Slice,
1619            Array(..) => PrimitiveType::Array,
1620            Type::Pat(..) => PrimitiveType::Pat,
1621            Type::FieldOf(..) => PrimitiveType::FieldOf,
1622            RawPointer(..) => PrimitiveType::RawPointer,
1623            QPath(QPathData { self_type, .. }) => return self_type.def_id(cache),
1624            Generic(_) | SelfTy | Infer | ImplTrait(_) | UnsafeBinder(_) => return None,
1625        };
1626        Primitive(t).def_id(cache)
1627    }
1628}
1629
1630#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1631pub(crate) struct QPathData {
1632    pub assoc: PathSegment,
1633    pub self_type: Type,
1634    /// FIXME: compute this field on demand.
1635    pub should_fully_qualify: bool,
1636    pub trait_: Option<Path>,
1637}
1638
1639/// A primitive (aka, builtin) type.
1640///
1641/// This represents things like `i32`, `str`, etc.
1642///
1643/// N.B. This has to be different from [`hir::PrimTy`] because it also includes types that aren't
1644/// paths, like [`Self::Unit`].
1645#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1646pub(crate) enum PrimitiveType {
1647    Isize,
1648    I8,
1649    I16,
1650    I32,
1651    I64,
1652    I128,
1653    Usize,
1654    U8,
1655    U16,
1656    U32,
1657    U64,
1658    U128,
1659    F16,
1660    F32,
1661    F64,
1662    F128,
1663    Char,
1664    Bool,
1665    Str,
1666    Slice,
1667    Array,
1668    Pat,
1669    FieldOf,
1670    Tuple,
1671    Unit,
1672    RawPointer,
1673    Reference,
1674    Fn,
1675    Never,
1676}
1677
1678type SimplifiedTypes = FxIndexMap<PrimitiveType, ArrayVec<SimplifiedType, 3>>;
1679impl PrimitiveType {
1680    pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1681        use ast::{FloatTy, IntTy, UintTy};
1682        match prim {
1683            hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1684            hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1685            hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1686            hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1687            hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1688            hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1689            hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1690            hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1691            hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1692            hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1693            hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1694            hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1695            hir::PrimTy::Float(FloatTy::F16) => PrimitiveType::F16,
1696            hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1697            hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1698            hir::PrimTy::Float(FloatTy::F128) => PrimitiveType::F128,
1699            hir::PrimTy::Str => PrimitiveType::Str,
1700            hir::PrimTy::Bool => PrimitiveType::Bool,
1701            hir::PrimTy::Char => PrimitiveType::Char,
1702        }
1703    }
1704
1705    pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1706        match s {
1707            sym::isize => Some(PrimitiveType::Isize),
1708            sym::i8 => Some(PrimitiveType::I8),
1709            sym::i16 => Some(PrimitiveType::I16),
1710            sym::i32 => Some(PrimitiveType::I32),
1711            sym::i64 => Some(PrimitiveType::I64),
1712            sym::i128 => Some(PrimitiveType::I128),
1713            sym::usize => Some(PrimitiveType::Usize),
1714            sym::u8 => Some(PrimitiveType::U8),
1715            sym::u16 => Some(PrimitiveType::U16),
1716            sym::u32 => Some(PrimitiveType::U32),
1717            sym::u64 => Some(PrimitiveType::U64),
1718            sym::u128 => Some(PrimitiveType::U128),
1719            sym::bool => Some(PrimitiveType::Bool),
1720            sym::char => Some(PrimitiveType::Char),
1721            sym::str => Some(PrimitiveType::Str),
1722            sym::f16 => Some(PrimitiveType::F16),
1723            sym::f32 => Some(PrimitiveType::F32),
1724            sym::f64 => Some(PrimitiveType::F64),
1725            sym::f128 => Some(PrimitiveType::F128),
1726            sym::array => Some(PrimitiveType::Array),
1727            sym::slice => Some(PrimitiveType::Slice),
1728            sym::tuple => Some(PrimitiveType::Tuple),
1729            sym::unit => Some(PrimitiveType::Unit),
1730            sym::pointer => Some(PrimitiveType::RawPointer),
1731            sym::reference => Some(PrimitiveType::Reference),
1732            kw::Fn => Some(PrimitiveType::Fn),
1733            sym::never => Some(PrimitiveType::Never),
1734            _ => None,
1735        }
1736    }
1737
1738    pub(crate) fn from_ty(ty: Ty<'_>) -> Option<Self> {
1739        match ty.kind() {
1740            ty::Array(..) => Some(Self::Array),
1741            ty::Bool => Some(Self::Bool),
1742            ty::Char => Some(Self::Char),
1743            ty::FnDef(..) | ty::FnPtr(..) => Some(Self::Fn),
1744            ty::Int(int) => Some(Self::from(*int)),
1745            ty::Uint(uint) => Some(Self::from(*uint)),
1746            ty::Float(float) => Some(Self::from(*float)),
1747            ty::Never => Some(Self::Never),
1748            ty::Pat(..) => Some(Self::Pat),
1749            ty::RawPtr(..) => Some(Self::RawPointer),
1750            ty::Ref(..) => Some(Self::Reference),
1751            ty::Slice(..) => Some(Self::Slice),
1752            ty::Str => Some(Self::Str),
1753            ty::Tuple(elems) if elems.is_empty() => Some(Self::Unit),
1754            ty::Tuple(_) => Some(Self::Tuple),
1755            ty::Adt(..)
1756            | ty::Alias(_, ..)
1757            | ty::Bound(..)
1758            | ty::Closure(..)
1759            | ty::Coroutine(..)
1760            | ty::CoroutineClosure(..)
1761            | ty::CoroutineWitness(..)
1762            | ty::Dynamic(..)
1763            | ty::Error(..)
1764            | ty::Foreign(..)
1765            | ty::Infer(..)
1766            | ty::Param(..)
1767            | ty::Placeholder(..)
1768            | ty::UnsafeBinder(..) => None,
1769        }
1770    }
1771
1772    pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
1773        use PrimitiveType::*;
1774        use ty::{FloatTy, IntTy, UintTy};
1775        static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
1776
1777        let single = |x| iter::once(x).collect();
1778        CELL.get_or_init(move || {
1779            map! {
1780                Isize => single(SimplifiedType::Int(IntTy::Isize)),
1781                I8 => single(SimplifiedType::Int(IntTy::I8)),
1782                I16 => single(SimplifiedType::Int(IntTy::I16)),
1783                I32 => single(SimplifiedType::Int(IntTy::I32)),
1784                I64 => single(SimplifiedType::Int(IntTy::I64)),
1785                I128 => single(SimplifiedType::Int(IntTy::I128)),
1786                Usize => single(SimplifiedType::Uint(UintTy::Usize)),
1787                U8 => single(SimplifiedType::Uint(UintTy::U8)),
1788                U16 => single(SimplifiedType::Uint(UintTy::U16)),
1789                U32 => single(SimplifiedType::Uint(UintTy::U32)),
1790                U64 => single(SimplifiedType::Uint(UintTy::U64)),
1791                U128 => single(SimplifiedType::Uint(UintTy::U128)),
1792                F16 => single(SimplifiedType::Float(FloatTy::F16)),
1793                F32 => single(SimplifiedType::Float(FloatTy::F32)),
1794                F64 => single(SimplifiedType::Float(FloatTy::F64)),
1795                F128 => single(SimplifiedType::Float(FloatTy::F128)),
1796                Str => single(SimplifiedType::Str),
1797                Bool => single(SimplifiedType::Bool),
1798                Char => single(SimplifiedType::Char),
1799                Array => single(SimplifiedType::Array),
1800                Slice => single(SimplifiedType::Slice),
1801                // FIXME: If we ever add an inherent impl for tuples
1802                // with different lengths, they won't show in rustdoc.
1803                //
1804                // Either manually update this arrayvec at this point
1805                // or start with a more complex refactoring.
1806                Tuple => [SimplifiedType::Tuple(1), SimplifiedType::Tuple(2), SimplifiedType::Tuple(3)].into(),
1807                Unit => single(SimplifiedType::Tuple(0)),
1808                RawPointer => [SimplifiedType::Ptr(Mutability::Not), SimplifiedType::Ptr(Mutability::Mut)].into_iter().collect(),
1809                Reference => [SimplifiedType::Ref(Mutability::Not), SimplifiedType::Ref(Mutability::Mut)].into_iter().collect(),
1810                // FIXME: This will be wrong if we ever add inherent impls
1811                // for function pointers.
1812                Fn => single(SimplifiedType::Function(1)),
1813                Never => single(SimplifiedType::Never),
1814            }
1815        })
1816    }
1817
1818    pub(crate) fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = DefId> + 'tcx {
1819        Self::simplified_types()
1820            .get(self)
1821            .into_iter()
1822            .flatten()
1823            .flat_map(move |&simp| tcx.incoherent_impls(simp).iter())
1824            .copied()
1825    }
1826
1827    pub(crate) fn as_sym(&self) -> Symbol {
1828        use PrimitiveType::*;
1829        match self {
1830            Isize => sym::isize,
1831            I8 => sym::i8,
1832            I16 => sym::i16,
1833            I32 => sym::i32,
1834            I64 => sym::i64,
1835            I128 => sym::i128,
1836            Usize => sym::usize,
1837            U8 => sym::u8,
1838            U16 => sym::u16,
1839            U32 => sym::u32,
1840            U64 => sym::u64,
1841            U128 => sym::u128,
1842            F16 => sym::f16,
1843            F32 => sym::f32,
1844            F64 => sym::f64,
1845            F128 => sym::f128,
1846            Str => sym::str,
1847            Bool => sym::bool,
1848            Char => sym::char,
1849            Array => sym::array,
1850            Pat => sym::pat,
1851            FieldOf => sym::field_of,
1852            Slice => sym::slice,
1853            Tuple => sym::tuple,
1854            Unit => sym::unit,
1855            RawPointer => sym::pointer,
1856            Reference => sym::reference,
1857            Fn => kw::Fn,
1858            Never => sym::never,
1859        }
1860    }
1861
1862    /// Returns the DefId of the module with `rustc_doc_primitive` for this primitive type.
1863    /// Panics if there is no such module.
1864    ///
1865    /// This gives precedence to primitives defined in the current crate, and deprioritizes
1866    /// primitives defined in `core`,
1867    /// but otherwise, if multiple crates define the same primitive, there is no guarantee of which
1868    /// will be picked.
1869    ///
1870    /// In particular, if a crate depends on both `std` and another crate that also defines
1871    /// `rustc_doc_primitive`, then it's entirely random whether `std` or the other crate is picked.
1872    /// (no_std crates are usually fine unless multiple dependencies define a primitive.)
1873    pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxIndexMap<PrimitiveType, DefId> {
1874        fn as_primitive(def_id: DefId, tcx: TyCtxt<'_>) -> Option<PrimitiveType> {
1875            let (attr_span, prim_sym) = find_attr!(
1876                tcx, def_id,
1877                RustcDocPrimitive(span, prim) => (*span, *prim)
1878            )?;
1879            let Some(prim) = PrimitiveType::from_symbol(prim_sym) else {
1880                span_bug!(attr_span, "primitive `{prim_sym}` is not a member of `PrimitiveType`");
1881            };
1882            Some(prim)
1883        }
1884
1885        static PRIMITIVE_LOCATIONS: OnceCell<FxIndexMap<PrimitiveType, DefId>> = OnceCell::new();
1886        PRIMITIVE_LOCATIONS.get_or_init(|| {
1887            let mut primitive_locations = FxIndexMap::default();
1888            // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate.
1889            // This is a degenerate case that I don't plan to support.
1890
1891            let mut ids = tcx.all_fake_doc_items(()).clone();
1892
1893            // HACK: Primitives are unhygienically duplicated by `include!`.
1894            // Sort them with core first, so that if std is present in the crate graph,
1895            // core's items are overridden and we link to std preferentially.
1896            ids.iter_mut().partition_in_place(|id| tcx.crate_name(id.krate) == sym::core);
1897            for def_id in ids {
1898                if let Some(prim) = as_primitive(def_id, tcx) {
1899                    primitive_locations.insert(prim, def_id);
1900                }
1901            }
1902
1903            primitive_locations
1904        })
1905    }
1906}
1907
1908impl From<ty::IntTy> for PrimitiveType {
1909    fn from(int_ty: ty::IntTy) -> PrimitiveType {
1910        match int_ty {
1911            ty::IntTy::Isize => PrimitiveType::Isize,
1912            ty::IntTy::I8 => PrimitiveType::I8,
1913            ty::IntTy::I16 => PrimitiveType::I16,
1914            ty::IntTy::I32 => PrimitiveType::I32,
1915            ty::IntTy::I64 => PrimitiveType::I64,
1916            ty::IntTy::I128 => PrimitiveType::I128,
1917        }
1918    }
1919}
1920
1921impl From<ty::UintTy> for PrimitiveType {
1922    fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1923        match uint_ty {
1924            ty::UintTy::Usize => PrimitiveType::Usize,
1925            ty::UintTy::U8 => PrimitiveType::U8,
1926            ty::UintTy::U16 => PrimitiveType::U16,
1927            ty::UintTy::U32 => PrimitiveType::U32,
1928            ty::UintTy::U64 => PrimitiveType::U64,
1929            ty::UintTy::U128 => PrimitiveType::U128,
1930        }
1931    }
1932}
1933
1934impl From<ty::FloatTy> for PrimitiveType {
1935    fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1936        match float_ty {
1937            ty::FloatTy::F16 => PrimitiveType::F16,
1938            ty::FloatTy::F32 => PrimitiveType::F32,
1939            ty::FloatTy::F64 => PrimitiveType::F64,
1940            ty::FloatTy::F128 => PrimitiveType::F128,
1941        }
1942    }
1943}
1944
1945impl From<hir::PrimTy> for PrimitiveType {
1946    fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1947        match prim_ty {
1948            hir::PrimTy::Int(int_ty) => int_ty.into(),
1949            hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1950            hir::PrimTy::Float(float_ty) => float_ty.into(),
1951            hir::PrimTy::Str => PrimitiveType::Str,
1952            hir::PrimTy::Bool => PrimitiveType::Bool,
1953            hir::PrimTy::Char => PrimitiveType::Char,
1954        }
1955    }
1956}
1957
1958#[derive(Clone, Debug)]
1959pub(crate) struct Struct {
1960    pub(crate) ctor_kind: Option<CtorKind>,
1961    pub(crate) generics: Generics,
1962    pub(crate) fields: ThinVec<Item>,
1963}
1964
1965impl Struct {
1966    pub(crate) fn has_stripped_entries(&self) -> bool {
1967        self.fields.iter().any(|f| f.is_stripped())
1968    }
1969}
1970
1971#[derive(Clone, Debug)]
1972pub(crate) struct Union {
1973    pub(crate) generics: Generics,
1974    pub(crate) fields: Vec<Item>,
1975}
1976
1977impl Union {
1978    pub(crate) fn has_stripped_entries(&self) -> bool {
1979        self.fields.iter().any(|f| f.is_stripped())
1980    }
1981}
1982
1983/// This is a more limited form of the standard Struct, different in that
1984/// it lacks the things most items have (name, id, parameterization). Found
1985/// only as a variant in an enum.
1986#[derive(Clone, Debug)]
1987pub(crate) struct VariantStruct {
1988    pub(crate) fields: ThinVec<Item>,
1989}
1990
1991impl VariantStruct {
1992    pub(crate) fn has_stripped_entries(&self) -> bool {
1993        self.fields.iter().any(|f| f.is_stripped())
1994    }
1995}
1996
1997#[derive(Clone, Debug)]
1998pub(crate) struct Enum {
1999    pub(crate) variants: IndexVec<VariantIdx, Item>,
2000    pub(crate) generics: Generics,
2001}
2002
2003impl Enum {
2004    pub(crate) fn has_stripped_entries(&self) -> bool {
2005        self.variants.iter().any(|f| f.is_stripped())
2006    }
2007
2008    pub(crate) fn non_stripped_variants(&self) -> impl Iterator<Item = &Item> {
2009        self.variants.iter().filter(|v| !v.is_stripped())
2010    }
2011}
2012
2013#[derive(Clone, Debug)]
2014pub(crate) struct Variant {
2015    pub kind: VariantKind,
2016    pub discriminant: Option<Discriminant>,
2017}
2018
2019#[derive(Clone, Debug)]
2020pub(crate) enum VariantKind {
2021    CLike,
2022    Tuple(ThinVec<Item>),
2023    Struct(VariantStruct),
2024}
2025
2026impl Variant {
2027    pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
2028        match &self.kind {
2029            VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()),
2030            VariantKind::CLike | VariantKind::Tuple(_) => None,
2031        }
2032    }
2033}
2034
2035#[derive(Clone, Debug)]
2036pub(crate) struct Discriminant {
2037    // In the case of cross crate re-exports, we don't have the necessary information
2038    // to reconstruct the expression of the discriminant, only the value.
2039    pub(super) expr: Option<BodyId>,
2040    pub(super) value: DefId,
2041}
2042
2043impl Discriminant {
2044    /// Will be `None` in the case of cross-crate reexports, and may be
2045    /// simplified
2046    pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
2047        self.expr
2048            .map(|body| rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body)))
2049    }
2050    pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String {
2051        print_evaluated_const(tcx, self.value, with_underscores, false).unwrap()
2052    }
2053}
2054
2055/// Small wrapper around [`rustc_span::Span`] that adds helper methods
2056/// and enforces calling [`rustc_span::Span::source_callsite()`].
2057#[derive(Copy, Clone, Debug)]
2058pub(crate) struct Span(rustc_span::Span);
2059
2060impl Span {
2061    /// Wraps a [`rustc_span::Span`]. In case this span is the result of a macro expansion, the
2062    /// span will be updated to point to the macro invocation instead of the macro definition.
2063    ///
2064    /// (See rust-lang/rust#39726)
2065    pub(crate) fn new(sp: rustc_span::Span) -> Self {
2066        Self(sp.source_callsite())
2067    }
2068
2069    pub(crate) fn inner(&self) -> rustc_span::Span {
2070        self.0
2071    }
2072
2073    pub(crate) fn filename(&self, sess: &Session) -> FileName {
2074        sess.source_map().span_to_filename(self.0)
2075    }
2076
2077    pub(crate) fn lo(&self, sess: &Session) -> Loc {
2078        sess.source_map().lookup_char_pos(self.0.lo())
2079    }
2080
2081    pub(crate) fn hi(&self, sess: &Session) -> Loc {
2082        sess.source_map().lookup_char_pos(self.0.hi())
2083    }
2084
2085    pub(crate) fn cnum(&self, sess: &Session) -> CrateNum {
2086        // FIXME: is there a time when the lo and hi crate would be different?
2087        self.lo(sess).file.cnum
2088    }
2089}
2090
2091#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2092pub(crate) struct Path {
2093    pub(crate) res: Res,
2094    pub(crate) segments: ThinVec<PathSegment>,
2095}
2096
2097impl Path {
2098    pub(crate) fn def_id(&self) -> DefId {
2099        self.res.def_id()
2100    }
2101
2102    pub(crate) fn last_opt(&self) -> Option<Symbol> {
2103        self.segments.last().map(|s| s.name)
2104    }
2105
2106    pub(crate) fn last(&self) -> Symbol {
2107        self.last_opt().expect("segments were empty")
2108    }
2109
2110    pub(crate) fn whole_name(&self) -> String {
2111        self.segments
2112            .iter()
2113            .map(|s| if s.name == kw::PathRoot { "" } else { s.name.as_str() })
2114            .intersperse("::")
2115            .collect()
2116    }
2117
2118    /// Checks if this is a `T::Name` path for an associated type.
2119    pub(crate) fn is_assoc_ty(&self) -> bool {
2120        match self.res {
2121            Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _)
2122                if self.segments.len() != 1 =>
2123            {
2124                true
2125            }
2126            Res::Def(DefKind::AssocTy, _) => true,
2127            _ => false,
2128        }
2129    }
2130
2131    pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
2132        self.segments.last().map(|seg| &seg.args)
2133    }
2134
2135    pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
2136        self.segments.last().and_then(|seg| {
2137            if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2138                Some(args.iter().filter_map(|arg| match arg {
2139                    GenericArg::Type(ty) => Some(ty),
2140                    _ => None,
2141                }))
2142            } else {
2143                None
2144            }
2145        })
2146    }
2147}
2148
2149#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2150pub(crate) enum GenericArg {
2151    Lifetime(Lifetime),
2152    Type(Type),
2153    Const(Box<ConstantKind>),
2154    Infer,
2155}
2156
2157impl GenericArg {
2158    pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
2159        if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2160    }
2161
2162    pub(crate) fn as_ty(&self) -> Option<&Type> {
2163        if let Self::Type(ty) = self { Some(ty) } else { None }
2164    }
2165}
2166
2167#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2168pub(crate) enum GenericArgs {
2169    /// `<args, constraints = ..>`
2170    AngleBracketed { args: ThinVec<GenericArg>, constraints: ThinVec<AssocItemConstraint> },
2171    /// `(inputs) -> output`
2172    Parenthesized { inputs: ThinVec<Type>, output: Option<Box<Type>> },
2173    /// `(..)`
2174    ReturnTypeNotation,
2175}
2176
2177impl GenericArgs {
2178    pub(crate) fn is_empty(&self) -> bool {
2179        match self {
2180            GenericArgs::AngleBracketed { args, constraints } => {
2181                args.is_empty() && constraints.is_empty()
2182            }
2183            GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
2184            GenericArgs::ReturnTypeNotation => false,
2185        }
2186    }
2187    pub(crate) fn constraints(&self) -> Box<dyn Iterator<Item = AssocItemConstraint> + '_> {
2188        match self {
2189            GenericArgs::AngleBracketed { constraints, .. } => {
2190                Box::new(constraints.iter().cloned())
2191            }
2192            GenericArgs::Parenthesized { output, .. } => Box::new(
2193                output
2194                    .as_ref()
2195                    .map(|ty| AssocItemConstraint {
2196                        assoc: PathSegment {
2197                            name: sym::Output,
2198                            args: GenericArgs::AngleBracketed {
2199                                args: ThinVec::new(),
2200                                constraints: ThinVec::new(),
2201                            },
2202                        },
2203                        kind: AssocItemConstraintKind::Equality {
2204                            term: Term::Type((**ty).clone()),
2205                        },
2206                    })
2207                    .into_iter(),
2208            ),
2209            GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2210        }
2211    }
2212}
2213
2214impl<'a> IntoIterator for &'a GenericArgs {
2215    type IntoIter = Box<dyn Iterator<Item = GenericArg> + 'a>;
2216    type Item = GenericArg;
2217    fn into_iter(self) -> Self::IntoIter {
2218        match self {
2219            GenericArgs::AngleBracketed { args, .. } => Box::new(args.iter().cloned()),
2220            GenericArgs::Parenthesized { inputs, .. } => {
2221                // FIXME: This isn't really right, since `Fn(A, B)` is `Fn<(A, B)>`
2222                Box::new(inputs.iter().cloned().map(GenericArg::Type))
2223            }
2224            GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
2225        }
2226    }
2227}
2228
2229#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2230pub(crate) struct PathSegment {
2231    pub(crate) name: Symbol,
2232    pub(crate) args: GenericArgs,
2233}
2234
2235#[derive(Clone, Debug)]
2236pub(crate) enum TypeAliasInnerType {
2237    Enum { variants: IndexVec<VariantIdx, Item>, is_non_exhaustive: bool },
2238    Union { fields: Vec<Item> },
2239    Struct { ctor_kind: Option<CtorKind>, fields: Vec<Item> },
2240}
2241
2242impl TypeAliasInnerType {
2243    fn has_stripped_entries(&self) -> Option<bool> {
2244        Some(match self {
2245            Self::Enum { variants, .. } => variants.iter().any(|v| v.is_stripped()),
2246            Self::Union { fields } | Self::Struct { fields, .. } => {
2247                fields.iter().any(|f| f.is_stripped())
2248            }
2249        })
2250    }
2251}
2252
2253#[derive(Clone, Debug)]
2254pub(crate) struct TypeAlias {
2255    pub(crate) type_: Type,
2256    pub(crate) generics: Generics,
2257    /// Inner `AdtDef` type, ie `type TyKind = IrTyKind<Adt, Ty>`,
2258    /// to be shown directly on the typedef page.
2259    pub(crate) inner_type: Option<TypeAliasInnerType>,
2260    /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
2261    /// alias instead of the final type. This will always have the final type, regardless of whether
2262    /// `type_` came from HIR or from metadata.
2263    ///
2264    /// If `item_type.is_none()`, `type_` is guaranteed to come from metadata (and therefore hold the
2265    /// final type).
2266    pub(crate) item_type: Option<Type>,
2267}
2268
2269#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2270pub(crate) struct BareFunctionDecl {
2271    pub(crate) safety: hir::Safety,
2272    pub(crate) generic_params: Vec<GenericParamDef>,
2273    pub(crate) decl: FnDecl,
2274    pub(crate) abi: ExternAbi,
2275}
2276
2277#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2278pub(crate) struct UnsafeBinderTy {
2279    pub(crate) generic_params: Vec<GenericParamDef>,
2280    pub(crate) ty: Type,
2281}
2282
2283#[derive(Clone, Debug)]
2284pub(crate) struct Static {
2285    pub(crate) type_: Box<Type>,
2286    pub(crate) mutability: Mutability,
2287    pub(crate) expr: Option<BodyId>,
2288}
2289
2290#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2291pub(crate) struct Constant {
2292    pub(crate) generics: Generics,
2293    pub(crate) kind: ConstantKind,
2294    pub(crate) type_: Type,
2295}
2296
2297#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2298pub(crate) enum Term {
2299    Type(Type),
2300    Constant(ConstantKind),
2301}
2302
2303impl Term {
2304    pub(crate) fn ty(&self) -> Option<&Type> {
2305        if let Term::Type(ty) = self { Some(ty) } else { None }
2306    }
2307}
2308
2309impl From<Type> for Term {
2310    fn from(ty: Type) -> Self {
2311        Term::Type(ty)
2312    }
2313}
2314
2315#[derive(Clone, PartialEq, Eq, Hash, Debug)]
2316pub(crate) enum ConstantKind {
2317    /// This is the wrapper around `ty::Const` for a non-local constant. Because it doesn't have a
2318    /// `BodyId`, we need to handle it on its own.
2319    ///
2320    /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified
2321    /// by a DefId. So this field must be different from `Extern`.
2322    TyConst { expr: Box<str> },
2323    /// A constant that is just a path (i.e., referring to a const param, free const, etc.).
2324    // FIXME: this is an unfortunate representation. rustdoc's logic around consts needs to be improved.
2325    Path { path: Box<str> },
2326    /// A constant (expression) that's not an item or associated item. These are usually found
2327    /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
2328    /// used to define explicit discriminant values for enum variants.
2329    Anonymous { body: BodyId },
2330    /// A constant from a different crate.
2331    Extern { def_id: DefId },
2332    /// `const FOO: u32 = ...;`
2333    Local { def_id: DefId, body: BodyId },
2334    /// An inferred constant as in `[10u8; _]`.
2335    Infer,
2336}
2337
2338impl ConstantKind {
2339    pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2340        match *self {
2341            ConstantKind::TyConst { ref expr } => expr.to_string(),
2342            ConstantKind::Path { ref path } => path.to_string(),
2343            ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2344            ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2345                rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body))
2346            }
2347            ConstantKind::Infer => "_".to_string(),
2348        }
2349    }
2350
2351    pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2352        match *self {
2353            ConstantKind::TyConst { .. }
2354            | ConstantKind::Path { .. }
2355            | ConstantKind::Anonymous { .. }
2356            | ConstantKind::Infer => None,
2357            ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2358                print_evaluated_const(tcx, def_id, true, true)
2359            }
2360        }
2361    }
2362
2363    pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2364        match *self {
2365            ConstantKind::TyConst { .. }
2366            | ConstantKind::Extern { .. }
2367            | ConstantKind::Path { .. }
2368            | ConstantKind::Infer => false,
2369            ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2370                is_literal_expr(tcx, body.hir_id)
2371            }
2372        }
2373    }
2374}
2375
2376#[derive(Clone, Debug)]
2377pub(crate) struct Impl {
2378    pub(crate) safety: hir::Safety,
2379    pub(crate) generics: Generics,
2380    pub(crate) trait_: Option<Path>,
2381    pub(crate) for_: Type,
2382    pub(crate) items: Vec<Item>,
2383    pub(crate) polarity: ty::ImplPolarity,
2384    pub(crate) kind: ImplKind,
2385    pub(crate) is_deprecated: bool,
2386}
2387
2388impl Impl {
2389    pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxIndexSet<Symbol> {
2390        self.trait_
2391            .as_ref()
2392            .map(|t| t.def_id())
2393            .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name()).collect())
2394            .unwrap_or_default()
2395    }
2396
2397    pub(crate) fn is_negative_trait_impl(&self) -> bool {
2398        matches!(self.polarity, ty::ImplPolarity::Negative)
2399    }
2400}
2401
2402#[derive(Clone, Debug)]
2403pub(crate) enum ImplKind {
2404    Normal,
2405    Auto,
2406    FakeVariadic,
2407    Blanket(Box<Type>),
2408}
2409
2410impl ImplKind {
2411    pub(crate) fn is_auto(&self) -> bool {
2412        matches!(self, ImplKind::Auto)
2413    }
2414
2415    pub(crate) fn is_blanket(&self) -> bool {
2416        matches!(self, ImplKind::Blanket(_))
2417    }
2418
2419    pub(crate) fn is_fake_variadic(&self) -> bool {
2420        matches!(self, ImplKind::FakeVariadic)
2421    }
2422
2423    pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
2424        match self {
2425            ImplKind::Blanket(ty) => Some(ty),
2426            _ => None,
2427        }
2428    }
2429}
2430
2431#[derive(Clone, Debug)]
2432pub(crate) struct Import {
2433    pub(crate) kind: ImportKind,
2434    /// The item being re-exported.
2435    pub(crate) source: ImportSource,
2436    pub(crate) should_be_displayed: bool,
2437}
2438
2439impl Import {
2440    pub(crate) fn new_simple(
2441        name: Symbol,
2442        source: ImportSource,
2443        should_be_displayed: bool,
2444    ) -> Self {
2445        Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2446    }
2447
2448    pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2449        Self { kind: ImportKind::Glob, source, should_be_displayed }
2450    }
2451
2452    pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool {
2453        self.source.did.is_some_and(|did| tcx.is_doc_hidden(did))
2454    }
2455}
2456
2457#[derive(Clone, Debug)]
2458pub(crate) enum ImportKind {
2459    // use source as str;
2460    Simple(Symbol),
2461    // use source::*;
2462    Glob,
2463}
2464
2465#[derive(Clone, Debug)]
2466pub(crate) struct ImportSource {
2467    pub(crate) path: Path,
2468    pub(crate) did: Option<DefId>,
2469}
2470
2471#[derive(Clone, Debug)]
2472pub(crate) struct Macro {
2473    pub(crate) source: String,
2474    /// Whether the macro was defined via `macro_rules!` as opposed to `macro`.
2475    pub(crate) macro_rules: bool,
2476}
2477
2478#[derive(Clone, Debug)]
2479pub(crate) struct ProcMacro {
2480    pub(crate) kind: MacroKind,
2481    pub(crate) helpers: Vec<Symbol>,
2482}
2483
2484/// A constraint on an associated item.
2485///
2486/// ### Examples
2487///
2488/// * the `A = Ty` and `B = Ty` in `Trait<A = Ty, B = Ty>`
2489/// * the `G<Ty> = Ty` in `Trait<G<Ty> = Ty>`
2490/// * the `A: Bound` in `Trait<A: Bound>`
2491/// * the `RetTy` in `Trait(ArgTy, ArgTy) -> RetTy`
2492/// * the `C = { Ct }` in `Trait<C = { Ct }>` (feature `associated_const_equality`)
2493/// * the `f(..): Bound` in `Trait<f(..): Bound>` (feature `return_type_notation`)
2494#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2495pub(crate) struct AssocItemConstraint {
2496    pub(crate) assoc: PathSegment,
2497    pub(crate) kind: AssocItemConstraintKind,
2498}
2499
2500/// The kind of [associated item constraint][AssocItemConstraint].
2501#[derive(Clone, PartialEq, Eq, Debug, Hash)]
2502pub(crate) enum AssocItemConstraintKind {
2503    Equality { term: Term },
2504    Bound { bounds: Vec<GenericBound> },
2505}
2506
2507// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
2508#[cfg(target_pointer_width = "64")]
2509mod size_asserts {
2510    use rustc_data_structures::static_assert_size;
2511
2512    use super::*;
2513    // tidy-alphabetical-start
2514    static_assert_size!(Crate, 16); // frequently moved by-value
2515    static_assert_size!(DocFragment, 48);
2516    static_assert_size!(GenericArg, 32);
2517    static_assert_size!(GenericArgs, 24);
2518    static_assert_size!(GenericParamDef, 40);
2519    static_assert_size!(Generics, 16);
2520    static_assert_size!(Item, 8);
2521    static_assert_size!(ItemInner, 144);
2522    static_assert_size!(ItemKind, 48);
2523    static_assert_size!(PathSegment, 32);
2524    static_assert_size!(Type, 32);
2525    // tidy-alphabetical-end
2526}