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