1 use std::cell::{Cell, RefCell};
2 use std::default::Default;
3 use std::hash::{Hash, Hasher};
4 use std::iter::FromIterator;
5 use std::lazy::SyncOnceCell as OnceCell;
6 use std::path::PathBuf;
11 use arrayvec::ArrayVec;
14 use rustc_ast::util::comments::beautify_doc_string;
15 use rustc_ast::{self as ast, AttrStyle};
16 use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
17 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
18 use rustc_data_structures::thin_vec::ThinVec;
20 use rustc_hir::def::{CtorKind, DefKind, Res};
21 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
22 use rustc_hir::lang_items::LangItem;
23 use rustc_hir::{BodyId, Mutability};
24 use rustc_index::vec::IndexVec;
25 use rustc_middle::ty::{self, TyCtxt};
26 use rustc_session::Session;
27 use rustc_span::hygiene::MacroKind;
28 use rustc_span::source_map::DUMMY_SP;
29 use rustc_span::symbol::{kw, sym, Ident, Symbol, SymbolStr};
30 use rustc_span::{self, FileName, Loc};
31 use rustc_target::abi::VariantIdx;
32 use rustc_target::spec::abi::Abi;
34 use crate::clean::cfg::Cfg;
35 use crate::clean::external_path;
36 use crate::clean::inline::{self, print_inlined_const};
37 use crate::clean::types::Type::{QPath, ResolvedPath};
38 use crate::clean::utils::{is_literal_expr, print_const_expr, print_evaluated_const};
39 use crate::clean::Clean;
40 use crate::core::DocContext;
41 use crate::formats::cache::Cache;
42 use crate::formats::item_type::ItemType;
43 use crate::html::render::cache::ExternalLocation;
44 use crate::html::render::Context;
47 use self::ItemKind::*;
51 crate type FakeDefIdSet = FxHashSet<FakeDefId>;
53 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
54 crate enum FakeDefId {
56 Fake(DefIndex, CrateNum),
60 #[cfg(parallel_compiler)]
61 crate fn new_fake(crate: CrateNum) -> Self {
65 #[cfg(not(parallel_compiler))]
66 crate fn new_fake(krate: CrateNum) -> Self {
67 thread_local!(static FAKE_DEF_ID_COUNTER: Cell<usize> = Cell::new(0));
68 let id = FAKE_DEF_ID_COUNTER.with(|id| {
73 Self::Fake(DefIndex::from(id), krate)
76 crate fn new_real(id: DefId) -> Self {
81 crate fn is_local(self) -> bool {
83 FakeDefId::Real(id) => id.is_local(),
84 FakeDefId::Fake(_, krate) => krate == LOCAL_CRATE,
89 crate fn expect_real(self) -> rustc_hir::def_id::DefId {
90 self.as_real().unwrap_or_else(|| panic!("FakeDefId::expect_real: `{:?}` isn't real", self))
94 crate fn as_real(self) -> Option<DefId> {
96 FakeDefId::Real(id) => Some(id),
97 FakeDefId::Fake(_, _) => None,
102 crate fn krate(self) -> CrateNum {
104 FakeDefId::Real(id) => id.krate,
105 FakeDefId::Fake(_, krate) => krate,
110 crate fn index(self) -> Option<DefIndex> {
112 FakeDefId::Real(id) => Some(id.index),
113 FakeDefId::Fake(_, _) => None,
118 impl From<DefId> for FakeDefId {
119 fn from(id: DefId) -> Self {
124 #[derive(Clone, Debug)]
129 crate externs: Vec<(CrateNum, ExternalCrate)>,
130 crate primitives: ThinVec<(DefId, PrimitiveType)>,
131 // These are later on moved into `CACHEKEY`, leaving the map empty.
132 // Only here so that they can be filtered through the rustdoc passes.
133 crate external_traits: Rc<RefCell<FxHashMap<DefId, TraitWithExtraInfo>>>,
134 crate collapsed: bool,
137 /// This struct is used to wrap additional information added by rustdoc on a `trait` item.
138 #[derive(Clone, Debug)]
139 crate struct TraitWithExtraInfo {
141 crate is_notable: bool,
144 #[derive(Clone, Debug)]
145 crate struct ExternalCrate {
146 crate crate_num: CrateNum,
151 fn def_id(&self) -> DefId {
152 DefId { krate: self.crate_num, index: CRATE_DEF_INDEX }
155 crate fn src(&self, tcx: TyCtxt<'_>) -> FileName {
156 let krate_span = tcx.def_span(self.def_id());
157 tcx.sess.source_map().span_to_filename(krate_span)
160 crate fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
161 tcx.crate_name(self.crate_num)
164 crate fn src_root(&self, tcx: TyCtxt<'_>) -> PathBuf {
165 match self.src(tcx) {
166 FileName::Real(ref p) => match p.local_path().parent() {
167 Some(p) => p.to_path_buf(),
168 None => PathBuf::new(),
174 /// Attempts to find where an external crate is located, given that we're
175 /// rendering in to the specified source destination.
178 extern_url: Option<&str>,
179 dst: &std::path::Path,
181 ) -> ExternalLocation {
182 use ExternalLocation::*;
184 fn to_remote(url: impl ToString) -> ExternalLocation {
185 let mut url = url.to_string();
186 if !url.ends_with('/') {
192 // See if there's documentation generated into the local directory
193 // WARNING: since rustdoc creates these directories as it generates documentation, this check is only accurate before rendering starts.
194 // Make sure to call `location()` by that time.
195 let local_location = dst.join(&*self.name(tcx).as_str());
196 if local_location.is_dir() {
200 if let Some(url) = extern_url {
201 return to_remote(url);
204 // Failing that, see if there's an attribute specifying where to find this
206 let did = DefId { krate: self.crate_num, index: CRATE_DEF_INDEX };
209 .filter(|a| a.has_name(sym::html_root_url))
210 .filter_map(|a| a.value_str())
213 .unwrap_or(Unknown) // Well, at least we tried.
216 crate fn keywords(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, Symbol)> {
217 let root = self.def_id();
219 let as_keyword = |res: Res| {
220 if let Res::Def(DefKind::Mod, def_id) = res {
221 let attrs = tcx.get_attrs(def_id);
222 let mut keyword = None;
223 for attr in attrs.lists(sym::doc) {
224 if attr.has_name(sym::keyword) {
225 if let Some(v) = attr.value_str() {
231 return keyword.map(|p| (def_id, p));
242 let item = tcx.hir().item(id);
244 hir::ItemKind::Mod(_) => {
245 as_keyword(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
247 hir::ItemKind::Use(ref path, hir::UseKind::Single)
248 if item.vis.node.is_pub() =>
250 as_keyword(path.res).map(|(_, prim)| (id.def_id.to_def_id(), prim))
257 tcx.item_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect()
261 crate fn primitives(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, PrimitiveType)> {
262 let root = self.def_id();
264 // Collect all inner modules which are tagged as implementations of
267 // Note that this loop only searches the top-level items of the crate,
268 // and this is intentional. If we were to search the entire crate for an
269 // item tagged with `#[doc(primitive)]` then we would also have to
270 // search the entirety of external modules for items tagged
271 // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
272 // all that metadata unconditionally).
274 // In order to keep the metadata load under control, the
275 // `#[doc(primitive)]` feature is explicitly designed to only allow the
276 // primitive tags to show up as the top level items in a crate.
278 // Also note that this does not attempt to deal with modules tagged
279 // duplicately for the same primitive. This is handled later on when
280 // rendering by delegating everything to a hash map.
281 let as_primitive = |res: Res| {
282 if let Res::Def(DefKind::Mod, def_id) = res {
283 let attrs = tcx.get_attrs(def_id);
285 for attr in attrs.lists(sym::doc) {
286 if let Some(v) = attr.value_str() {
287 if attr.has_name(sym::primitive) {
288 prim = PrimitiveType::from_symbol(v);
292 // FIXME: should warn on unknown primitives?
296 return prim.map(|p| (def_id, p));
308 let item = tcx.hir().item(id);
310 hir::ItemKind::Mod(_) => {
311 as_primitive(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
313 hir::ItemKind::Use(ref path, hir::UseKind::Single)
314 if item.vis.node.is_pub() =>
316 as_primitive(path.res).map(|(_, prim)| {
317 // Pretend the primitive is local.
318 (id.def_id.to_def_id(), prim)
326 tcx.item_children(root).iter().map(|item| item.res).filter_map(as_primitive).collect()
331 /// Anything with a source location and set of attributes and, optionally, a
332 /// name. That is, anything that can be documented. This doesn't correspond
333 /// directly to the AST's concept of an item; it's a strict superset.
334 #[derive(Clone, Debug)]
336 /// The name of this item.
337 /// Optional because not every item has a name, e.g. impls.
338 crate name: Option<Symbol>,
339 crate attrs: Box<Attributes>,
340 crate visibility: Visibility,
341 /// Information about this item that is specific to what kind of item it is.
342 /// E.g., struct vs enum vs function.
343 crate kind: Box<ItemKind>,
344 crate def_id: FakeDefId,
346 crate cfg: Option<Arc<Cfg>>,
349 // `Item` is used a lot. Make sure it doesn't unintentionally get bigger.
350 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
351 rustc_data_structures::static_assert_size!(Item, 48);
353 crate fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
354 Span::from_rustc_span(def_id.as_local().map_or_else(
355 || tcx.def_span(def_id),
358 hir.span_with_body(hir.local_def_id_to_hir_id(local))
364 crate fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx Stability> {
365 if self.is_fake() { None } else { tcx.lookup_stability(self.def_id.expect_real()) }
368 crate fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ConstStability> {
369 if self.is_fake() { None } else { tcx.lookup_const_stability(self.def_id.expect_real()) }
372 crate fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
373 if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id.expect_real()) }
376 crate fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
377 if self.is_fake() { false } else { tcx.get_attrs(self.def_id.expect_real()).inner_docs() }
380 crate fn span(&self, tcx: TyCtxt<'_>) -> Span {
381 let kind = match &*self.kind {
382 ItemKind::StrippedItem(k) => k,
385 if let ItemKind::ModuleItem(Module { span, .. }) | ItemKind::ImplItem(Impl { span, .. }) =
389 } else if self.is_fake() {
392 rustc_span(self.def_id.expect_real(), tcx)
396 crate fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
397 crate::passes::span_of_attrs(&self.attrs).unwrap_or_else(|| self.span(tcx).inner())
400 /// Finds the `doc` attribute as a NameValue and returns the corresponding
402 crate fn doc_value(&self) -> Option<String> {
403 self.attrs.doc_value()
406 /// Convenience wrapper around [`Self::from_def_id_and_parts`] which converts
407 /// `hir_id` to a [`DefId`]
408 pub fn from_hir_id_and_parts(
410 name: Option<Symbol>,
412 cx: &mut DocContext<'_>,
414 Item::from_def_id_and_parts(cx.tcx.hir().local_def_id(hir_id).to_def_id(), name, kind, cx)
417 pub fn from_def_id_and_parts(
419 name: Option<Symbol>,
421 cx: &mut DocContext<'_>,
423 let ast_attrs = cx.tcx.get_attrs(def_id);
425 Self::from_def_id_and_attrs_and_parts(
429 box ast_attrs.clean(cx),
431 ast_attrs.cfg(cx.sess()),
435 pub fn from_def_id_and_attrs_and_parts(
437 name: Option<Symbol>,
439 attrs: Box<Attributes>,
440 cx: &mut DocContext<'_>,
441 cfg: Option<Arc<Cfg>>,
443 trace!("name={:?}, def_id={:?}", name, def_id);
446 def_id: def_id.into(),
450 visibility: cx.tcx.visibility(def_id).clean(cx),
455 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
457 crate fn collapsed_doc_value(&self) -> Option<String> {
458 self.attrs.collapsed_doc_value()
461 crate fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
462 use crate::html::format::href;
467 .map_or(&[][..], |v| v.as_slice())
469 .filter_map(|ItemLink { link: s, link_text, did, ref fragment }| {
472 if let Some((mut href, ..)) = href(did.expect_real(), cx) {
473 if let Some(ref fragment) = *fragment {
475 href.push_str(fragment);
478 original_text: s.clone(),
479 new_text: link_text.clone(),
486 // FIXME(83083): using fragments as a side-channel for
487 // primitive names is very unfortunate
489 let relative_to = &cx.current;
490 if let Some(ref fragment) = *fragment {
491 let url = match cx.cache().extern_locations.get(&self.def_id.krate()) {
492 Some(&ExternalLocation::Local) => {
493 if relative_to[0] == "std" {
494 let depth = relative_to.len() - 1;
497 let depth = relative_to.len();
498 format!("{}std/", "../".repeat(depth))
501 Some(ExternalLocation::Remote(ref s)) => {
502 format!("{}/std/", s.trim_end_matches('/'))
504 Some(ExternalLocation::Unknown) | None => {
505 "https://doc.rust-lang.org/nightly/std/".to_string()
508 // This is a primitive so the url is done "by hand".
509 let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
511 original_text: s.clone(),
512 new_text: link_text.clone(),
514 "{}primitive.{}.html{}",
521 panic!("This isn't a primitive?!");
529 crate fn is_crate(&self) -> bool {
530 self.is_mod() && self.def_id.as_real().map_or(false, |did| did.index == CRATE_DEF_INDEX)
533 crate fn is_mod(&self) -> bool {
534 self.type_() == ItemType::Module
536 crate fn is_trait(&self) -> bool {
537 self.type_() == ItemType::Trait
539 crate fn is_struct(&self) -> bool {
540 self.type_() == ItemType::Struct
542 crate fn is_enum(&self) -> bool {
543 self.type_() == ItemType::Enum
545 crate fn is_variant(&self) -> bool {
546 self.type_() == ItemType::Variant
548 crate fn is_associated_type(&self) -> bool {
549 self.type_() == ItemType::AssocType
551 crate fn is_associated_const(&self) -> bool {
552 self.type_() == ItemType::AssocConst
554 crate fn is_method(&self) -> bool {
555 self.type_() == ItemType::Method
557 crate fn is_ty_method(&self) -> bool {
558 self.type_() == ItemType::TyMethod
560 crate fn is_typedef(&self) -> bool {
561 self.type_() == ItemType::Typedef
563 crate fn is_primitive(&self) -> bool {
564 self.type_() == ItemType::Primitive
566 crate fn is_union(&self) -> bool {
567 self.type_() == ItemType::Union
569 crate fn is_import(&self) -> bool {
570 self.type_() == ItemType::Import
572 crate fn is_extern_crate(&self) -> bool {
573 self.type_() == ItemType::ExternCrate
575 crate fn is_keyword(&self) -> bool {
576 self.type_() == ItemType::Keyword
578 crate fn is_stripped(&self) -> bool {
580 StrippedItem(..) => true,
581 ImportItem(ref i) => !i.should_be_displayed,
585 crate fn has_stripped_fields(&self) -> Option<bool> {
587 StructItem(ref _struct) => Some(_struct.fields_stripped),
588 UnionItem(ref union) => Some(union.fields_stripped),
589 VariantItem(Variant::Struct(ref vstruct)) => Some(vstruct.fields_stripped),
594 crate fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
595 self.stability(tcx).as_ref().and_then(|ref s| {
596 let mut classes = Vec::with_capacity(2);
598 if s.level.is_unstable() {
599 classes.push("unstable");
602 // FIXME: what about non-staged API items that are deprecated?
603 if self.deprecation(tcx).is_some() {
604 classes.push("deprecated");
607 if !classes.is_empty() { Some(classes.join(" ")) } else { None }
611 crate fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
612 match self.stability(tcx)?.level {
613 StabilityLevel::Stable { since, .. } => Some(since.as_str()),
614 StabilityLevel::Unstable { .. } => None,
618 crate fn const_stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
619 match self.const_stability(tcx)?.level {
620 StabilityLevel::Stable { since, .. } => Some(since.as_str()),
621 StabilityLevel::Unstable { .. } => None,
625 crate fn is_non_exhaustive(&self) -> bool {
626 self.attrs.other_attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
629 /// Returns a documentation-level item type from the item.
630 crate fn type_(&self) -> ItemType {
634 crate fn is_default(&self) -> bool {
636 ItemKind::MethodItem(_, Some(defaultness)) => {
637 defaultness.has_value() && !defaultness.is_final()
643 crate fn is_fake(&self) -> bool {
644 matches!(self.def_id, FakeDefId::Fake(_, _))
648 #[derive(Clone, Debug)]
649 crate enum ItemKind {
651 /// The crate's name, *not* the name it's imported as.
658 FunctionItem(Function),
660 TypedefItem(Typedef, bool /* is associated type */),
661 OpaqueTyItem(OpaqueTy),
663 ConstantItem(Constant),
665 TraitAliasItem(TraitAlias),
667 /// A method signature only. Used for required methods in traits (ie,
668 /// non-default-methods).
669 TyMethodItem(Function),
670 /// A method with a body.
671 MethodItem(Function, Option<hir::Defaultness>),
672 StructFieldItem(Type),
673 VariantItem(Variant),
674 /// `fn`s from an extern block
675 ForeignFunctionItem(Function),
676 /// `static`s from an extern block
677 ForeignStaticItem(Static),
678 /// `type`s from an extern block
681 ProcMacroItem(ProcMacro),
682 PrimitiveItem(PrimitiveType),
683 AssocConstItem(Type, Option<String>),
684 /// An associated item in a trait or trait impl.
686 /// The bounds may be non-empty if there is a `where` clause.
687 /// The `Option<Type>` is the default concrete type (e.g. `trait Trait { type Target = usize; }`)
688 AssocTypeItem(Vec<GenericBound>, Option<Type>),
689 /// An item that has been stripped by a rustdoc pass
690 StrippedItem(Box<ItemKind>),
695 /// Some items contain others such as structs (for their fields) and Enums
696 /// (for their variants). This method returns those contained items.
697 crate fn inner_items(&self) -> impl Iterator<Item = &Item> {
699 StructItem(s) => s.fields.iter(),
700 UnionItem(u) => u.fields.iter(),
701 VariantItem(Variant::Struct(v)) => v.fields.iter(),
702 EnumItem(e) => e.variants.iter(),
703 TraitItem(t) => t.items.iter(),
704 ImplItem(i) => i.items.iter(),
705 ModuleItem(m) => m.items.iter(),
706 ExternCrateItem { .. }
718 | ForeignFunctionItem(_)
719 | ForeignStaticItem(_)
724 | AssocConstItem(_, _)
725 | AssocTypeItem(_, _)
727 | KeywordItem(_) => [].iter(),
732 #[derive(Clone, Debug)]
733 crate struct Module {
734 crate items: Vec<Item>,
738 crate struct ListAttributesIter<'a> {
739 attrs: slice::Iter<'a, ast::Attribute>,
740 current_list: vec::IntoIter<ast::NestedMetaItem>,
744 impl<'a> Iterator for ListAttributesIter<'a> {
745 type Item = ast::NestedMetaItem;
747 fn next(&mut self) -> Option<Self::Item> {
748 if let Some(nested) = self.current_list.next() {
752 for attr in &mut self.attrs {
753 if let Some(list) = attr.meta_item_list() {
754 if attr.has_name(self.name) {
755 self.current_list = list.into_iter();
756 if let Some(nested) = self.current_list.next() {
766 fn size_hint(&self) -> (usize, Option<usize>) {
767 let lower = self.current_list.len();
772 crate trait AttributesExt {
773 /// Finds an attribute as List and returns the list of attributes nested inside.
774 fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
776 fn span(&self) -> Option<rustc_span::Span>;
778 fn inner_docs(&self) -> bool;
780 fn other_attrs(&self) -> Vec<ast::Attribute>;
782 fn cfg(&self, sess: &Session) -> Option<Arc<Cfg>>;
785 impl AttributesExt for [ast::Attribute] {
786 fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
787 ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), name }
790 /// Return the span of the first doc-comment, if it exists.
791 fn span(&self) -> Option<rustc_span::Span> {
792 self.iter().find(|attr| attr.doc_str().is_some()).map(|attr| attr.span)
795 /// Returns whether the first doc-comment is an inner attribute.
797 //// If there are no doc-comments, return true.
798 /// FIXME(#78591): Support both inner and outer attributes on the same item.
799 fn inner_docs(&self) -> bool {
800 self.iter().find(|a| a.doc_str().is_some()).map_or(true, |a| a.style == AttrStyle::Inner)
803 fn other_attrs(&self) -> Vec<ast::Attribute> {
804 self.iter().filter(|attr| attr.doc_str().is_none()).cloned().collect()
807 fn cfg(&self, sess: &Session) -> Option<Arc<Cfg>> {
808 let mut cfg = Cfg::True;
810 for attr in self.iter() {
812 if attr.doc_str().is_none() && attr.has_name(sym::doc) {
814 if let Some(list) = attr.meta().as_ref().and_then(|mi| mi.meta_item_list()) {
817 if !item.has_name(sym::cfg) {
821 if let Some(cfg_mi) = item
823 .and_then(|item| rustc_expand::config::parse_cfg(&item, sess))
825 match Cfg::parse(&cfg_mi) {
826 Ok(new_cfg) => cfg &= new_cfg,
827 Err(e) => sess.span_err(e.span, e.msg),
835 for attr in self.lists(sym::target_feature) {
836 if attr.has_name(sym::enable) {
837 if let Some(feat) = attr.value_str() {
838 let meta = attr::mk_name_value_item_str(
839 Ident::with_dummy_span(sym::target_feature),
843 if let Ok(feat_cfg) = Cfg::parse(&meta) {
850 if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) }
854 crate trait NestedAttributesExt {
855 /// Returns `true` if the attribute list contains a specific `Word`
856 fn has_word(self, word: Symbol) -> bool;
857 fn get_word_attr(self, word: Symbol) -> Option<ast::NestedMetaItem>;
860 impl<I: Iterator<Item = ast::NestedMetaItem> + IntoIterator<Item = ast::NestedMetaItem>>
861 NestedAttributesExt for I
863 fn has_word(self, word: Symbol) -> bool {
864 self.into_iter().any(|attr| attr.is_word() && attr.has_name(word))
867 fn get_word_attr(mut self, word: Symbol) -> Option<ast::NestedMetaItem> {
868 self.find(|attr| attr.is_word() && attr.has_name(word))
872 /// A portion of documentation, extracted from a `#[doc]` attribute.
874 /// Each variant contains the line number within the complete doc-comment where the fragment
875 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
877 /// Included files are kept separate from inline doc comments so that proper line-number
878 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
879 /// kept separate because of issue #42760.
880 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
881 crate struct DocFragment {
883 crate span: rustc_span::Span,
884 /// The module this doc-comment came from.
886 /// This allows distinguishing between the original documentation and a pub re-export.
887 /// If it is `None`, the item was not re-exported.
888 crate parent_module: Option<DefId>,
890 crate kind: DocFragmentKind,
891 crate need_backline: bool,
895 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
896 crate enum DocFragmentKind {
897 /// A doc fragment created from a `///` or `//!` doc comment.
899 /// A doc fragment created from a "raw" `#[doc=""]` attribute.
901 /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
902 /// given filename and the file contents.
903 Include { filename: Symbol },
906 // The goal of this function is to apply the `DocFragment` transformations that are required when
907 // transforming into the final markdown. So the transformations in here are:
909 // * Applying the computed indent to each lines in each doc fragment (a `DocFragment` can contain
910 // multiple lines in case of `#[doc = ""]`).
911 // * Adding backlines between `DocFragment`s and adding an extra one if required (stored in the
912 // `need_backline` field).
913 fn add_doc_fragment(out: &mut String, frag: &DocFragment) {
914 let s = frag.doc.as_str();
915 let mut iter = s.lines().peekable();
916 while let Some(line) = iter.next() {
917 if line.chars().any(|c| !c.is_whitespace()) {
918 assert!(line.len() >= frag.indent);
919 out.push_str(&line[frag.indent..]);
923 if iter.peek().is_some() {
927 if frag.need_backline {
932 impl<'a> FromIterator<&'a DocFragment> for String {
933 fn from_iter<T>(iter: T) -> Self
935 T: IntoIterator<Item = &'a DocFragment>,
937 let mut prev_kind: Option<DocFragmentKind> = None;
938 iter.into_iter().fold(String::new(), |mut acc, frag| {
942 .map(|p| matches!(p, DocFragmentKind::Include { .. }) && p != frag.kind)
947 add_doc_fragment(&mut acc, &frag);
948 prev_kind = Some(frag.kind);
954 /// The attributes on an [`Item`], including attributes like `#[derive(...)]` and `#[inline]`,
955 /// as well as doc comments.
956 #[derive(Clone, Debug, Default)]
957 crate struct Attributes {
958 crate doc_strings: Vec<DocFragment>,
959 crate other_attrs: Vec<ast::Attribute>,
962 #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
963 /// A link that has not yet been rendered.
965 /// This link will be turned into a rendered link by [`Item::links`].
966 crate struct ItemLink {
967 /// The original link written in the markdown
968 pub(crate) link: String,
969 /// The link text displayed in the HTML.
971 /// This may not be the same as `link` if there was a disambiguator
972 /// in an intra-doc link (e.g. \[`fn@f`\])
973 pub(crate) link_text: String,
974 pub(crate) did: Option<FakeDefId>,
975 /// The url fragment to append to the link
976 pub(crate) fragment: Option<String>,
979 pub struct RenderedLink {
980 /// The text the link was original written as.
982 /// This could potentially include disambiguators and backticks.
983 pub(crate) original_text: String,
984 /// The text to display in the HTML
985 pub(crate) new_text: String,
986 /// The URL to put in the `href`
987 pub(crate) href: String,
991 crate fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
992 self.other_attrs.lists(name)
995 /// Reads a `MetaItem` from within an attribute, looks for whether it is a
996 /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
998 crate fn extract_include(mi: &ast::MetaItem) -> Option<(Symbol, Symbol)> {
999 mi.meta_item_list().and_then(|list| {
1001 if meta.has_name(sym::include) {
1002 // the actual compiled `#[doc(include="filename")]` gets expanded to
1003 // `#[doc(include(file="filename", contents="file contents")]` so we need to
1004 // look for that instead
1005 return meta.meta_item_list().and_then(|list| {
1006 let mut filename: Option<Symbol> = None;
1007 let mut contents: Option<Symbol> = None;
1010 if it.has_name(sym::file) {
1011 if let Some(name) = it.value_str() {
1012 filename = Some(name);
1014 } else if it.has_name(sym::contents) {
1015 if let Some(docs) = it.value_str() {
1016 contents = Some(docs);
1021 if let (Some(filename), Some(contents)) = (filename, contents) {
1022 Some((filename, contents))
1034 crate fn has_doc_flag(&self, flag: Symbol) -> bool {
1035 for attr in &self.other_attrs {
1036 if !attr.has_name(sym::doc) {
1040 if let Some(items) = attr.meta_item_list() {
1041 if items.iter().filter_map(|i| i.meta_item()).any(|it| it.has_name(flag)) {
1051 attrs: &[ast::Attribute],
1052 additional_attrs: Option<(&[ast::Attribute], DefId)>,
1054 let mut doc_strings: Vec<DocFragment> = vec![];
1055 let mut doc_line = 0;
1057 fn update_need_backline(doc_strings: &mut Vec<DocFragment>, frag: &DocFragment) {
1058 if let Some(prev) = doc_strings.last_mut() {
1059 if matches!(prev.kind, DocFragmentKind::Include { .. })
1060 || prev.kind != frag.kind
1061 || prev.parent_module != frag.parent_module
1063 // add a newline for extra padding between segments
1064 prev.need_backline = prev.kind == DocFragmentKind::SugaredDoc
1065 || prev.kind == DocFragmentKind::RawDoc
1067 prev.need_backline = true;
1072 let clean_attr = |(attr, parent_module): (&ast::Attribute, Option<DefId>)| {
1073 if let Some(value) = attr.doc_str() {
1074 trace!("got doc_str={:?}", value);
1075 let value = beautify_doc_string(value);
1076 let kind = if attr.is_doc_comment() {
1077 DocFragmentKind::SugaredDoc
1079 DocFragmentKind::RawDoc
1082 let line = doc_line;
1083 doc_line += value.as_str().lines().count();
1084 let frag = DocFragment {
1090 need_backline: false,
1094 update_need_backline(&mut doc_strings, &frag);
1096 doc_strings.push(frag);
1100 if attr.has_name(sym::doc) {
1101 if let Some(mi) = attr.meta() {
1102 if let Some((filename, contents)) = Attributes::extract_include(&mi) {
1103 let line = doc_line;
1104 doc_line += contents.as_str().lines().count();
1105 let frag = DocFragment {
1109 kind: DocFragmentKind::Include { filename },
1111 need_backline: false,
1114 update_need_backline(&mut doc_strings, &frag);
1115 doc_strings.push(frag);
1123 // Additional documentation should be shown before the original documentation
1124 let other_attrs = additional_attrs
1126 .map(|(attrs, id)| attrs.iter().map(move |attr| (attr, Some(id))))
1128 .chain(attrs.iter().map(|attr| (attr, None)))
1129 .filter_map(clean_attr)
1132 Attributes { doc_strings, other_attrs }
1135 /// Finds the `doc` attribute as a NameValue and returns the corresponding
1137 crate fn doc_value(&self) -> Option<String> {
1138 let mut iter = self.doc_strings.iter();
1140 let ori = iter.next()?;
1141 let mut out = String::new();
1142 add_doc_fragment(&mut out, &ori);
1143 while let Some(new_frag) = iter.next() {
1144 if matches!(ori.kind, DocFragmentKind::Include { .. })
1145 || new_frag.kind != ori.kind
1146 || new_frag.parent_module != ori.parent_module
1150 add_doc_fragment(&mut out, &new_frag);
1152 if out.is_empty() { None } else { Some(out) }
1155 /// Return the doc-comments on this item, grouped by the module they came from.
1157 /// The module can be different if this is a re-export with added documentation.
1158 crate fn collapsed_doc_value_by_module_level(&self) -> FxHashMap<Option<DefId>, String> {
1159 let mut ret = FxHashMap::default();
1161 for new_frag in self.doc_strings.iter() {
1162 let out = ret.entry(new_frag.parent_module).or_default();
1163 add_doc_fragment(out, &new_frag);
1168 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
1170 crate fn collapsed_doc_value(&self) -> Option<String> {
1171 if self.doc_strings.is_empty() { None } else { Some(self.doc_strings.iter().collect()) }
1174 crate fn get_doc_aliases(&self) -> Box<[String]> {
1175 let mut aliases = FxHashSet::default();
1177 for attr in self.other_attrs.lists(sym::doc).filter(|a| a.has_name(sym::alias)) {
1178 if let Some(values) = attr.meta_item_list() {
1180 match l.literal().unwrap().kind {
1181 ast::LitKind::Str(s, _) => {
1182 aliases.insert(s.as_str().to_string());
1184 _ => unreachable!(),
1188 aliases.insert(attr.value_str().map(|s| s.to_string()).unwrap());
1191 aliases.into_iter().collect::<Vec<String>>().into()
1195 impl PartialEq for Attributes {
1196 fn eq(&self, rhs: &Self) -> bool {
1197 self.doc_strings == rhs.doc_strings
1201 .map(|attr| attr.id)
1202 .eq(rhs.other_attrs.iter().map(|attr| attr.id))
1206 impl Eq for Attributes {}
1208 impl Hash for Attributes {
1209 fn hash<H: Hasher>(&self, hasher: &mut H) {
1210 self.doc_strings.hash(hasher);
1211 for attr in &self.other_attrs {
1212 attr.id.hash(hasher);
1217 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1218 crate enum GenericBound {
1219 TraitBound(PolyTrait, hir::TraitBoundModifier),
1224 crate fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1225 let did = cx.tcx.require_lang_item(LangItem::Sized, None);
1226 let empty = cx.tcx.intern_substs(&[]);
1227 let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
1228 inline::record_extern_fqn(cx, did, ItemType::Trait);
1229 GenericBound::TraitBound(
1231 trait_: ResolvedPath { path, param_names: None, did, is_generic: false },
1232 generic_params: Vec::new(),
1234 hir::TraitBoundModifier::Maybe,
1238 crate fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1239 use rustc_hir::TraitBoundModifier as TBM;
1240 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
1241 if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
1248 crate fn get_poly_trait(&self) -> Option<PolyTrait> {
1249 if let GenericBound::TraitBound(ref p, _) = *self {
1250 return Some(p.clone());
1255 crate fn get_trait_type(&self) -> Option<Type> {
1256 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1257 Some(trait_.clone())
1264 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1265 crate struct Lifetime(pub Symbol);
1268 crate fn get_ref(&self) -> SymbolStr {
1272 crate fn statik() -> Lifetime {
1273 Lifetime(kw::StaticLifetime)
1276 crate fn elided() -> Lifetime {
1277 Lifetime(kw::UnderscoreLifetime)
1281 #[derive(Clone, Debug)]
1282 crate enum WherePredicate {
1283 BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
1284 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1285 EqPredicate { lhs: Type, rhs: Type },
1288 impl WherePredicate {
1289 crate fn get_bounds(&self) -> Option<&[GenericBound]> {
1291 WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
1292 WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
1298 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1299 crate enum GenericParamDefKind {
1303 bounds: Vec<GenericBound>,
1304 default: Option<Type>,
1305 synthetic: Option<hir::SyntheticTyParamKind>,
1313 impl GenericParamDefKind {
1314 crate fn is_type(&self) -> bool {
1315 matches!(self, GenericParamDefKind::Type { .. })
1318 // FIXME(eddyb) this either returns the default of a type parameter, or the
1319 // type of a `const` parameter. It seems that the intention is to *visit*
1320 // any embedded types, but `get_type` seems to be the wrong name for that.
1321 crate fn get_type(&self) -> Option<Type> {
1323 GenericParamDefKind::Type { default, .. } => default.clone(),
1324 GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
1325 GenericParamDefKind::Lifetime => None,
1330 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1331 crate struct GenericParamDef {
1333 crate kind: GenericParamDefKind,
1336 impl GenericParamDef {
1337 crate fn is_synthetic_type_param(&self) -> bool {
1339 GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => false,
1340 GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
1344 crate fn is_type(&self) -> bool {
1348 crate fn get_type(&self) -> Option<Type> {
1349 self.kind.get_type()
1352 crate fn get_bounds(&self) -> Option<&[GenericBound]> {
1354 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1360 // maybe use a Generic enum and use Vec<Generic>?
1361 #[derive(Clone, Debug, Default)]
1362 crate struct Generics {
1363 crate params: Vec<GenericParamDef>,
1364 crate where_predicates: Vec<WherePredicate>,
1367 #[derive(Clone, Debug)]
1368 crate struct Function {
1370 crate generics: Generics,
1371 crate header: hir::FnHeader,
1374 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1375 crate struct FnDecl {
1376 crate inputs: Arguments,
1377 crate output: FnRetTy,
1378 crate c_variadic: bool,
1382 crate fn self_type(&self) -> Option<SelfTy> {
1383 self.inputs.values.get(0).and_then(|v| v.to_self())
1386 /// Returns the sugared return type for an async function.
1388 /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
1389 /// will return `i32`.
1393 /// This function will panic if the return type does not match the expected sugaring for async
1395 crate fn sugared_async_return_type(&self) -> FnRetTy {
1396 match &self.output {
1397 FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
1398 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
1399 let bindings = trait_.bindings().unwrap();
1400 FnRetTy::Return(bindings[0].ty().clone())
1402 _ => panic!("unexpected desugaring of async function"),
1404 _ => panic!("unexpected desugaring of async function"),
1409 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1410 crate struct Arguments {
1411 crate values: Vec<Argument>,
1414 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1415 crate struct Argument {
1420 #[derive(Clone, PartialEq, Debug)]
1423 SelfBorrowed(Option<Lifetime>, Mutability),
1428 crate fn to_self(&self) -> Option<SelfTy> {
1429 if self.name != kw::SelfLower {
1432 if self.type_.is_self_type() {
1433 return Some(SelfValue);
1436 BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
1437 Some(SelfBorrowed(lifetime.clone(), mutability))
1439 _ => Some(SelfExplicit(self.type_.clone())),
1444 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1445 crate enum FnRetTy {
1450 impl GetDefId for FnRetTy {
1451 fn def_id(&self) -> Option<DefId> {
1453 Return(ref ty) => ty.def_id(),
1454 DefaultReturn => None,
1458 fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
1460 Return(ref ty) => ty.def_id_full(cache),
1461 DefaultReturn => None,
1466 #[derive(Clone, Debug)]
1467 crate struct Trait {
1468 crate unsafety: hir::Unsafety,
1469 crate items: Vec<Item>,
1470 crate generics: Generics,
1471 crate bounds: Vec<GenericBound>,
1472 crate is_auto: bool,
1475 #[derive(Clone, Debug)]
1476 crate struct TraitAlias {
1477 crate generics: Generics,
1478 crate bounds: Vec<GenericBound>,
1481 /// A trait reference, which may have higher ranked lifetimes.
1482 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1483 crate struct PolyTrait {
1485 crate generic_params: Vec<GenericParamDef>,
1488 /// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
1489 /// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
1490 /// importantly, it does not preserve mutability or boxes.
1491 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1493 /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
1496 param_names: Option<Vec<GenericBound>>,
1498 /// `true` if is a `T::Name` path for associated types.
1501 /// For parameterized types, so the consumer of the JSON don't go
1502 /// looking for types which don't exist anywhere.
1504 /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
1505 /// arrays, slices, and tuples.
1506 Primitive(PrimitiveType),
1507 /// `extern "ABI" fn`
1508 BareFunction(Box<BareFunctionDecl>),
1511 /// The `String` field is about the size or the constant representing the array's length.
1512 Array(Box<Type>, String),
1514 RawPointer(Mutability, Box<Type>),
1516 lifetime: Option<Lifetime>,
1517 mutability: Mutability,
1521 // `<Type as Trait>::Name`
1524 self_type: Box<Type>,
1531 // `impl TraitA + TraitB + ...`
1532 ImplTrait(Vec<GenericBound>),
1535 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1536 /// N.B. this has to be different from `hir::PrimTy` because it also includes types that aren't
1537 /// paths, like `Unit`.
1538 crate enum PrimitiveType {
1566 crate trait GetDefId {
1567 /// Use this method to get the [`DefId`] of a [`clean`] AST node.
1568 /// This will return [`None`] when called on a primitive [`clean::Type`].
1569 /// Use [`Self::def_id_full`] if you want to include primitives.
1571 /// [`clean`]: crate::clean
1572 /// [`clean::Type`]: crate::clean::Type
1573 // FIXME: get rid of this function and always use `def_id_full`
1574 fn def_id(&self) -> Option<DefId>;
1576 /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s.
1578 /// See [`Self::def_id`] for more.
1580 /// [clean]: crate::clean
1581 fn def_id_full(&self, cache: &Cache) -> Option<DefId>;
1584 impl<T: GetDefId> GetDefId for Option<T> {
1585 fn def_id(&self) -> Option<DefId> {
1586 self.as_ref().and_then(|d| d.def_id())
1589 fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
1590 self.as_ref().and_then(|d| d.def_id_full(cache))
1595 crate fn primitive_type(&self) -> Option<PrimitiveType> {
1597 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1598 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1599 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1602 Some(PrimitiveType::Unit)
1604 Some(PrimitiveType::Tuple)
1607 RawPointer(..) => Some(PrimitiveType::RawPointer),
1608 BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
1609 BareFunction(..) => Some(PrimitiveType::Fn),
1610 Never => Some(PrimitiveType::Never),
1615 crate fn is_generic(&self) -> bool {
1617 ResolvedPath { is_generic, .. } => is_generic,
1622 crate fn is_self_type(&self) -> bool {
1624 Generic(name) => name == kw::SelfUpper,
1629 crate fn generics(&self) -> Option<Vec<&Type>> {
1631 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1632 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
1635 .filter_map(|arg| match arg {
1636 GenericArg::Type(ty) => Some(ty),
1649 crate fn bindings(&self) -> Option<&[TypeBinding]> {
1651 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1652 if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
1662 crate fn is_full_generic(&self) -> bool {
1663 matches!(self, Type::Generic(_))
1666 crate fn is_primitive(&self) -> bool {
1668 Self::Primitive(_) => true,
1669 Self::BorrowedRef { ref type_, .. } | Self::RawPointer(_, ref type_) => {
1670 type_.is_primitive()
1676 crate fn projection(&self) -> Option<(&Type, DefId, Symbol)> {
1677 let (self_, trait_, name) = match self {
1678 QPath { self_type, trait_, name } => (self_type, trait_, name),
1681 let trait_did = match **trait_ {
1682 ResolvedPath { did, .. } => did,
1685 Some((&self_, trait_did, *name))
1690 fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
1691 let t: PrimitiveType = match *self {
1692 ResolvedPath { did, .. } => return Some(did.into()),
1693 Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
1694 BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
1695 BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache),
1700 PrimitiveType::Tuple
1703 BareFunction(..) => PrimitiveType::Fn,
1704 Never => PrimitiveType::Never,
1705 Slice(..) => PrimitiveType::Slice,
1706 Array(..) => PrimitiveType::Array,
1707 RawPointer(..) => PrimitiveType::RawPointer,
1708 QPath { ref self_type, .. } => return self_type.inner_def_id(cache),
1709 Generic(_) | Infer | ImplTrait(_) => return None,
1711 cache.and_then(|c| Primitive(t).def_id_full(c))
1715 impl GetDefId for Type {
1716 fn def_id(&self) -> Option<DefId> {
1717 self.inner_def_id(None)
1720 fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
1721 self.inner_def_id(Some(cache))
1725 impl PrimitiveType {
1726 crate fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1727 use ast::{FloatTy, IntTy, UintTy};
1729 hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1730 hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1731 hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1732 hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1733 hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1734 hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1735 hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1736 hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1737 hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1738 hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1739 hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1740 hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1741 hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1742 hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1743 hir::PrimTy::Str => PrimitiveType::Str,
1744 hir::PrimTy::Bool => PrimitiveType::Bool,
1745 hir::PrimTy::Char => PrimitiveType::Char,
1749 crate fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1751 sym::isize => Some(PrimitiveType::Isize),
1752 sym::i8 => Some(PrimitiveType::I8),
1753 sym::i16 => Some(PrimitiveType::I16),
1754 sym::i32 => Some(PrimitiveType::I32),
1755 sym::i64 => Some(PrimitiveType::I64),
1756 sym::i128 => Some(PrimitiveType::I128),
1757 sym::usize => Some(PrimitiveType::Usize),
1758 sym::u8 => Some(PrimitiveType::U8),
1759 sym::u16 => Some(PrimitiveType::U16),
1760 sym::u32 => Some(PrimitiveType::U32),
1761 sym::u64 => Some(PrimitiveType::U64),
1762 sym::u128 => Some(PrimitiveType::U128),
1763 sym::bool => Some(PrimitiveType::Bool),
1764 sym::char => Some(PrimitiveType::Char),
1765 sym::str => Some(PrimitiveType::Str),
1766 sym::f32 => Some(PrimitiveType::F32),
1767 sym::f64 => Some(PrimitiveType::F64),
1768 sym::array => Some(PrimitiveType::Array),
1769 sym::slice => Some(PrimitiveType::Slice),
1770 sym::tuple => Some(PrimitiveType::Tuple),
1771 sym::unit => Some(PrimitiveType::Unit),
1772 sym::pointer => Some(PrimitiveType::RawPointer),
1773 sym::reference => Some(PrimitiveType::Reference),
1774 kw::Fn => Some(PrimitiveType::Fn),
1775 sym::never => Some(PrimitiveType::Never),
1780 crate fn as_str(&self) -> &'static str {
1781 use self::PrimitiveType::*;
1804 RawPointer => "pointer",
1805 Reference => "reference",
1811 crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static ArrayVec<DefId, 4> {
1812 Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
1815 crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, ArrayVec<DefId, 4>> {
1816 static CELL: OnceCell<FxHashMap<PrimitiveType, ArrayVec<DefId, 4>>> = OnceCell::new();
1818 CELL.get_or_init(move || {
1819 use self::PrimitiveType::*;
1821 let single = |a: Option<DefId>| a.into_iter().collect();
1822 let both = |a: Option<DefId>, b: Option<DefId>| -> ArrayVec<_, 4> {
1823 a.into_iter().chain(b).collect()
1826 let lang_items = tcx.lang_items();
1828 Isize => single(lang_items.isize_impl()),
1829 I8 => single(lang_items.i8_impl()),
1830 I16 => single(lang_items.i16_impl()),
1831 I32 => single(lang_items.i32_impl()),
1832 I64 => single(lang_items.i64_impl()),
1833 I128 => single(lang_items.i128_impl()),
1834 Usize => single(lang_items.usize_impl()),
1835 U8 => single(lang_items.u8_impl()),
1836 U16 => single(lang_items.u16_impl()),
1837 U32 => single(lang_items.u32_impl()),
1838 U64 => single(lang_items.u64_impl()),
1839 U128 => single(lang_items.u128_impl()),
1840 F32 => both(lang_items.f32_impl(), lang_items.f32_runtime_impl()),
1841 F64 => both(lang_items.f64_impl(), lang_items.f64_runtime_impl()),
1842 Char => single(lang_items.char_impl()),
1843 Bool => single(lang_items.bool_impl()),
1844 Str => both(lang_items.str_impl(), lang_items.str_alloc_impl()),
1849 .chain(lang_items.slice_u8_impl())
1850 .chain(lang_items.slice_alloc_impl())
1851 .chain(lang_items.slice_u8_alloc_impl())
1854 Array => single(lang_items.array_impl()),
1855 Tuple => ArrayVec::new(),
1856 Unit => ArrayVec::new(),
1861 .chain(lang_items.mut_ptr_impl())
1862 .chain(lang_items.const_slice_ptr_impl())
1863 .chain(lang_items.mut_slice_ptr_impl())
1866 Reference => ArrayVec::new(),
1867 Fn => ArrayVec::new(),
1868 Never => ArrayVec::new(),
1873 crate fn to_url_str(&self) -> &'static str {
1877 crate fn as_sym(&self) -> Symbol {
1878 use PrimitiveType::*;
1880 Isize => sym::isize,
1886 Usize => sym::usize,
1897 Array => sym::array,
1898 Slice => sym::slice,
1899 Tuple => sym::tuple,
1901 RawPointer => sym::pointer,
1902 Reference => sym::reference,
1904 Never => sym::never,
1909 impl From<ast::IntTy> for PrimitiveType {
1910 fn from(int_ty: ast::IntTy) -> PrimitiveType {
1912 ast::IntTy::Isize => PrimitiveType::Isize,
1913 ast::IntTy::I8 => PrimitiveType::I8,
1914 ast::IntTy::I16 => PrimitiveType::I16,
1915 ast::IntTy::I32 => PrimitiveType::I32,
1916 ast::IntTy::I64 => PrimitiveType::I64,
1917 ast::IntTy::I128 => PrimitiveType::I128,
1922 impl From<ast::UintTy> for PrimitiveType {
1923 fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1925 ast::UintTy::Usize => PrimitiveType::Usize,
1926 ast::UintTy::U8 => PrimitiveType::U8,
1927 ast::UintTy::U16 => PrimitiveType::U16,
1928 ast::UintTy::U32 => PrimitiveType::U32,
1929 ast::UintTy::U64 => PrimitiveType::U64,
1930 ast::UintTy::U128 => PrimitiveType::U128,
1935 impl From<ast::FloatTy> for PrimitiveType {
1936 fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1938 ast::FloatTy::F32 => PrimitiveType::F32,
1939 ast::FloatTy::F64 => PrimitiveType::F64,
1944 impl From<ty::IntTy> for PrimitiveType {
1945 fn from(int_ty: ty::IntTy) -> PrimitiveType {
1947 ty::IntTy::Isize => PrimitiveType::Isize,
1948 ty::IntTy::I8 => PrimitiveType::I8,
1949 ty::IntTy::I16 => PrimitiveType::I16,
1950 ty::IntTy::I32 => PrimitiveType::I32,
1951 ty::IntTy::I64 => PrimitiveType::I64,
1952 ty::IntTy::I128 => PrimitiveType::I128,
1957 impl From<ty::UintTy> for PrimitiveType {
1958 fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1960 ty::UintTy::Usize => PrimitiveType::Usize,
1961 ty::UintTy::U8 => PrimitiveType::U8,
1962 ty::UintTy::U16 => PrimitiveType::U16,
1963 ty::UintTy::U32 => PrimitiveType::U32,
1964 ty::UintTy::U64 => PrimitiveType::U64,
1965 ty::UintTy::U128 => PrimitiveType::U128,
1970 impl From<ty::FloatTy> for PrimitiveType {
1971 fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1973 ty::FloatTy::F32 => PrimitiveType::F32,
1974 ty::FloatTy::F64 => PrimitiveType::F64,
1979 impl From<hir::PrimTy> for PrimitiveType {
1980 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1982 hir::PrimTy::Int(int_ty) => int_ty.into(),
1983 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1984 hir::PrimTy::Float(float_ty) => float_ty.into(),
1985 hir::PrimTy::Str => PrimitiveType::Str,
1986 hir::PrimTy::Bool => PrimitiveType::Bool,
1987 hir::PrimTy::Char => PrimitiveType::Char,
1992 #[derive(Copy, Clone, Debug)]
1993 crate enum Visibility {
1996 /// Visibility inherited from parent.
1998 /// For example, this is the visibility of private items and of enum variants.
2000 /// `pub(crate)`, `pub(super)`, or `pub(in path::to::somewhere)`
2005 crate fn is_public(&self) -> bool {
2006 matches!(self, Visibility::Public)
2010 #[derive(Clone, Debug)]
2011 crate struct Struct {
2012 crate struct_type: CtorKind,
2013 crate generics: Generics,
2014 crate fields: Vec<Item>,
2015 crate fields_stripped: bool,
2018 #[derive(Clone, Debug)]
2019 crate struct Union {
2020 crate generics: Generics,
2021 crate fields: Vec<Item>,
2022 crate fields_stripped: bool,
2025 /// This is a more limited form of the standard Struct, different in that
2026 /// it lacks the things most items have (name, id, parameterization). Found
2027 /// only as a variant in an enum.
2028 #[derive(Clone, Debug)]
2029 crate struct VariantStruct {
2030 crate struct_type: CtorKind,
2031 crate fields: Vec<Item>,
2032 crate fields_stripped: bool,
2035 #[derive(Clone, Debug)]
2037 crate variants: IndexVec<VariantIdx, Item>,
2038 crate generics: Generics,
2039 crate variants_stripped: bool,
2042 #[derive(Clone, Debug)]
2043 crate enum Variant {
2046 Struct(VariantStruct),
2049 /// Small wrapper around [`rustc_span::Span]` that adds helper methods
2050 /// and enforces calling [`rustc_span::Span::source_callsite()`].
2051 #[derive(Copy, Clone, Debug)]
2052 crate struct Span(rustc_span::Span);
2055 crate fn from_rustc_span(sp: rustc_span::Span) -> Self {
2056 // Get the macro invocation instead of the definition,
2057 // in case the span is result of a macro expansion.
2058 // (See rust-lang/rust#39726)
2059 Self(sp.source_callsite())
2062 crate fn inner(&self) -> rustc_span::Span {
2066 crate fn dummy() -> Self {
2067 Self(rustc_span::DUMMY_SP)
2070 crate fn is_dummy(&self) -> bool {
2074 crate fn filename(&self, sess: &Session) -> FileName {
2075 sess.source_map().span_to_filename(self.0)
2078 crate fn lo(&self, sess: &Session) -> Loc {
2079 sess.source_map().lookup_char_pos(self.0.lo())
2082 crate fn hi(&self, sess: &Session) -> Loc {
2083 sess.source_map().lookup_char_pos(self.0.hi())
2086 crate fn cnum(&self, sess: &Session) -> CrateNum {
2087 // FIXME: is there a time when the lo and hi crate would be different?
2088 self.lo(sess).file.cnum
2092 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2096 crate segments: Vec<PathSegment>,
2100 crate fn last(&self) -> Symbol {
2101 self.segments.last().expect("segments were empty").name
2104 crate fn last_name(&self) -> SymbolStr {
2105 self.segments.last().expect("segments were empty").name.as_str()
2108 crate fn whole_name(&self) -> String {
2109 String::from(if self.global { "::" } else { "" })
2110 + &self.segments.iter().map(|s| s.name.to_string()).collect::<Vec<_>>().join("::")
2114 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2115 crate enum GenericArg {
2121 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2122 crate enum GenericArgs {
2123 AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
2124 Parenthesized { inputs: Vec<Type>, output: Option<Type> },
2127 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2128 crate struct PathSegment {
2130 crate args: GenericArgs,
2133 #[derive(Clone, Debug)]
2134 crate struct Typedef {
2136 crate generics: Generics,
2137 /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
2138 /// alias instead of the final type. This will always have the final type, regardless of whether
2139 /// `type_` came from HIR or from metadata.
2141 /// If `item_type.is_none()`, `type_` is guarenteed to come from metadata (and therefore hold the
2143 crate item_type: Option<Type>,
2146 impl GetDefId for Typedef {
2147 fn def_id(&self) -> Option<DefId> {
2151 fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
2152 self.type_.def_id_full(cache)
2156 #[derive(Clone, Debug)]
2157 crate struct OpaqueTy {
2158 crate bounds: Vec<GenericBound>,
2159 crate generics: Generics,
2162 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2163 crate struct BareFunctionDecl {
2164 crate unsafety: hir::Unsafety,
2165 crate generic_params: Vec<GenericParamDef>,
2170 #[derive(Clone, Debug)]
2171 crate struct Static {
2173 crate mutability: Mutability,
2174 crate expr: Option<BodyId>,
2177 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2178 crate struct Constant {
2180 crate kind: ConstantKind,
2183 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2184 crate enum ConstantKind {
2185 /// This is the wrapper around `ty::Const` for a non-local constant. Because it doesn't have a
2186 /// `BodyId`, we need to handle it on its own.
2188 /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified
2189 /// by a DefId. So this field must be different from `Extern`.
2190 TyConst { expr: String },
2191 /// A constant (expression) that's not an item or associated item. These are usually found
2192 /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
2193 /// used to define explicit discriminant values for enum variants.
2194 Anonymous { body: BodyId },
2195 /// A constant from a different crate.
2196 Extern { def_id: DefId },
2197 /// `const FOO: u32 = ...;`
2198 Local { def_id: DefId, body: BodyId },
2202 crate fn expr(&self, tcx: TyCtxt<'_>) -> String {
2204 ConstantKind::TyConst { ref expr } => expr.clone(),
2205 ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2206 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2207 print_const_expr(tcx, body)
2212 crate fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2214 ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
2215 ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2216 print_evaluated_const(tcx, def_id)
2221 crate fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2223 ConstantKind::TyConst { .. } => false,
2224 ConstantKind::Extern { def_id } => def_id.as_local().map_or(false, |def_id| {
2225 is_literal_expr(tcx, tcx.hir().local_def_id_to_hir_id(def_id))
2227 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2228 is_literal_expr(tcx, body.hir_id)
2234 #[derive(Clone, Debug)]
2237 crate unsafety: hir::Unsafety,
2238 crate generics: Generics,
2239 crate trait_: Option<Type>,
2241 crate items: Vec<Item>,
2242 crate negative_polarity: bool,
2243 crate synthetic: bool,
2244 crate blanket_impl: Option<Type>,
2248 crate fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxHashSet<Symbol> {
2251 .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.ident.name).collect())
2252 .unwrap_or_default()
2256 #[derive(Clone, Debug)]
2257 crate struct Import {
2258 crate kind: ImportKind,
2259 crate source: ImportSource,
2260 crate should_be_displayed: bool,
2264 crate fn new_simple(name: Symbol, source: ImportSource, should_be_displayed: bool) -> Self {
2265 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2268 crate fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2269 Self { kind: ImportKind::Glob, source, should_be_displayed }
2273 #[derive(Clone, Debug)]
2274 crate enum ImportKind {
2275 // use source as str;
2281 #[derive(Clone, Debug)]
2282 crate struct ImportSource {
2284 crate did: Option<DefId>,
2287 #[derive(Clone, Debug)]
2288 crate struct Macro {
2289 crate source: String,
2290 crate imported_from: Option<Symbol>,
2293 #[derive(Clone, Debug)]
2294 crate struct ProcMacro {
2295 crate kind: MacroKind,
2296 crate helpers: Vec<Symbol>,
2299 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
2300 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
2301 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2302 crate struct TypeBinding {
2304 crate kind: TypeBindingKind,
2307 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2308 crate enum TypeBindingKind {
2309 Equality { ty: Type },
2310 Constraint { bounds: Vec<GenericBound> },
2314 crate fn ty(&self) -> &Type {
2316 TypeBindingKind::Equality { ref ty } => ty,
2317 _ => panic!("expected equality type binding for parenthesized generic args"),