1 use std::cell::RefCell;
2 use std::default::Default;
4 use std::hash::{Hash, Hasher};
5 use std::iter::FromIterator;
6 use std::lazy::SyncOnceCell as OnceCell;
11 use arrayvec::ArrayVec;
13 use rustc_ast::util::comments::beautify_doc_string;
14 use rustc_ast::{self as ast, AttrStyle};
15 use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
16 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
17 use rustc_feature::UnstableFeatures;
19 use rustc_hir::def::{CtorKind, Res};
20 use rustc_hir::def_id::{CrateNum, DefId, DefIndex};
21 use rustc_hir::lang_items::LangItem;
22 use rustc_hir::{BodyId, Mutability};
23 use rustc_index::vec::IndexVec;
24 use rustc_middle::ty::{self, TyCtxt};
25 use rustc_session::Session;
26 use rustc_span::hygiene::MacroKind;
27 use rustc_span::source_map::DUMMY_SP;
28 use rustc_span::symbol::{kw, sym, Ident, Symbol, SymbolStr};
29 use rustc_span::{self, FileName, Loc};
30 use rustc_target::abi::VariantIdx;
31 use rustc_target::spec::abi::Abi;
33 use crate::clean::cfg::Cfg;
34 use crate::clean::external_path;
35 use crate::clean::inline;
36 use crate::clean::types::Type::{QPath, ResolvedPath};
37 use crate::clean::Clean;
38 use crate::core::DocContext;
39 use crate::formats::cache::Cache;
40 use crate::formats::item_type::ItemType;
41 use crate::html::render::cache::ExternalLocation;
44 use self::ItemKind::*;
48 thread_local!(crate static MAX_DEF_IDX: RefCell<FxHashMap<CrateNum, DefIndex>> = Default::default());
50 #[derive(Clone, Debug)]
53 crate version: Option<String>,
55 crate module: Option<Item>,
56 crate externs: Vec<(CrateNum, ExternalCrate)>,
57 crate primitives: Vec<(DefId, PrimitiveType)>,
58 // These are later on moved into `CACHEKEY`, leaving the map empty.
59 // Only here so that they can be filtered through the rustdoc passes.
60 crate external_traits: Rc<RefCell<FxHashMap<DefId, TraitWithExtraInfo>>>,
61 crate masked_crates: FxHashSet<CrateNum>,
62 crate collapsed: bool,
65 /// This struct is used to wrap additional information added by rustdoc on a `trait` item.
66 #[derive(Clone, Debug)]
67 crate struct TraitWithExtraInfo {
69 crate is_spotlight: bool,
72 #[derive(Clone, Debug)]
73 crate struct ExternalCrate {
76 crate attrs: Attributes,
77 crate primitives: Vec<(DefId, PrimitiveType)>,
78 crate keywords: Vec<(DefId, Symbol)>,
81 /// Anything with a source location and set of attributes and, optionally, a
82 /// name. That is, anything that can be documented. This doesn't correspond
83 /// directly to the AST's concept of an item; it's a strict superset.
88 /// Not everything has a name. E.g., impls
89 crate name: Option<Symbol>,
90 crate attrs: Box<Attributes>,
91 crate visibility: Visibility,
92 crate kind: Box<ItemKind>,
96 // `Item` is used a lot. Make sure it doesn't unintentionally get bigger.
97 #[cfg(target_arch = "x86_64")]
98 rustc_data_structures::static_assert_size!(Item, 48);
100 impl fmt::Debug for Item {
101 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
102 let def_id: &dyn fmt::Debug = if self.is_fake() { &"**FAKE**" } else { &self.def_id };
104 fmt.debug_struct("Item")
105 .field("source", &self.source)
106 .field("name", &self.name)
107 .field("attrs", &self.attrs)
108 .field("kind", &self.kind)
109 .field("visibility", &self.visibility)
110 .field("def_id", def_id)
116 crate fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx Stability> {
117 if self.is_fake() { None } else { tcx.lookup_stability(self.def_id) }
120 crate fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ConstStability> {
121 if self.is_fake() { None } else { tcx.lookup_const_stability(self.def_id) }
124 crate fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
125 if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id) }
128 /// Finds the `doc` attribute as a NameValue and returns the corresponding
130 crate fn doc_value(&self) -> Option<String> {
131 self.attrs.doc_value()
134 /// Convenience wrapper around [`Self::from_def_id_and_parts`] which converts
135 /// `hir_id` to a [`DefId`]
136 pub fn from_hir_id_and_parts(
138 name: Option<Symbol>,
140 cx: &mut DocContext<'_>,
142 Item::from_def_id_and_parts(cx.tcx.hir().local_def_id(hir_id).to_def_id(), name, kind, cx)
145 pub fn from_def_id_and_parts(
147 name: Option<Symbol>,
149 cx: &mut DocContext<'_>,
151 Self::from_def_id_and_attrs_and_parts(
155 box cx.tcx.get_attrs(def_id).clean(cx),
160 pub fn from_def_id_and_attrs_and_parts(
162 name: Option<Symbol>,
164 attrs: Box<Attributes>,
165 cx: &mut DocContext<'_>,
167 debug!("name={:?}, def_id={:?}", name, def_id);
169 // `span_if_local()` lies about functions and only gives the span of the function signature
170 let source = def_id.as_local().map_or_else(
171 || cx.tcx.def_span(def_id),
173 let hir = cx.tcx.hir();
174 hir.span_with_body(hir.local_def_id_to_hir_id(local))
182 source: source.clean(cx),
184 visibility: cx.tcx.visibility(def_id).clean(cx),
188 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
190 crate fn collapsed_doc_value(&self) -> Option<String> {
191 self.attrs.collapsed_doc_value()
194 crate fn links(&self, cache: &Cache) -> Vec<RenderedLink> {
195 self.attrs.links(&self.def_id.krate, cache)
198 crate fn is_crate(&self) -> bool {
201 StrippedItem(box ModuleItem(Module { is_crate: true, .. }))
202 | ModuleItem(Module { is_crate: true, .. })
205 crate fn is_mod(&self) -> bool {
206 self.type_() == ItemType::Module
208 crate fn is_trait(&self) -> bool {
209 self.type_() == ItemType::Trait
211 crate fn is_struct(&self) -> bool {
212 self.type_() == ItemType::Struct
214 crate fn is_enum(&self) -> bool {
215 self.type_() == ItemType::Enum
217 crate fn is_variant(&self) -> bool {
218 self.type_() == ItemType::Variant
220 crate fn is_associated_type(&self) -> bool {
221 self.type_() == ItemType::AssocType
223 crate fn is_associated_const(&self) -> bool {
224 self.type_() == ItemType::AssocConst
226 crate fn is_method(&self) -> bool {
227 self.type_() == ItemType::Method
229 crate fn is_ty_method(&self) -> bool {
230 self.type_() == ItemType::TyMethod
232 crate fn is_typedef(&self) -> bool {
233 self.type_() == ItemType::Typedef
235 crate fn is_primitive(&self) -> bool {
236 self.type_() == ItemType::Primitive
238 crate fn is_union(&self) -> bool {
239 self.type_() == ItemType::Union
241 crate fn is_import(&self) -> bool {
242 self.type_() == ItemType::Import
244 crate fn is_extern_crate(&self) -> bool {
245 self.type_() == ItemType::ExternCrate
247 crate fn is_keyword(&self) -> bool {
248 self.type_() == ItemType::Keyword
250 crate fn is_stripped(&self) -> bool {
252 StrippedItem(..) => true,
253 ImportItem(ref i) => !i.should_be_displayed,
257 crate fn has_stripped_fields(&self) -> Option<bool> {
259 StructItem(ref _struct) => Some(_struct.fields_stripped),
260 UnionItem(ref union) => Some(union.fields_stripped),
261 VariantItem(Variant::Struct(ref vstruct)) => Some(vstruct.fields_stripped),
266 crate fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
267 self.stability(tcx).as_ref().and_then(|ref s| {
268 let mut classes = Vec::with_capacity(2);
270 if s.level.is_unstable() {
271 classes.push("unstable");
274 // FIXME: what about non-staged API items that are deprecated?
275 if self.deprecation(tcx).is_some() {
276 classes.push("deprecated");
279 if !classes.is_empty() { Some(classes.join(" ")) } else { None }
283 crate fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
284 match self.stability(tcx)?.level {
285 StabilityLevel::Stable { since, .. } => Some(since.as_str()),
286 StabilityLevel::Unstable { .. } => None,
290 crate fn const_stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
291 match self.const_stability(tcx)?.level {
292 StabilityLevel::Stable { since, .. } => Some(since.as_str()),
293 StabilityLevel::Unstable { .. } => None,
297 crate fn is_non_exhaustive(&self) -> bool {
298 self.attrs.other_attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
301 /// Returns a documentation-level item type from the item.
302 crate fn type_(&self) -> ItemType {
306 crate fn is_default(&self) -> bool {
308 ItemKind::MethodItem(_, Some(defaultness)) => {
309 defaultness.has_value() && !defaultness.is_final()
315 /// See the documentation for [`next_def_id()`].
317 /// [`next_def_id()`]: DocContext::next_def_id()
318 crate fn is_fake(&self) -> bool {
319 MAX_DEF_IDX.with(|m| {
320 m.borrow().get(&self.def_id.krate).map(|&idx| idx <= self.def_id.index).unwrap_or(false)
325 #[derive(Clone, Debug)]
326 crate enum ItemKind {
327 ExternCrateItem(Symbol, Option<Symbol>),
332 FunctionItem(Function),
334 TypedefItem(Typedef, bool /* is associated type */),
335 OpaqueTyItem(OpaqueTy),
337 ConstantItem(Constant),
339 TraitAliasItem(TraitAlias),
341 /// A method signature only. Used for required methods in traits (ie,
342 /// non-default-methods).
343 TyMethodItem(Function),
344 /// A method with a body.
345 MethodItem(Function, Option<hir::Defaultness>),
346 StructFieldItem(Type),
347 VariantItem(Variant),
348 /// `fn`s from an extern block
349 ForeignFunctionItem(Function),
350 /// `static`s from an extern block
351 ForeignStaticItem(Static),
352 /// `type`s from an extern block
355 ProcMacroItem(ProcMacro),
356 PrimitiveItem(PrimitiveType),
357 AssocConstItem(Type, Option<String>),
358 /// An associated item in a trait or trait impl.
360 /// The bounds may be non-empty if there is a `where` clause.
361 /// The `Option<Type>` is the default concrete type (e.g. `trait Trait { type Target = usize; }`)
362 AssocTypeItem(Vec<GenericBound>, Option<Type>),
363 /// An item that has been stripped by a rustdoc pass
364 StrippedItem(Box<ItemKind>),
369 /// Some items contain others such as structs (for their fields) and Enums
370 /// (for their variants). This method returns those contained items.
371 crate fn inner_items(&self) -> impl Iterator<Item = &Item> {
373 StructItem(s) => s.fields.iter(),
374 UnionItem(u) => u.fields.iter(),
375 VariantItem(Variant::Struct(v)) => v.fields.iter(),
376 EnumItem(e) => e.variants.iter(),
377 TraitItem(t) => t.items.iter(),
378 ImplItem(i) => i.items.iter(),
379 ModuleItem(m) => m.items.iter(),
380 ExternCrateItem(_, _)
392 | ForeignFunctionItem(_)
393 | ForeignStaticItem(_)
398 | AssocConstItem(_, _)
399 | AssocTypeItem(_, _)
401 | KeywordItem(_) => [].iter(),
405 crate fn is_type_alias(&self) -> bool {
406 matches!(self, ItemKind::TypedefItem(..) | ItemKind::AssocTypeItem(..))
410 #[derive(Clone, Debug)]
411 crate struct Module {
412 crate items: Vec<Item>,
413 crate is_crate: bool,
416 crate struct ListAttributesIter<'a> {
417 attrs: slice::Iter<'a, ast::Attribute>,
418 current_list: vec::IntoIter<ast::NestedMetaItem>,
422 impl<'a> Iterator for ListAttributesIter<'a> {
423 type Item = ast::NestedMetaItem;
425 fn next(&mut self) -> Option<Self::Item> {
426 if let Some(nested) = self.current_list.next() {
430 for attr in &mut self.attrs {
431 if let Some(list) = attr.meta_item_list() {
432 if attr.has_name(self.name) {
433 self.current_list = list.into_iter();
434 if let Some(nested) = self.current_list.next() {
444 fn size_hint(&self) -> (usize, Option<usize>) {
445 let lower = self.current_list.len();
450 crate trait AttributesExt {
451 /// Finds an attribute as List and returns the list of attributes nested inside.
452 fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
455 impl AttributesExt for [ast::Attribute] {
456 fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
457 ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), name }
461 crate trait NestedAttributesExt {
462 /// Returns `true` if the attribute list contains a specific `Word`
463 fn has_word(self, word: Symbol) -> bool;
464 fn get_word_attr(self, word: Symbol) -> Option<ast::NestedMetaItem>;
467 impl<I: Iterator<Item = ast::NestedMetaItem> + IntoIterator<Item = ast::NestedMetaItem>>
468 NestedAttributesExt for I
470 fn has_word(self, word: Symbol) -> bool {
471 self.into_iter().any(|attr| attr.is_word() && attr.has_name(word))
474 fn get_word_attr(mut self, word: Symbol) -> Option<ast::NestedMetaItem> {
475 self.find(|attr| attr.is_word() && attr.has_name(word))
479 /// A portion of documentation, extracted from a `#[doc]` attribute.
481 /// Each variant contains the line number within the complete doc-comment where the fragment
482 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
484 /// Included files are kept separate from inline doc comments so that proper line-number
485 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
486 /// kept separate because of issue #42760.
487 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
488 crate struct DocFragment {
490 crate span: rustc_span::Span,
491 /// The module this doc-comment came from.
493 /// This allows distinguishing between the original documentation and a pub re-export.
494 /// If it is `None`, the item was not re-exported.
495 crate parent_module: Option<DefId>,
497 crate kind: DocFragmentKind,
498 crate need_backline: bool,
502 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
503 crate enum DocFragmentKind {
504 /// A doc fragment created from a `///` or `//!` doc comment.
506 /// A doc fragment created from a "raw" `#[doc=""]` attribute.
508 /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
509 /// given filename and the file contents.
510 Include { filename: Symbol },
513 // The goal of this function is to apply the `DocFragment` transformations that are required when
514 // transforming into the final markdown. So the transformations in here are:
516 // * Applying the computed indent to each lines in each doc fragment (a `DocFragment` can contain
517 // multiple lines in case of `#[doc = ""]`).
518 // * Adding backlines between `DocFragment`s and adding an extra one if required (stored in the
519 // `need_backline` field).
520 fn add_doc_fragment(out: &mut String, frag: &DocFragment) {
521 let s = frag.doc.as_str();
522 let mut iter = s.lines().peekable();
523 while let Some(line) = iter.next() {
524 if line.chars().any(|c| !c.is_whitespace()) {
525 assert!(line.len() >= frag.indent);
526 out.push_str(&line[frag.indent..]);
530 if iter.peek().is_some() {
534 if frag.need_backline {
539 impl<'a> FromIterator<&'a DocFragment> for String {
540 fn from_iter<T>(iter: T) -> Self
542 T: IntoIterator<Item = &'a DocFragment>,
544 let mut prev_kind: Option<DocFragmentKind> = None;
545 iter.into_iter().fold(String::new(), |mut acc, frag| {
549 .map(|p| matches!(p, DocFragmentKind::Include { .. }) && p != frag.kind)
554 add_doc_fragment(&mut acc, &frag);
555 prev_kind = Some(frag.kind);
561 #[derive(Clone, Debug, Default)]
562 crate struct Attributes {
563 crate doc_strings: Vec<DocFragment>,
564 crate other_attrs: Vec<ast::Attribute>,
565 crate cfg: Option<Arc<Cfg>>,
566 crate span: Option<rustc_span::Span>,
567 /// map from Rust paths to resolved defs and potential URL fragments
568 crate links: Vec<ItemLink>,
569 crate inner_docs: bool,
572 #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
573 /// A link that has not yet been rendered.
575 /// This link will be turned into a rendered link by [`Attributes::links`]
576 crate struct ItemLink {
577 /// The original link written in the markdown
578 pub(crate) link: String,
579 /// The link text displayed in the HTML.
581 /// This may not be the same as `link` if there was a disambiguator
582 /// in an intra-doc link (e.g. \[`fn@f`\])
583 pub(crate) link_text: String,
584 pub(crate) did: Option<DefId>,
585 /// The url fragment to append to the link
586 pub(crate) fragment: Option<String>,
589 pub struct RenderedLink {
590 /// The text the link was original written as.
592 /// This could potentially include disambiguators and backticks.
593 pub(crate) original_text: String,
594 /// The text to display in the HTML
595 pub(crate) new_text: String,
596 /// The URL to put in the `href`
597 pub(crate) href: String,
601 /// Extracts the content from an attribute `#[doc(cfg(content))]`.
602 crate fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
603 use rustc_ast::NestedMetaItem::MetaItem;
605 if let ast::MetaItemKind::List(ref nmis) = mi.kind {
607 if let MetaItem(ref cfg_mi) = nmis[0] {
608 if cfg_mi.has_name(sym::cfg) {
609 if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.kind {
610 if cfg_nmis.len() == 1 {
611 if let MetaItem(ref content_mi) = cfg_nmis[0] {
612 return Some(content_mi);
624 /// Reads a `MetaItem` from within an attribute, looks for whether it is a
625 /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
627 crate fn extract_include(mi: &ast::MetaItem) -> Option<(Symbol, Symbol)> {
628 mi.meta_item_list().and_then(|list| {
630 if meta.has_name(sym::include) {
631 // the actual compiled `#[doc(include="filename")]` gets expanded to
632 // `#[doc(include(file="filename", contents="file contents")]` so we need to
633 // look for that instead
634 return meta.meta_item_list().and_then(|list| {
635 let mut filename: Option<Symbol> = None;
636 let mut contents: Option<Symbol> = None;
639 if it.has_name(sym::file) {
640 if let Some(name) = it.value_str() {
641 filename = Some(name);
643 } else if it.has_name(sym::contents) {
644 if let Some(docs) = it.value_str() {
645 contents = Some(docs);
650 if let (Some(filename), Some(contents)) = (filename, contents) {
651 Some((filename, contents))
663 crate fn has_doc_flag(&self, flag: Symbol) -> bool {
664 for attr in &self.other_attrs {
665 if !attr.has_name(sym::doc) {
669 if let Some(items) = attr.meta_item_list() {
670 if items.iter().filter_map(|i| i.meta_item()).any(|it| it.has_name(flag)) {
680 diagnostic: &::rustc_errors::Handler,
681 attrs: &[ast::Attribute],
682 additional_attrs: Option<(&[ast::Attribute], DefId)>,
684 let mut doc_strings: Vec<DocFragment> = vec![];
686 let mut cfg = Cfg::True;
687 let mut doc_line = 0;
689 fn update_need_backline(doc_strings: &mut Vec<DocFragment>, frag: &DocFragment) {
690 if let Some(prev) = doc_strings.last_mut() {
691 if matches!(prev.kind, DocFragmentKind::Include { .. })
692 || prev.kind != frag.kind
693 || prev.parent_module != frag.parent_module
695 // add a newline for extra padding between segments
696 prev.need_backline = prev.kind == DocFragmentKind::SugaredDoc
697 || prev.kind == DocFragmentKind::RawDoc
699 prev.need_backline = true;
704 let clean_attr = |(attr, parent_module): (&ast::Attribute, _)| {
705 if let Some(value) = attr.doc_str() {
706 trace!("got doc_str={:?}", value);
707 let value = beautify_doc_string(value);
708 let kind = if attr.is_doc_comment() {
709 DocFragmentKind::SugaredDoc
711 DocFragmentKind::RawDoc
715 doc_line += value.as_str().lines().count();
716 let frag = DocFragment {
722 need_backline: false,
726 update_need_backline(&mut doc_strings, &frag);
728 doc_strings.push(frag);
731 sp = Some(attr.span);
735 if attr.has_name(sym::doc) {
736 if let Some(mi) = attr.meta() {
737 if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
738 // Extracted #[doc(cfg(...))]
739 match Cfg::parse(cfg_mi) {
740 Ok(new_cfg) => cfg &= new_cfg,
741 Err(e) => diagnostic.span_err(e.span, e.msg),
743 } else if let Some((filename, contents)) = Attributes::extract_include(&mi)
746 doc_line += contents.as_str().lines().count();
747 let frag = DocFragment {
751 kind: DocFragmentKind::Include { filename },
753 need_backline: false,
756 update_need_backline(&mut doc_strings, &frag);
757 doc_strings.push(frag);
765 // Additional documentation should be shown before the original documentation
766 let other_attrs = additional_attrs
768 .map(|(attrs, id)| attrs.iter().map(move |attr| (attr, Some(id))))
770 .chain(attrs.iter().map(|attr| (attr, None)))
771 .filter_map(clean_attr)
774 // treat #[target_feature(enable = "feat")] attributes as if they were
775 // #[doc(cfg(target_feature = "feat"))] attributes as well
776 for attr in attrs.lists(sym::target_feature) {
777 if attr.has_name(sym::enable) {
778 if let Some(feat) = attr.value_str() {
779 let meta = attr::mk_name_value_item_str(
780 Ident::with_dummy_span(sym::target_feature),
784 if let Ok(feat_cfg) = Cfg::parse(&meta) {
791 let inner_docs = attrs
793 .find(|a| a.doc_str().is_some())
794 .map_or(true, |a| a.style == AttrStyle::Inner);
799 cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) },
806 /// Finds the `doc` attribute as a NameValue and returns the corresponding
808 crate fn doc_value(&self) -> Option<String> {
809 let mut iter = self.doc_strings.iter();
811 let ori = iter.next()?;
812 let mut out = String::new();
813 add_doc_fragment(&mut out, &ori);
814 while let Some(new_frag) = iter.next() {
815 if matches!(ori.kind, DocFragmentKind::Include { .. })
816 || new_frag.kind != ori.kind
817 || new_frag.parent_module != ori.parent_module
821 add_doc_fragment(&mut out, &new_frag);
823 if out.is_empty() { None } else { Some(out) }
826 /// Return the doc-comments on this item, grouped by the module they came from.
828 /// The module can be different if this is a re-export with added documentation.
829 crate fn collapsed_doc_value_by_module_level(&self) -> FxHashMap<Option<DefId>, String> {
830 let mut ret = FxHashMap::default();
832 for new_frag in self.doc_strings.iter() {
833 let out = ret.entry(new_frag.parent_module).or_default();
834 add_doc_fragment(out, &new_frag);
839 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
841 crate fn collapsed_doc_value(&self) -> Option<String> {
842 if self.doc_strings.is_empty() { None } else { Some(self.doc_strings.iter().collect()) }
845 /// Gets links as a vector
847 /// Cache must be populated before call
848 crate fn links(&self, krate: &CrateNum, cache: &Cache) -> Vec<RenderedLink> {
849 use crate::html::format::href;
850 use crate::html::render::CURRENT_DEPTH;
854 .filter_map(|ItemLink { link: s, link_text, did, fragment }| {
857 if let Some((mut href, ..)) = href(did, cache) {
858 if let Some(ref fragment) = *fragment {
860 href.push_str(fragment);
863 original_text: s.clone(),
864 new_text: link_text.clone(),
872 if let Some(ref fragment) = *fragment {
873 let url = match cache.extern_locations.get(krate) {
874 Some(&(_, _, ExternalLocation::Local)) => {
875 let depth = CURRENT_DEPTH.with(|l| l.get());
878 Some(&(_, _, ExternalLocation::Remote(ref s))) => s.to_string(),
879 Some(&(_, _, ExternalLocation::Unknown)) | None => String::from(
880 // NOTE: intentionally doesn't pass crate name to avoid having
881 // different primitive links between crates
882 if UnstableFeatures::from_environment(None).is_nightly_build() {
883 "https://doc.rust-lang.org/nightly"
885 "https://doc.rust-lang.org"
889 // This is a primitive so the url is done "by hand".
890 let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
892 original_text: s.clone(),
893 new_text: link_text.clone(),
895 "{}{}std/primitive.{}.html{}",
897 if !url.ends_with('/') { "/" } else { "" },
903 panic!("This isn't a primitive?!");
911 crate fn get_doc_aliases(&self) -> FxHashSet<String> {
914 .filter(|a| a.has_name(sym::alias))
915 .filter_map(|a| a.value_str().map(|s| s.to_string()))
916 .filter(|v| !v.is_empty())
917 .collect::<FxHashSet<_>>()
921 impl PartialEq for Attributes {
922 fn eq(&self, rhs: &Self) -> bool {
923 self.doc_strings == rhs.doc_strings
924 && self.cfg == rhs.cfg
925 && self.span == rhs.span
926 && self.links == rhs.links
931 .eq(rhs.other_attrs.iter().map(|attr| attr.id))
935 impl Eq for Attributes {}
937 impl Hash for Attributes {
938 fn hash<H: Hasher>(&self, hasher: &mut H) {
939 self.doc_strings.hash(hasher);
940 self.cfg.hash(hasher);
941 self.span.hash(hasher);
942 self.links.hash(hasher);
943 for attr in &self.other_attrs {
944 attr.id.hash(hasher);
949 impl AttributesExt for Attributes {
950 fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
951 self.other_attrs.lists(name)
955 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
956 crate enum GenericBound {
957 TraitBound(PolyTrait, hir::TraitBoundModifier),
962 crate fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
963 let did = cx.tcx.require_lang_item(LangItem::Sized, None);
964 let empty = cx.tcx.intern_substs(&[]);
965 let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
966 inline::record_extern_fqn(cx, did, TypeKind::Trait);
967 GenericBound::TraitBound(
969 trait_: ResolvedPath { path, param_names: None, did, is_generic: false },
970 generic_params: Vec::new(),
972 hir::TraitBoundModifier::Maybe,
976 crate fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
977 use rustc_hir::TraitBoundModifier as TBM;
978 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
979 if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
986 crate fn get_poly_trait(&self) -> Option<PolyTrait> {
987 if let GenericBound::TraitBound(ref p, _) = *self {
988 return Some(p.clone());
993 crate fn get_trait_type(&self) -> Option<Type> {
994 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1002 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1003 crate struct Lifetime(pub Symbol);
1006 crate fn get_ref(&self) -> SymbolStr {
1010 crate fn statik() -> Lifetime {
1011 Lifetime(kw::StaticLifetime)
1014 crate fn elided() -> Lifetime {
1015 Lifetime(kw::UnderscoreLifetime)
1019 #[derive(Clone, Debug)]
1020 crate enum WherePredicate {
1021 BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
1022 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1023 EqPredicate { lhs: Type, rhs: Type },
1026 impl WherePredicate {
1027 crate fn get_bounds(&self) -> Option<&[GenericBound]> {
1029 WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
1030 WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
1036 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1037 crate enum GenericParamDefKind {
1041 bounds: Vec<GenericBound>,
1042 default: Option<Type>,
1043 synthetic: Option<hir::SyntheticTyParamKind>,
1051 impl GenericParamDefKind {
1052 crate fn is_type(&self) -> bool {
1053 matches!(self, GenericParamDefKind::Type { .. })
1056 // FIXME(eddyb) this either returns the default of a type parameter, or the
1057 // type of a `const` parameter. It seems that the intention is to *visit*
1058 // any embedded types, but `get_type` seems to be the wrong name for that.
1059 crate fn get_type(&self) -> Option<Type> {
1061 GenericParamDefKind::Type { default, .. } => default.clone(),
1062 GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
1063 GenericParamDefKind::Lifetime => None,
1068 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1069 crate struct GenericParamDef {
1071 crate kind: GenericParamDefKind,
1074 impl GenericParamDef {
1075 crate fn is_synthetic_type_param(&self) -> bool {
1077 GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => false,
1078 GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
1082 crate fn is_type(&self) -> bool {
1086 crate fn get_type(&self) -> Option<Type> {
1087 self.kind.get_type()
1090 crate fn get_bounds(&self) -> Option<&[GenericBound]> {
1092 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1098 // maybe use a Generic enum and use Vec<Generic>?
1099 #[derive(Clone, Debug, Default)]
1100 crate struct Generics {
1101 crate params: Vec<GenericParamDef>,
1102 crate where_predicates: Vec<WherePredicate>,
1105 #[derive(Clone, Debug)]
1106 crate struct Function {
1108 crate generics: Generics,
1109 crate header: hir::FnHeader,
1112 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1113 crate struct FnDecl {
1114 crate inputs: Arguments,
1115 crate output: FnRetTy,
1116 crate c_variadic: bool,
1117 crate attrs: Attributes,
1121 crate fn self_type(&self) -> Option<SelfTy> {
1122 self.inputs.values.get(0).and_then(|v| v.to_self())
1125 /// Returns the sugared return type for an async function.
1127 /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
1128 /// will return `i32`.
1132 /// This function will panic if the return type does not match the expected sugaring for async
1134 crate fn sugared_async_return_type(&self) -> FnRetTy {
1135 match &self.output {
1136 FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
1137 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
1138 let bindings = trait_.bindings().unwrap();
1139 FnRetTy::Return(bindings[0].ty().clone())
1141 _ => panic!("unexpected desugaring of async function"),
1143 _ => panic!("unexpected desugaring of async function"),
1148 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1149 crate struct Arguments {
1150 crate values: Vec<Argument>,
1153 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1154 crate struct Argument {
1159 #[derive(Clone, PartialEq, Debug)]
1162 SelfBorrowed(Option<Lifetime>, Mutability),
1167 crate fn to_self(&self) -> Option<SelfTy> {
1168 if self.name != kw::SelfLower {
1171 if self.type_.is_self_type() {
1172 return Some(SelfValue);
1175 BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
1176 Some(SelfBorrowed(lifetime.clone(), mutability))
1178 _ => Some(SelfExplicit(self.type_.clone())),
1183 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1184 crate enum FnRetTy {
1189 impl GetDefId for FnRetTy {
1190 fn def_id(&self) -> Option<DefId> {
1192 Return(ref ty) => ty.def_id(),
1193 DefaultReturn => None,
1197 fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
1199 Return(ref ty) => ty.def_id_full(cache),
1200 DefaultReturn => None,
1205 #[derive(Clone, Debug)]
1206 crate struct Trait {
1207 crate unsafety: hir::Unsafety,
1208 crate items: Vec<Item>,
1209 crate generics: Generics,
1210 crate bounds: Vec<GenericBound>,
1211 crate is_auto: bool,
1214 #[derive(Clone, Debug)]
1215 crate struct TraitAlias {
1216 crate generics: Generics,
1217 crate bounds: Vec<GenericBound>,
1220 /// A trait reference, which may have higher ranked lifetimes.
1221 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1222 crate struct PolyTrait {
1224 crate generic_params: Vec<GenericParamDef>,
1227 /// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
1228 /// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
1229 /// importantly, it does not preserve mutability or boxes.
1230 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1232 /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
1235 param_names: Option<Vec<GenericBound>>,
1237 /// `true` if is a `T::Name` path for associated types.
1240 /// For parameterized types, so the consumer of the JSON don't go
1241 /// looking for types which don't exist anywhere.
1243 /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
1244 /// arrays, slices, and tuples.
1245 Primitive(PrimitiveType),
1246 /// `extern "ABI" fn`
1247 BareFunction(Box<BareFunctionDecl>),
1250 /// The `String` field is about the size or the constant representing the array's length.
1251 Array(Box<Type>, String),
1253 RawPointer(Mutability, Box<Type>),
1255 lifetime: Option<Lifetime>,
1256 mutability: Mutability,
1260 // `<Type as Trait>::Name`
1263 self_type: Box<Type>,
1270 // `impl TraitA + TraitB + ...`
1271 ImplTrait(Vec<GenericBound>),
1274 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1275 /// N.B. this has to be different from `hir::PrimTy` because it also includes types that aren't
1276 /// paths, like `Unit`.
1277 crate enum PrimitiveType {
1305 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1306 crate enum TypeKind {
1324 impl From<hir::def::DefKind> for TypeKind {
1325 fn from(other: hir::def::DefKind) -> Self {
1327 hir::def::DefKind::Enum => Self::Enum,
1328 hir::def::DefKind::Fn => Self::Function,
1329 hir::def::DefKind::Mod => Self::Module,
1330 hir::def::DefKind::Const => Self::Const,
1331 hir::def::DefKind::Static => Self::Static,
1332 hir::def::DefKind::Struct => Self::Struct,
1333 hir::def::DefKind::Union => Self::Union,
1334 hir::def::DefKind::Trait => Self::Trait,
1335 hir::def::DefKind::TyAlias => Self::Typedef,
1336 hir::def::DefKind::TraitAlias => Self::TraitAlias,
1337 hir::def::DefKind::Macro(_) => Self::Macro,
1338 hir::def::DefKind::ForeignTy
1339 | hir::def::DefKind::Variant
1340 | hir::def::DefKind::AssocTy
1341 | hir::def::DefKind::TyParam
1342 | hir::def::DefKind::ConstParam
1343 | hir::def::DefKind::Ctor(..)
1344 | hir::def::DefKind::AssocFn
1345 | hir::def::DefKind::AssocConst
1346 | hir::def::DefKind::ExternCrate
1347 | hir::def::DefKind::Use
1348 | hir::def::DefKind::ForeignMod
1349 | hir::def::DefKind::AnonConst
1350 | hir::def::DefKind::OpaqueTy
1351 | hir::def::DefKind::Field
1352 | hir::def::DefKind::LifetimeParam
1353 | hir::def::DefKind::GlobalAsm
1354 | hir::def::DefKind::Impl
1355 | hir::def::DefKind::Closure
1356 | hir::def::DefKind::Generator => Self::Foreign,
1361 crate trait GetDefId {
1362 /// Use this method to get the [`DefId`] of a [`clean`] AST node.
1363 /// This will return [`None`] when called on a primitive [`clean::Type`].
1364 /// Use [`Self::def_id_full`] if you want to include primitives.
1366 /// [`clean`]: crate::clean
1367 /// [`clean::Type`]: crate::clean::Type
1368 // FIXME: get rid of this function and always use `def_id_full`
1369 fn def_id(&self) -> Option<DefId>;
1371 /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s.
1373 /// See [`Self::def_id`] for more.
1375 /// [clean]: crate::clean
1376 fn def_id_full(&self, cache: &Cache) -> Option<DefId>;
1379 impl<T: GetDefId> GetDefId for Option<T> {
1380 fn def_id(&self) -> Option<DefId> {
1381 self.as_ref().and_then(|d| d.def_id())
1384 fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
1385 self.as_ref().and_then(|d| d.def_id_full(cache))
1390 crate fn primitive_type(&self) -> Option<PrimitiveType> {
1392 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1393 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1394 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1397 Some(PrimitiveType::Unit)
1399 Some(PrimitiveType::Tuple)
1402 RawPointer(..) => Some(PrimitiveType::RawPointer),
1403 BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
1404 BareFunction(..) => Some(PrimitiveType::Fn),
1405 Never => Some(PrimitiveType::Never),
1410 crate fn is_generic(&self) -> bool {
1412 ResolvedPath { is_generic, .. } => is_generic,
1417 crate fn is_self_type(&self) -> bool {
1419 Generic(name) => name == kw::SelfUpper,
1424 crate fn generics(&self) -> Option<Vec<&Type>> {
1426 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1427 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
1430 .filter_map(|arg| match arg {
1431 GenericArg::Type(ty) => Some(ty),
1444 crate fn bindings(&self) -> Option<&[TypeBinding]> {
1446 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1447 if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
1457 crate fn is_full_generic(&self) -> bool {
1458 matches!(self, Type::Generic(_))
1461 crate fn is_primitive(&self) -> bool {
1463 Self::Primitive(_) => true,
1464 Self::BorrowedRef { ref type_, .. } | Self::RawPointer(_, ref type_) => {
1465 type_.is_primitive()
1471 crate fn projection(&self) -> Option<(&Type, DefId, Symbol)> {
1472 let (self_, trait_, name) = match self {
1473 QPath { self_type, trait_, name } => (self_type, trait_, name),
1476 let trait_did = match **trait_ {
1477 ResolvedPath { did, .. } => did,
1480 Some((&self_, trait_did, *name))
1485 fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
1486 let t: PrimitiveType = match *self {
1487 ResolvedPath { did, .. } => return Some(did),
1488 Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
1489 BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
1490 BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache),
1495 PrimitiveType::Tuple
1498 BareFunction(..) => PrimitiveType::Fn,
1499 Never => PrimitiveType::Never,
1500 Slice(..) => PrimitiveType::Slice,
1501 Array(..) => PrimitiveType::Array,
1502 RawPointer(..) => PrimitiveType::RawPointer,
1503 QPath { ref self_type, .. } => return self_type.inner_def_id(cache),
1504 Generic(_) | Infer | ImplTrait(_) => return None,
1506 cache.and_then(|c| Primitive(t).def_id_full(c))
1510 impl GetDefId for Type {
1511 fn def_id(&self) -> Option<DefId> {
1512 self.inner_def_id(None)
1515 fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
1516 self.inner_def_id(Some(cache))
1520 impl PrimitiveType {
1521 crate fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1522 use ast::{FloatTy, IntTy, UintTy};
1524 hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1525 hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1526 hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1527 hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1528 hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1529 hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1530 hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1531 hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1532 hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1533 hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1534 hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1535 hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1536 hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1537 hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1538 hir::PrimTy::Str => PrimitiveType::Str,
1539 hir::PrimTy::Bool => PrimitiveType::Bool,
1540 hir::PrimTy::Char => PrimitiveType::Char,
1544 crate fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1546 sym::isize => Some(PrimitiveType::Isize),
1547 sym::i8 => Some(PrimitiveType::I8),
1548 sym::i16 => Some(PrimitiveType::I16),
1549 sym::i32 => Some(PrimitiveType::I32),
1550 sym::i64 => Some(PrimitiveType::I64),
1551 sym::i128 => Some(PrimitiveType::I128),
1552 sym::usize => Some(PrimitiveType::Usize),
1553 sym::u8 => Some(PrimitiveType::U8),
1554 sym::u16 => Some(PrimitiveType::U16),
1555 sym::u32 => Some(PrimitiveType::U32),
1556 sym::u64 => Some(PrimitiveType::U64),
1557 sym::u128 => Some(PrimitiveType::U128),
1558 sym::bool => Some(PrimitiveType::Bool),
1559 sym::char => Some(PrimitiveType::Char),
1560 sym::str => Some(PrimitiveType::Str),
1561 sym::f32 => Some(PrimitiveType::F32),
1562 sym::f64 => Some(PrimitiveType::F64),
1563 sym::array => Some(PrimitiveType::Array),
1564 sym::slice => Some(PrimitiveType::Slice),
1565 sym::tuple => Some(PrimitiveType::Tuple),
1566 sym::unit => Some(PrimitiveType::Unit),
1567 sym::pointer => Some(PrimitiveType::RawPointer),
1568 sym::reference => Some(PrimitiveType::Reference),
1569 kw::Fn => Some(PrimitiveType::Fn),
1570 sym::never => Some(PrimitiveType::Never),
1575 crate fn as_str(&self) -> &'static str {
1576 use self::PrimitiveType::*;
1599 RawPointer => "pointer",
1600 Reference => "reference",
1606 crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static ArrayVec<[DefId; 4]> {
1607 Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
1610 crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, ArrayVec<[DefId; 4]>> {
1611 static CELL: OnceCell<FxHashMap<PrimitiveType, ArrayVec<[DefId; 4]>>> = OnceCell::new();
1613 CELL.get_or_init(move || {
1614 use self::PrimitiveType::*;
1616 /// A macro to create a FxHashMap.
1621 /// let letters = map!{"a" => "b", "c" => "d"};
1624 /// Trailing commas are allowed.
1625 /// Commas between elements are required (even if the expression is a block).
1627 ($( $key: expr => $val: expr ),* $(,)*) => {{
1628 let mut map = ::rustc_data_structures::fx::FxHashMap::default();
1629 $( map.insert($key, $val); )*
1634 let single = |a: Option<DefId>| a.into_iter().collect();
1635 let both = |a: Option<DefId>, b: Option<DefId>| -> ArrayVec<_> {
1636 a.into_iter().chain(b).collect()
1639 let lang_items = tcx.lang_items();
1641 Isize => single(lang_items.isize_impl()),
1642 I8 => single(lang_items.i8_impl()),
1643 I16 => single(lang_items.i16_impl()),
1644 I32 => single(lang_items.i32_impl()),
1645 I64 => single(lang_items.i64_impl()),
1646 I128 => single(lang_items.i128_impl()),
1647 Usize => single(lang_items.usize_impl()),
1648 U8 => single(lang_items.u8_impl()),
1649 U16 => single(lang_items.u16_impl()),
1650 U32 => single(lang_items.u32_impl()),
1651 U64 => single(lang_items.u64_impl()),
1652 U128 => single(lang_items.u128_impl()),
1653 F32 => both(lang_items.f32_impl(), lang_items.f32_runtime_impl()),
1654 F64 => both(lang_items.f64_impl(), lang_items.f64_runtime_impl()),
1655 Char => single(lang_items.char_impl()),
1656 Bool => single(lang_items.bool_impl()),
1657 Str => both(lang_items.str_impl(), lang_items.str_alloc_impl()),
1662 .chain(lang_items.slice_u8_impl())
1663 .chain(lang_items.slice_alloc_impl())
1664 .chain(lang_items.slice_u8_alloc_impl())
1667 Array => single(lang_items.array_impl()),
1668 Tuple => ArrayVec::new(),
1669 Unit => ArrayVec::new(),
1674 .chain(lang_items.mut_ptr_impl())
1675 .chain(lang_items.const_slice_ptr_impl())
1676 .chain(lang_items.mut_slice_ptr_impl())
1679 Reference => ArrayVec::new(),
1680 Fn => ArrayVec::new(),
1681 Never => ArrayVec::new(),
1686 crate fn to_url_str(&self) -> &'static str {
1690 crate fn as_sym(&self) -> Symbol {
1691 use PrimitiveType::*;
1693 Isize => sym::isize,
1699 Usize => sym::usize,
1710 Array => sym::array,
1711 Slice => sym::slice,
1712 Tuple => sym::tuple,
1714 RawPointer => sym::pointer,
1715 Reference => sym::reference,
1717 Never => sym::never,
1722 impl From<ast::IntTy> for PrimitiveType {
1723 fn from(int_ty: ast::IntTy) -> PrimitiveType {
1725 ast::IntTy::Isize => PrimitiveType::Isize,
1726 ast::IntTy::I8 => PrimitiveType::I8,
1727 ast::IntTy::I16 => PrimitiveType::I16,
1728 ast::IntTy::I32 => PrimitiveType::I32,
1729 ast::IntTy::I64 => PrimitiveType::I64,
1730 ast::IntTy::I128 => PrimitiveType::I128,
1735 impl From<ast::UintTy> for PrimitiveType {
1736 fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1738 ast::UintTy::Usize => PrimitiveType::Usize,
1739 ast::UintTy::U8 => PrimitiveType::U8,
1740 ast::UintTy::U16 => PrimitiveType::U16,
1741 ast::UintTy::U32 => PrimitiveType::U32,
1742 ast::UintTy::U64 => PrimitiveType::U64,
1743 ast::UintTy::U128 => PrimitiveType::U128,
1748 impl From<ast::FloatTy> for PrimitiveType {
1749 fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1751 ast::FloatTy::F32 => PrimitiveType::F32,
1752 ast::FloatTy::F64 => PrimitiveType::F64,
1757 impl From<ty::IntTy> for PrimitiveType {
1758 fn from(int_ty: ty::IntTy) -> PrimitiveType {
1760 ty::IntTy::Isize => PrimitiveType::Isize,
1761 ty::IntTy::I8 => PrimitiveType::I8,
1762 ty::IntTy::I16 => PrimitiveType::I16,
1763 ty::IntTy::I32 => PrimitiveType::I32,
1764 ty::IntTy::I64 => PrimitiveType::I64,
1765 ty::IntTy::I128 => PrimitiveType::I128,
1770 impl From<ty::UintTy> for PrimitiveType {
1771 fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1773 ty::UintTy::Usize => PrimitiveType::Usize,
1774 ty::UintTy::U8 => PrimitiveType::U8,
1775 ty::UintTy::U16 => PrimitiveType::U16,
1776 ty::UintTy::U32 => PrimitiveType::U32,
1777 ty::UintTy::U64 => PrimitiveType::U64,
1778 ty::UintTy::U128 => PrimitiveType::U128,
1783 impl From<ty::FloatTy> for PrimitiveType {
1784 fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1786 ty::FloatTy::F32 => PrimitiveType::F32,
1787 ty::FloatTy::F64 => PrimitiveType::F64,
1792 impl From<hir::PrimTy> for PrimitiveType {
1793 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1795 hir::PrimTy::Int(int_ty) => int_ty.into(),
1796 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1797 hir::PrimTy::Float(float_ty) => float_ty.into(),
1798 hir::PrimTy::Str => PrimitiveType::Str,
1799 hir::PrimTy::Bool => PrimitiveType::Bool,
1800 hir::PrimTy::Char => PrimitiveType::Char,
1805 #[derive(Copy, Clone, Debug)]
1806 crate enum Visibility {
1813 crate fn is_public(&self) -> bool {
1814 matches!(self, Visibility::Public)
1818 #[derive(Clone, Debug)]
1819 crate struct Struct {
1820 crate struct_type: CtorKind,
1821 crate generics: Generics,
1822 crate fields: Vec<Item>,
1823 crate fields_stripped: bool,
1826 #[derive(Clone, Debug)]
1827 crate struct Union {
1828 crate generics: Generics,
1829 crate fields: Vec<Item>,
1830 crate fields_stripped: bool,
1833 /// This is a more limited form of the standard Struct, different in that
1834 /// it lacks the things most items have (name, id, parameterization). Found
1835 /// only as a variant in an enum.
1836 #[derive(Clone, Debug)]
1837 crate struct VariantStruct {
1838 crate struct_type: CtorKind,
1839 crate fields: Vec<Item>,
1840 crate fields_stripped: bool,
1843 #[derive(Clone, Debug)]
1845 crate variants: IndexVec<VariantIdx, Item>,
1846 crate generics: Generics,
1847 crate variants_stripped: bool,
1850 #[derive(Clone, Debug)]
1851 crate enum Variant {
1854 Struct(VariantStruct),
1857 /// Small wrapper around `rustc_span::Span` that adds helper methods and enforces calling `source_callsite`.
1858 #[derive(Clone, Debug)]
1859 crate struct Span(rustc_span::Span);
1862 crate fn from_rustc_span(sp: rustc_span::Span) -> Self {
1863 // Get the macro invocation instead of the definition,
1864 // in case the span is result of a macro expansion.
1865 // (See rust-lang/rust#39726)
1866 Self(sp.source_callsite())
1869 crate fn dummy() -> Self {
1870 Self(rustc_span::DUMMY_SP)
1873 crate fn span(&self) -> rustc_span::Span {
1877 crate fn is_dummy(&self) -> bool {
1881 crate fn filename(&self, sess: &Session) -> FileName {
1882 sess.source_map().span_to_filename(self.0)
1885 crate fn lo(&self, sess: &Session) -> Loc {
1886 sess.source_map().lookup_char_pos(self.0.lo())
1889 crate fn hi(&self, sess: &Session) -> Loc {
1890 sess.source_map().lookup_char_pos(self.0.hi())
1893 crate fn cnum(&self, sess: &Session) -> CrateNum {
1894 // FIXME: is there a time when the lo and hi crate would be different?
1895 self.lo(sess).file.cnum
1899 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1903 crate segments: Vec<PathSegment>,
1907 crate fn last(&self) -> Symbol {
1908 self.segments.last().expect("segments were empty").name
1911 crate fn last_name(&self) -> SymbolStr {
1912 self.segments.last().expect("segments were empty").name.as_str()
1915 crate fn whole_name(&self) -> String {
1916 String::from(if self.global { "::" } else { "" })
1917 + &self.segments.iter().map(|s| s.name.to_string()).collect::<Vec<_>>().join("::")
1921 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1922 crate enum GenericArg {
1928 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1929 crate enum GenericArgs {
1930 AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
1931 Parenthesized { inputs: Vec<Type>, output: Option<Type> },
1934 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1935 crate struct PathSegment {
1937 crate args: GenericArgs,
1940 #[derive(Clone, Debug)]
1941 crate struct Typedef {
1943 crate generics: Generics,
1944 /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
1945 /// alias instead of the final type. This will always have the final type, regardless of whether
1946 /// `type_` came from HIR or from metadata.
1948 /// If `item_type.is_none()`, `type_` is guarenteed to come from metadata (and therefore hold the
1950 crate item_type: Option<Type>,
1953 impl GetDefId for Typedef {
1954 fn def_id(&self) -> Option<DefId> {
1958 fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
1959 self.type_.def_id_full(cache)
1963 #[derive(Clone, Debug)]
1964 crate struct OpaqueTy {
1965 crate bounds: Vec<GenericBound>,
1966 crate generics: Generics,
1969 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1970 crate struct BareFunctionDecl {
1971 crate unsafety: hir::Unsafety,
1972 crate generic_params: Vec<GenericParamDef>,
1977 #[derive(Clone, Debug)]
1978 crate struct Static {
1980 crate mutability: Mutability,
1981 crate expr: Option<BodyId>,
1984 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
1985 crate struct Constant {
1988 crate value: Option<String>,
1989 crate is_literal: bool,
1992 #[derive(Clone, Debug)]
1994 crate unsafety: hir::Unsafety,
1995 crate generics: Generics,
1996 crate provided_trait_methods: FxHashSet<Symbol>,
1997 crate trait_: Option<Type>,
1999 crate items: Vec<Item>,
2000 crate negative_polarity: bool,
2001 crate synthetic: bool,
2002 crate blanket_impl: Option<Type>,
2005 #[derive(Clone, Debug)]
2006 crate struct Import {
2007 crate kind: ImportKind,
2008 crate source: ImportSource,
2009 crate should_be_displayed: bool,
2013 crate fn new_simple(name: Symbol, source: ImportSource, should_be_displayed: bool) -> Self {
2014 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2017 crate fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2018 Self { kind: ImportKind::Glob, source, should_be_displayed }
2022 #[derive(Clone, Debug)]
2023 crate enum ImportKind {
2024 // use source as str;
2030 #[derive(Clone, Debug)]
2031 crate struct ImportSource {
2033 crate did: Option<DefId>,
2036 #[derive(Clone, Debug)]
2037 crate struct Macro {
2038 crate source: String,
2039 crate imported_from: Option<Symbol>,
2042 #[derive(Clone, Debug)]
2043 crate struct ProcMacro {
2044 crate kind: MacroKind,
2045 crate helpers: Vec<Symbol>,
2048 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
2049 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
2050 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2051 crate struct TypeBinding {
2053 crate kind: TypeBindingKind,
2056 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2057 crate enum TypeBindingKind {
2058 Equality { ty: Type },
2059 Constraint { bounds: Vec<GenericBound> },
2063 crate fn ty(&self) -> &Type {
2065 TypeBindingKind::Equality { ref ty } => ty,
2066 _ => panic!("expected equality type binding for parenthesized generic args"),