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, LocalDefId, 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 as_local(self) -> Option<LocalDefId> {
91 FakeDefId::Real(id) => id.as_local(),
92 FakeDefId::Fake(idx, krate) => {
93 (krate == LOCAL_CRATE).then(|| LocalDefId { local_def_index: idx })
99 crate fn expect_local(self) -> LocalDefId {
101 .unwrap_or_else(|| panic!("FakeDefId::expect_local: `{:?}` isn't local", self))
105 crate fn expect_real(self) -> rustc_hir::def_id::DefId {
106 self.as_real().unwrap_or_else(|| panic!("FakeDefId::expect_real: `{:?}` isn't real", self))
110 crate fn as_real(self) -> Option<DefId> {
112 FakeDefId::Real(id) => Some(id),
113 FakeDefId::Fake(_, _) => None,
118 crate fn krate(self) -> CrateNum {
120 FakeDefId::Real(id) => id.krate,
121 FakeDefId::Fake(_, krate) => krate,
126 crate fn index(self) -> Option<DefIndex> {
128 FakeDefId::Real(id) => Some(id.index),
129 FakeDefId::Fake(_, _) => None,
134 impl From<DefId> for FakeDefId {
135 fn from(id: DefId) -> Self {
140 #[derive(Clone, Debug)]
145 crate externs: Vec<(CrateNum, ExternalCrate)>,
146 crate primitives: ThinVec<(DefId, PrimitiveType)>,
147 // These are later on moved into `CACHEKEY`, leaving the map empty.
148 // Only here so that they can be filtered through the rustdoc passes.
149 crate external_traits: Rc<RefCell<FxHashMap<DefId, TraitWithExtraInfo>>>,
150 crate collapsed: bool,
153 /// This struct is used to wrap additional information added by rustdoc on a `trait` item.
154 #[derive(Clone, Debug)]
155 crate struct TraitWithExtraInfo {
157 crate is_notable: bool,
160 #[derive(Clone, Debug)]
161 crate struct ExternalCrate {
162 crate crate_num: CrateNum,
167 fn def_id(&self) -> DefId {
168 DefId { krate: self.crate_num, index: CRATE_DEF_INDEX }
171 crate fn src(&self, tcx: TyCtxt<'_>) -> FileName {
172 let krate_span = tcx.def_span(self.def_id());
173 tcx.sess.source_map().span_to_filename(krate_span)
176 crate fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
177 tcx.crate_name(self.crate_num)
180 crate fn src_root(&self, tcx: TyCtxt<'_>) -> PathBuf {
181 match self.src(tcx) {
182 FileName::Real(ref p) => match p.local_path().parent() {
183 Some(p) => p.to_path_buf(),
184 None => PathBuf::new(),
190 /// Attempts to find where an external crate is located, given that we're
191 /// rendering in to the specified source destination.
194 extern_url: Option<&str>,
195 dst: &std::path::Path,
197 ) -> ExternalLocation {
198 use ExternalLocation::*;
200 fn to_remote(url: impl ToString) -> ExternalLocation {
201 let mut url = url.to_string();
202 if !url.ends_with('/') {
208 // See if there's documentation generated into the local directory
209 // WARNING: since rustdoc creates these directories as it generates documentation, this check is only accurate before rendering starts.
210 // Make sure to call `location()` by that time.
211 let local_location = dst.join(&*self.name(tcx).as_str());
212 if local_location.is_dir() {
216 if let Some(url) = extern_url {
217 return to_remote(url);
220 // Failing that, see if there's an attribute specifying where to find this
222 let did = DefId { krate: self.crate_num, index: CRATE_DEF_INDEX };
225 .filter(|a| a.has_name(sym::html_root_url))
226 .filter_map(|a| a.value_str())
229 .unwrap_or(Unknown) // Well, at least we tried.
232 crate fn keywords(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, Symbol)> {
233 let root = self.def_id();
235 let as_keyword = |res: Res| {
236 if let Res::Def(DefKind::Mod, def_id) = res {
237 let attrs = tcx.get_attrs(def_id);
238 let mut keyword = None;
239 for attr in attrs.lists(sym::doc) {
240 if attr.has_name(sym::keyword) {
241 if let Some(v) = attr.value_str() {
247 return keyword.map(|p| (def_id, p));
258 let item = tcx.hir().item(id);
260 hir::ItemKind::Mod(_) => {
261 as_keyword(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
263 hir::ItemKind::Use(ref path, hir::UseKind::Single)
264 if item.vis.node.is_pub() =>
266 as_keyword(path.res).map(|(_, prim)| (id.def_id.to_def_id(), prim))
273 tcx.item_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect()
277 crate fn primitives(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, PrimitiveType)> {
278 let root = self.def_id();
280 // Collect all inner modules which are tagged as implementations of
283 // Note that this loop only searches the top-level items of the crate,
284 // and this is intentional. If we were to search the entire crate for an
285 // item tagged with `#[doc(primitive)]` then we would also have to
286 // search the entirety of external modules for items tagged
287 // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
288 // all that metadata unconditionally).
290 // In order to keep the metadata load under control, the
291 // `#[doc(primitive)]` feature is explicitly designed to only allow the
292 // primitive tags to show up as the top level items in a crate.
294 // Also note that this does not attempt to deal with modules tagged
295 // duplicately for the same primitive. This is handled later on when
296 // rendering by delegating everything to a hash map.
297 let as_primitive = |res: Res| {
298 if let Res::Def(DefKind::Mod, def_id) = res {
299 let attrs = tcx.get_attrs(def_id);
301 for attr in attrs.lists(sym::doc) {
302 if let Some(v) = attr.value_str() {
303 if attr.has_name(sym::primitive) {
304 prim = PrimitiveType::from_symbol(v);
308 // FIXME: should warn on unknown primitives?
312 return prim.map(|p| (def_id, p));
324 let item = tcx.hir().item(id);
326 hir::ItemKind::Mod(_) => {
327 as_primitive(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
329 hir::ItemKind::Use(ref path, hir::UseKind::Single)
330 if item.vis.node.is_pub() =>
332 as_primitive(path.res).map(|(_, prim)| {
333 // Pretend the primitive is local.
334 (id.def_id.to_def_id(), prim)
342 tcx.item_children(root).iter().map(|item| item.res).filter_map(as_primitive).collect()
347 /// Anything with a source location and set of attributes and, optionally, a
348 /// name. That is, anything that can be documented. This doesn't correspond
349 /// directly to the AST's concept of an item; it's a strict superset.
350 #[derive(Clone, Debug)]
352 /// The name of this item.
353 /// Optional because not every item has a name, e.g. impls.
354 crate name: Option<Symbol>,
355 crate attrs: Box<Attributes>,
356 crate visibility: Visibility,
357 /// Information about this item that is specific to what kind of item it is.
358 /// E.g., struct vs enum vs function.
359 crate kind: Box<ItemKind>,
360 crate def_id: FakeDefId,
362 crate cfg: Option<Arc<Cfg>>,
365 // `Item` is used a lot. Make sure it doesn't unintentionally get bigger.
366 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
367 rustc_data_structures::static_assert_size!(Item, 48);
369 crate fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
370 Span::from_rustc_span(def_id.as_local().map_or_else(
371 || tcx.def_span(def_id),
374 hir.span_with_body(hir.local_def_id_to_hir_id(local))
380 crate fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx Stability> {
381 if self.is_fake() { None } else { tcx.lookup_stability(self.def_id.expect_real()) }
384 crate fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ConstStability> {
385 if self.is_fake() { None } else { tcx.lookup_const_stability(self.def_id.expect_real()) }
388 crate fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
389 if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id.expect_real()) }
392 crate fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
393 if self.is_fake() { false } else { tcx.get_attrs(self.def_id.expect_real()).inner_docs() }
396 crate fn span(&self, tcx: TyCtxt<'_>) -> Span {
397 let kind = match &*self.kind {
398 ItemKind::StrippedItem(k) => k,
401 if let ItemKind::ModuleItem(Module { span, .. }) | ItemKind::ImplItem(Impl { span, .. }) =
405 } else if self.is_fake() {
408 rustc_span(self.def_id.expect_real(), tcx)
412 crate fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
413 crate::passes::span_of_attrs(&self.attrs).unwrap_or_else(|| self.span(tcx).inner())
416 /// Finds the `doc` attribute as a NameValue and returns the corresponding
418 crate fn doc_value(&self) -> Option<String> {
419 self.attrs.doc_value()
422 /// Convenience wrapper around [`Self::from_def_id_and_parts`] which converts
423 /// `hir_id` to a [`DefId`]
424 pub fn from_hir_id_and_parts(
426 name: Option<Symbol>,
428 cx: &mut DocContext<'_>,
430 Item::from_def_id_and_parts(cx.tcx.hir().local_def_id(hir_id).to_def_id(), name, kind, cx)
433 pub fn from_def_id_and_parts(
435 name: Option<Symbol>,
437 cx: &mut DocContext<'_>,
439 let ast_attrs = cx.tcx.get_attrs(def_id);
441 Self::from_def_id_and_attrs_and_parts(
445 box ast_attrs.clean(cx),
447 ast_attrs.cfg(cx.sess()),
451 pub fn from_def_id_and_attrs_and_parts(
453 name: Option<Symbol>,
455 attrs: Box<Attributes>,
456 cx: &mut DocContext<'_>,
457 cfg: Option<Arc<Cfg>>,
459 trace!("name={:?}, def_id={:?}", name, def_id);
462 def_id: def_id.into(),
466 visibility: cx.tcx.visibility(def_id).clean(cx),
471 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
473 crate fn collapsed_doc_value(&self) -> Option<String> {
474 self.attrs.collapsed_doc_value()
477 crate fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
478 use crate::html::format::href;
483 .map_or(&[][..], |v| v.as_slice())
485 .filter_map(|ItemLink { link: s, link_text, did, ref fragment }| {
488 if let Some((mut href, ..)) = href(did.expect_real(), cx) {
489 if let Some(ref fragment) = *fragment {
491 href.push_str(fragment);
494 original_text: s.clone(),
495 new_text: link_text.clone(),
502 // FIXME(83083): using fragments as a side-channel for
503 // primitive names is very unfortunate
505 let relative_to = &cx.current;
506 if let Some(ref fragment) = *fragment {
507 let url = match cx.cache().extern_locations.get(&self.def_id.krate()) {
508 Some(&ExternalLocation::Local) => {
509 if relative_to[0] == "std" {
510 let depth = relative_to.len() - 1;
513 let depth = relative_to.len();
514 format!("{}std/", "../".repeat(depth))
517 Some(ExternalLocation::Remote(ref s)) => {
518 format!("{}/std/", s.trim_end_matches('/'))
520 Some(ExternalLocation::Unknown) | None => {
521 "https://doc.rust-lang.org/nightly/std/".to_string()
524 // This is a primitive so the url is done "by hand".
525 let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
527 original_text: s.clone(),
528 new_text: link_text.clone(),
530 "{}primitive.{}.html{}",
537 panic!("This isn't a primitive?!");
545 crate fn is_crate(&self) -> bool {
546 self.is_mod() && self.def_id.as_real().map_or(false, |did| did.index == CRATE_DEF_INDEX)
549 crate fn is_mod(&self) -> bool {
550 self.type_() == ItemType::Module
552 crate fn is_trait(&self) -> bool {
553 self.type_() == ItemType::Trait
555 crate fn is_struct(&self) -> bool {
556 self.type_() == ItemType::Struct
558 crate fn is_enum(&self) -> bool {
559 self.type_() == ItemType::Enum
561 crate fn is_variant(&self) -> bool {
562 self.type_() == ItemType::Variant
564 crate fn is_associated_type(&self) -> bool {
565 self.type_() == ItemType::AssocType
567 crate fn is_associated_const(&self) -> bool {
568 self.type_() == ItemType::AssocConst
570 crate fn is_method(&self) -> bool {
571 self.type_() == ItemType::Method
573 crate fn is_ty_method(&self) -> bool {
574 self.type_() == ItemType::TyMethod
576 crate fn is_typedef(&self) -> bool {
577 self.type_() == ItemType::Typedef
579 crate fn is_primitive(&self) -> bool {
580 self.type_() == ItemType::Primitive
582 crate fn is_union(&self) -> bool {
583 self.type_() == ItemType::Union
585 crate fn is_import(&self) -> bool {
586 self.type_() == ItemType::Import
588 crate fn is_extern_crate(&self) -> bool {
589 self.type_() == ItemType::ExternCrate
591 crate fn is_keyword(&self) -> bool {
592 self.type_() == ItemType::Keyword
594 crate fn is_stripped(&self) -> bool {
596 StrippedItem(..) => true,
597 ImportItem(ref i) => !i.should_be_displayed,
601 crate fn has_stripped_fields(&self) -> Option<bool> {
603 StructItem(ref _struct) => Some(_struct.fields_stripped),
604 UnionItem(ref union) => Some(union.fields_stripped),
605 VariantItem(Variant::Struct(ref vstruct)) => Some(vstruct.fields_stripped),
610 crate fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
611 self.stability(tcx).as_ref().and_then(|ref s| {
612 let mut classes = Vec::with_capacity(2);
614 if s.level.is_unstable() {
615 classes.push("unstable");
618 // FIXME: what about non-staged API items that are deprecated?
619 if self.deprecation(tcx).is_some() {
620 classes.push("deprecated");
623 if !classes.is_empty() { Some(classes.join(" ")) } else { None }
627 crate fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
628 match self.stability(tcx)?.level {
629 StabilityLevel::Stable { since, .. } => Some(since.as_str()),
630 StabilityLevel::Unstable { .. } => None,
634 crate fn const_stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
635 match self.const_stability(tcx)?.level {
636 StabilityLevel::Stable { since, .. } => Some(since.as_str()),
637 StabilityLevel::Unstable { .. } => None,
641 crate fn is_non_exhaustive(&self) -> bool {
642 self.attrs.other_attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
645 /// Returns a documentation-level item type from the item.
646 crate fn type_(&self) -> ItemType {
650 crate fn is_default(&self) -> bool {
652 ItemKind::MethodItem(_, Some(defaultness)) => {
653 defaultness.has_value() && !defaultness.is_final()
659 crate fn is_fake(&self) -> bool {
660 matches!(self.def_id, FakeDefId::Fake(_, _))
664 #[derive(Clone, Debug)]
665 crate enum ItemKind {
667 /// The crate's name, *not* the name it's imported as.
674 FunctionItem(Function),
676 TypedefItem(Typedef, bool /* is associated type */),
677 OpaqueTyItem(OpaqueTy),
679 ConstantItem(Constant),
681 TraitAliasItem(TraitAlias),
683 /// A method signature only. Used for required methods in traits (ie,
684 /// non-default-methods).
685 TyMethodItem(Function),
686 /// A method with a body.
687 MethodItem(Function, Option<hir::Defaultness>),
688 StructFieldItem(Type),
689 VariantItem(Variant),
690 /// `fn`s from an extern block
691 ForeignFunctionItem(Function),
692 /// `static`s from an extern block
693 ForeignStaticItem(Static),
694 /// `type`s from an extern block
697 ProcMacroItem(ProcMacro),
698 PrimitiveItem(PrimitiveType),
699 AssocConstItem(Type, Option<String>),
700 /// An associated item in a trait or trait impl.
702 /// The bounds may be non-empty if there is a `where` clause.
703 /// The `Option<Type>` is the default concrete type (e.g. `trait Trait { type Target = usize; }`)
704 AssocTypeItem(Vec<GenericBound>, Option<Type>),
705 /// An item that has been stripped by a rustdoc pass
706 StrippedItem(Box<ItemKind>),
711 /// Some items contain others such as structs (for their fields) and Enums
712 /// (for their variants). This method returns those contained items.
713 crate fn inner_items(&self) -> impl Iterator<Item = &Item> {
715 StructItem(s) => s.fields.iter(),
716 UnionItem(u) => u.fields.iter(),
717 VariantItem(Variant::Struct(v)) => v.fields.iter(),
718 EnumItem(e) => e.variants.iter(),
719 TraitItem(t) => t.items.iter(),
720 ImplItem(i) => i.items.iter(),
721 ModuleItem(m) => m.items.iter(),
722 ExternCrateItem { .. }
734 | ForeignFunctionItem(_)
735 | ForeignStaticItem(_)
740 | AssocConstItem(_, _)
741 | AssocTypeItem(_, _)
743 | KeywordItem(_) => [].iter(),
748 #[derive(Clone, Debug)]
749 crate struct Module {
750 crate items: Vec<Item>,
754 crate struct ListAttributesIter<'a> {
755 attrs: slice::Iter<'a, ast::Attribute>,
756 current_list: vec::IntoIter<ast::NestedMetaItem>,
760 impl<'a> Iterator for ListAttributesIter<'a> {
761 type Item = ast::NestedMetaItem;
763 fn next(&mut self) -> Option<Self::Item> {
764 if let Some(nested) = self.current_list.next() {
768 for attr in &mut self.attrs {
769 if let Some(list) = attr.meta_item_list() {
770 if attr.has_name(self.name) {
771 self.current_list = list.into_iter();
772 if let Some(nested) = self.current_list.next() {
782 fn size_hint(&self) -> (usize, Option<usize>) {
783 let lower = self.current_list.len();
788 crate trait AttributesExt {
789 /// Finds an attribute as List and returns the list of attributes nested inside.
790 fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
792 fn span(&self) -> Option<rustc_span::Span>;
794 fn inner_docs(&self) -> bool;
796 fn other_attrs(&self) -> Vec<ast::Attribute>;
798 fn cfg(&self, sess: &Session) -> Option<Arc<Cfg>>;
801 impl AttributesExt for [ast::Attribute] {
802 fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
803 ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), name }
806 /// Return the span of the first doc-comment, if it exists.
807 fn span(&self) -> Option<rustc_span::Span> {
808 self.iter().find(|attr| attr.doc_str().is_some()).map(|attr| attr.span)
811 /// Returns whether the first doc-comment is an inner attribute.
813 //// If there are no doc-comments, return true.
814 /// FIXME(#78591): Support both inner and outer attributes on the same item.
815 fn inner_docs(&self) -> bool {
816 self.iter().find(|a| a.doc_str().is_some()).map_or(true, |a| a.style == AttrStyle::Inner)
819 fn other_attrs(&self) -> Vec<ast::Attribute> {
820 self.iter().filter(|attr| attr.doc_str().is_none()).cloned().collect()
823 fn cfg(&self, sess: &Session) -> Option<Arc<Cfg>> {
824 let mut cfg = Cfg::True;
826 for attr in self.iter() {
828 if attr.doc_str().is_none() && attr.has_name(sym::doc) {
830 if let Some(list) = attr.meta().as_ref().and_then(|mi| mi.meta_item_list()) {
833 if !item.has_name(sym::cfg) {
837 if let Some(cfg_mi) = item
839 .and_then(|item| rustc_expand::config::parse_cfg(&item, sess))
841 match Cfg::parse(&cfg_mi) {
842 Ok(new_cfg) => cfg &= new_cfg,
843 Err(e) => sess.span_err(e.span, e.msg),
851 for attr in self.lists(sym::target_feature) {
852 if attr.has_name(sym::enable) {
853 if let Some(feat) = attr.value_str() {
854 let meta = attr::mk_name_value_item_str(
855 Ident::with_dummy_span(sym::target_feature),
859 if let Ok(feat_cfg) = Cfg::parse(&meta) {
866 if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) }
870 crate trait NestedAttributesExt {
871 /// Returns `true` if the attribute list contains a specific `Word`
872 fn has_word(self, word: Symbol) -> bool;
873 fn get_word_attr(self, word: Symbol) -> Option<ast::NestedMetaItem>;
876 impl<I: Iterator<Item = ast::NestedMetaItem> + IntoIterator<Item = ast::NestedMetaItem>>
877 NestedAttributesExt for I
879 fn has_word(self, word: Symbol) -> bool {
880 self.into_iter().any(|attr| attr.is_word() && attr.has_name(word))
883 fn get_word_attr(mut self, word: Symbol) -> Option<ast::NestedMetaItem> {
884 self.find(|attr| attr.is_word() && attr.has_name(word))
888 /// A portion of documentation, extracted from a `#[doc]` attribute.
890 /// Each variant contains the line number within the complete doc-comment where the fragment
891 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
893 /// Included files are kept separate from inline doc comments so that proper line-number
894 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
895 /// kept separate because of issue #42760.
896 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
897 crate struct DocFragment {
899 crate span: rustc_span::Span,
900 /// The module this doc-comment came from.
902 /// This allows distinguishing between the original documentation and a pub re-export.
903 /// If it is `None`, the item was not re-exported.
904 crate parent_module: Option<DefId>,
906 crate kind: DocFragmentKind,
907 crate need_backline: bool,
911 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
912 crate enum DocFragmentKind {
913 /// A doc fragment created from a `///` or `//!` doc comment.
915 /// A doc fragment created from a "raw" `#[doc=""]` attribute.
917 /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
918 /// given filename and the file contents.
919 Include { filename: Symbol },
922 // The goal of this function is to apply the `DocFragment` transformations that are required when
923 // transforming into the final markdown. So the transformations in here are:
925 // * Applying the computed indent to each lines in each doc fragment (a `DocFragment` can contain
926 // multiple lines in case of `#[doc = ""]`).
927 // * Adding backlines between `DocFragment`s and adding an extra one if required (stored in the
928 // `need_backline` field).
929 fn add_doc_fragment(out: &mut String, frag: &DocFragment) {
930 let s = frag.doc.as_str();
931 let mut iter = s.lines().peekable();
932 while let Some(line) = iter.next() {
933 if line.chars().any(|c| !c.is_whitespace()) {
934 assert!(line.len() >= frag.indent);
935 out.push_str(&line[frag.indent..]);
939 if iter.peek().is_some() {
943 if frag.need_backline {
948 impl<'a> FromIterator<&'a DocFragment> for String {
949 fn from_iter<T>(iter: T) -> Self
951 T: IntoIterator<Item = &'a DocFragment>,
953 let mut prev_kind: Option<DocFragmentKind> = None;
954 iter.into_iter().fold(String::new(), |mut acc, frag| {
958 .map(|p| matches!(p, DocFragmentKind::Include { .. }) && p != frag.kind)
963 add_doc_fragment(&mut acc, &frag);
964 prev_kind = Some(frag.kind);
970 /// The attributes on an [`Item`], including attributes like `#[derive(...)]` and `#[inline]`,
971 /// as well as doc comments.
972 #[derive(Clone, Debug, Default)]
973 crate struct Attributes {
974 crate doc_strings: Vec<DocFragment>,
975 crate other_attrs: Vec<ast::Attribute>,
978 #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
979 /// A link that has not yet been rendered.
981 /// This link will be turned into a rendered link by [`Item::links`].
982 crate struct ItemLink {
983 /// The original link written in the markdown
984 pub(crate) link: String,
985 /// The link text displayed in the HTML.
987 /// This may not be the same as `link` if there was a disambiguator
988 /// in an intra-doc link (e.g. \[`fn@f`\])
989 pub(crate) link_text: String,
990 pub(crate) did: Option<FakeDefId>,
991 /// The url fragment to append to the link
992 pub(crate) fragment: Option<String>,
995 pub struct RenderedLink {
996 /// The text the link was original written as.
998 /// This could potentially include disambiguators and backticks.
999 pub(crate) original_text: String,
1000 /// The text to display in the HTML
1001 pub(crate) new_text: String,
1002 /// The URL to put in the `href`
1003 pub(crate) href: String,
1007 crate fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
1008 self.other_attrs.lists(name)
1011 /// Reads a `MetaItem` from within an attribute, looks for whether it is a
1012 /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
1014 crate fn extract_include(mi: &ast::MetaItem) -> Option<(Symbol, Symbol)> {
1015 mi.meta_item_list().and_then(|list| {
1017 if meta.has_name(sym::include) {
1018 // the actual compiled `#[doc(include="filename")]` gets expanded to
1019 // `#[doc(include(file="filename", contents="file contents")]` so we need to
1020 // look for that instead
1021 return meta.meta_item_list().and_then(|list| {
1022 let mut filename: Option<Symbol> = None;
1023 let mut contents: Option<Symbol> = None;
1026 if it.has_name(sym::file) {
1027 if let Some(name) = it.value_str() {
1028 filename = Some(name);
1030 } else if it.has_name(sym::contents) {
1031 if let Some(docs) = it.value_str() {
1032 contents = Some(docs);
1037 if let (Some(filename), Some(contents)) = (filename, contents) {
1038 Some((filename, contents))
1050 crate fn has_doc_flag(&self, flag: Symbol) -> bool {
1051 for attr in &self.other_attrs {
1052 if !attr.has_name(sym::doc) {
1056 if let Some(items) = attr.meta_item_list() {
1057 if items.iter().filter_map(|i| i.meta_item()).any(|it| it.has_name(flag)) {
1067 attrs: &[ast::Attribute],
1068 additional_attrs: Option<(&[ast::Attribute], DefId)>,
1070 let mut doc_strings: Vec<DocFragment> = vec![];
1071 let mut doc_line = 0;
1073 fn update_need_backline(doc_strings: &mut Vec<DocFragment>, frag: &DocFragment) {
1074 if let Some(prev) = doc_strings.last_mut() {
1075 if matches!(prev.kind, DocFragmentKind::Include { .. })
1076 || prev.kind != frag.kind
1077 || prev.parent_module != frag.parent_module
1079 // add a newline for extra padding between segments
1080 prev.need_backline = prev.kind == DocFragmentKind::SugaredDoc
1081 || prev.kind == DocFragmentKind::RawDoc
1083 prev.need_backline = true;
1088 let clean_attr = |(attr, parent_module): (&ast::Attribute, Option<DefId>)| {
1089 if let Some(value) = attr.doc_str() {
1090 trace!("got doc_str={:?}", value);
1091 let value = beautify_doc_string(value);
1092 let kind = if attr.is_doc_comment() {
1093 DocFragmentKind::SugaredDoc
1095 DocFragmentKind::RawDoc
1098 let line = doc_line;
1099 doc_line += value.as_str().lines().count();
1100 let frag = DocFragment {
1106 need_backline: false,
1110 update_need_backline(&mut doc_strings, &frag);
1112 doc_strings.push(frag);
1116 if attr.has_name(sym::doc) {
1117 if let Some(mi) = attr.meta() {
1118 if let Some((filename, contents)) = Attributes::extract_include(&mi) {
1119 let line = doc_line;
1120 doc_line += contents.as_str().lines().count();
1121 let frag = DocFragment {
1125 kind: DocFragmentKind::Include { filename },
1127 need_backline: false,
1130 update_need_backline(&mut doc_strings, &frag);
1131 doc_strings.push(frag);
1139 // Additional documentation should be shown before the original documentation
1140 let other_attrs = additional_attrs
1142 .map(|(attrs, id)| attrs.iter().map(move |attr| (attr, Some(id))))
1144 .chain(attrs.iter().map(|attr| (attr, None)))
1145 .filter_map(clean_attr)
1148 Attributes { doc_strings, other_attrs }
1151 /// Finds the `doc` attribute as a NameValue and returns the corresponding
1153 crate fn doc_value(&self) -> Option<String> {
1154 let mut iter = self.doc_strings.iter();
1156 let ori = iter.next()?;
1157 let mut out = String::new();
1158 add_doc_fragment(&mut out, &ori);
1159 while let Some(new_frag) = iter.next() {
1160 if matches!(ori.kind, DocFragmentKind::Include { .. })
1161 || new_frag.kind != ori.kind
1162 || new_frag.parent_module != ori.parent_module
1166 add_doc_fragment(&mut out, &new_frag);
1168 if out.is_empty() { None } else { Some(out) }
1171 /// Return the doc-comments on this item, grouped by the module they came from.
1173 /// The module can be different if this is a re-export with added documentation.
1174 crate fn collapsed_doc_value_by_module_level(&self) -> FxHashMap<Option<DefId>, String> {
1175 let mut ret = FxHashMap::default();
1177 for new_frag in self.doc_strings.iter() {
1178 let out = ret.entry(new_frag.parent_module).or_default();
1179 add_doc_fragment(out, &new_frag);
1184 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
1186 crate fn collapsed_doc_value(&self) -> Option<String> {
1187 if self.doc_strings.is_empty() { None } else { Some(self.doc_strings.iter().collect()) }
1190 crate fn get_doc_aliases(&self) -> Box<[String]> {
1191 let mut aliases = FxHashSet::default();
1193 for attr in self.other_attrs.lists(sym::doc).filter(|a| a.has_name(sym::alias)) {
1194 if let Some(values) = attr.meta_item_list() {
1196 match l.literal().unwrap().kind {
1197 ast::LitKind::Str(s, _) => {
1198 aliases.insert(s.as_str().to_string());
1200 _ => unreachable!(),
1204 aliases.insert(attr.value_str().map(|s| s.to_string()).unwrap());
1207 aliases.into_iter().collect::<Vec<String>>().into()
1211 impl PartialEq for Attributes {
1212 fn eq(&self, rhs: &Self) -> bool {
1213 self.doc_strings == rhs.doc_strings
1217 .map(|attr| attr.id)
1218 .eq(rhs.other_attrs.iter().map(|attr| attr.id))
1222 impl Eq for Attributes {}
1224 impl Hash for Attributes {
1225 fn hash<H: Hasher>(&self, hasher: &mut H) {
1226 self.doc_strings.hash(hasher);
1227 for attr in &self.other_attrs {
1228 attr.id.hash(hasher);
1233 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1234 crate enum GenericBound {
1235 TraitBound(PolyTrait, hir::TraitBoundModifier),
1240 crate fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1241 let did = cx.tcx.require_lang_item(LangItem::Sized, None);
1242 let empty = cx.tcx.intern_substs(&[]);
1243 let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
1244 inline::record_extern_fqn(cx, did, ItemType::Trait);
1245 GenericBound::TraitBound(
1247 trait_: ResolvedPath { path, param_names: None, did, is_generic: false },
1248 generic_params: Vec::new(),
1250 hir::TraitBoundModifier::Maybe,
1254 crate fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1255 use rustc_hir::TraitBoundModifier as TBM;
1256 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
1257 if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
1264 crate fn get_poly_trait(&self) -> Option<PolyTrait> {
1265 if let GenericBound::TraitBound(ref p, _) = *self {
1266 return Some(p.clone());
1271 crate fn get_trait_type(&self) -> Option<Type> {
1272 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1273 Some(trait_.clone())
1280 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1281 crate struct Lifetime(pub Symbol);
1284 crate fn get_ref(&self) -> SymbolStr {
1288 crate fn statik() -> Lifetime {
1289 Lifetime(kw::StaticLifetime)
1292 crate fn elided() -> Lifetime {
1293 Lifetime(kw::UnderscoreLifetime)
1297 #[derive(Clone, Debug)]
1298 crate enum WherePredicate {
1299 BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
1300 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1301 EqPredicate { lhs: Type, rhs: Type },
1304 impl WherePredicate {
1305 crate fn get_bounds(&self) -> Option<&[GenericBound]> {
1307 WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
1308 WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
1314 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1315 crate enum GenericParamDefKind {
1319 bounds: Vec<GenericBound>,
1320 default: Option<Type>,
1321 synthetic: Option<hir::SyntheticTyParamKind>,
1329 impl GenericParamDefKind {
1330 crate fn is_type(&self) -> bool {
1331 matches!(self, GenericParamDefKind::Type { .. })
1334 // FIXME(eddyb) this either returns the default of a type parameter, or the
1335 // type of a `const` parameter. It seems that the intention is to *visit*
1336 // any embedded types, but `get_type` seems to be the wrong name for that.
1337 crate fn get_type(&self) -> Option<Type> {
1339 GenericParamDefKind::Type { default, .. } => default.clone(),
1340 GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
1341 GenericParamDefKind::Lifetime => None,
1346 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1347 crate struct GenericParamDef {
1349 crate kind: GenericParamDefKind,
1352 impl GenericParamDef {
1353 crate fn is_synthetic_type_param(&self) -> bool {
1355 GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => false,
1356 GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
1360 crate fn is_type(&self) -> bool {
1364 crate fn get_type(&self) -> Option<Type> {
1365 self.kind.get_type()
1368 crate fn get_bounds(&self) -> Option<&[GenericBound]> {
1370 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1376 // maybe use a Generic enum and use Vec<Generic>?
1377 #[derive(Clone, Debug, Default)]
1378 crate struct Generics {
1379 crate params: Vec<GenericParamDef>,
1380 crate where_predicates: Vec<WherePredicate>,
1383 #[derive(Clone, Debug)]
1384 crate struct Function {
1386 crate generics: Generics,
1387 crate header: hir::FnHeader,
1390 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1391 crate struct FnDecl {
1392 crate inputs: Arguments,
1393 crate output: FnRetTy,
1394 crate c_variadic: bool,
1398 crate fn self_type(&self) -> Option<SelfTy> {
1399 self.inputs.values.get(0).and_then(|v| v.to_self())
1402 /// Returns the sugared return type for an async function.
1404 /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
1405 /// will return `i32`.
1409 /// This function will panic if the return type does not match the expected sugaring for async
1411 crate fn sugared_async_return_type(&self) -> FnRetTy {
1412 match &self.output {
1413 FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
1414 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
1415 let bindings = trait_.bindings().unwrap();
1416 FnRetTy::Return(bindings[0].ty().clone())
1418 _ => panic!("unexpected desugaring of async function"),
1420 _ => panic!("unexpected desugaring of async function"),
1425 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1426 crate struct Arguments {
1427 crate values: Vec<Argument>,
1430 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1431 crate struct Argument {
1436 #[derive(Clone, PartialEq, Debug)]
1439 SelfBorrowed(Option<Lifetime>, Mutability),
1444 crate fn to_self(&self) -> Option<SelfTy> {
1445 if self.name != kw::SelfLower {
1448 if self.type_.is_self_type() {
1449 return Some(SelfValue);
1452 BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
1453 Some(SelfBorrowed(lifetime.clone(), mutability))
1455 _ => Some(SelfExplicit(self.type_.clone())),
1460 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1461 crate enum FnRetTy {
1466 impl GetDefId for FnRetTy {
1467 fn def_id(&self) -> Option<DefId> {
1469 Return(ref ty) => ty.def_id(),
1470 DefaultReturn => None,
1474 fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
1476 Return(ref ty) => ty.def_id_full(cache),
1477 DefaultReturn => None,
1482 #[derive(Clone, Debug)]
1483 crate struct Trait {
1484 crate unsafety: hir::Unsafety,
1485 crate items: Vec<Item>,
1486 crate generics: Generics,
1487 crate bounds: Vec<GenericBound>,
1488 crate is_auto: bool,
1491 #[derive(Clone, Debug)]
1492 crate struct TraitAlias {
1493 crate generics: Generics,
1494 crate bounds: Vec<GenericBound>,
1497 /// A trait reference, which may have higher ranked lifetimes.
1498 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1499 crate struct PolyTrait {
1501 crate generic_params: Vec<GenericParamDef>,
1504 /// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
1505 /// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
1506 /// importantly, it does not preserve mutability or boxes.
1507 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1509 /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
1512 param_names: Option<Vec<GenericBound>>,
1514 /// `true` if is a `T::Name` path for associated types.
1517 /// For parameterized types, so the consumer of the JSON don't go
1518 /// looking for types which don't exist anywhere.
1520 /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
1521 /// arrays, slices, and tuples.
1522 Primitive(PrimitiveType),
1523 /// `extern "ABI" fn`
1524 BareFunction(Box<BareFunctionDecl>),
1527 /// The `String` field is about the size or the constant representing the array's length.
1528 Array(Box<Type>, String),
1530 RawPointer(Mutability, Box<Type>),
1532 lifetime: Option<Lifetime>,
1533 mutability: Mutability,
1537 // `<Type as Trait>::Name`
1540 self_type: Box<Type>,
1547 // `impl TraitA + TraitB + ...`
1548 ImplTrait(Vec<GenericBound>),
1551 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1552 /// N.B. this has to be different from `hir::PrimTy` because it also includes types that aren't
1553 /// paths, like `Unit`.
1554 crate enum PrimitiveType {
1582 crate trait GetDefId {
1583 /// Use this method to get the [`DefId`] of a [`clean`] AST node.
1584 /// This will return [`None`] when called on a primitive [`clean::Type`].
1585 /// Use [`Self::def_id_full`] if you want to include primitives.
1587 /// [`clean`]: crate::clean
1588 /// [`clean::Type`]: crate::clean::Type
1589 // FIXME: get rid of this function and always use `def_id_full`
1590 fn def_id(&self) -> Option<DefId>;
1592 /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s.
1594 /// See [`Self::def_id`] for more.
1596 /// [clean]: crate::clean
1597 fn def_id_full(&self, cache: &Cache) -> Option<DefId>;
1600 impl<T: GetDefId> GetDefId for Option<T> {
1601 fn def_id(&self) -> Option<DefId> {
1602 self.as_ref().and_then(|d| d.def_id())
1605 fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
1606 self.as_ref().and_then(|d| d.def_id_full(cache))
1611 crate fn primitive_type(&self) -> Option<PrimitiveType> {
1613 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1614 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1615 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1618 Some(PrimitiveType::Unit)
1620 Some(PrimitiveType::Tuple)
1623 RawPointer(..) => Some(PrimitiveType::RawPointer),
1624 BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
1625 BareFunction(..) => Some(PrimitiveType::Fn),
1626 Never => Some(PrimitiveType::Never),
1631 crate fn is_generic(&self) -> bool {
1633 ResolvedPath { is_generic, .. } => is_generic,
1638 crate fn is_self_type(&self) -> bool {
1640 Generic(name) => name == kw::SelfUpper,
1645 crate fn generics(&self) -> Option<Vec<&Type>> {
1647 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1648 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
1651 .filter_map(|arg| match arg {
1652 GenericArg::Type(ty) => Some(ty),
1665 crate fn bindings(&self) -> Option<&[TypeBinding]> {
1667 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1668 if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
1678 crate fn is_full_generic(&self) -> bool {
1679 matches!(self, Type::Generic(_))
1682 crate fn is_primitive(&self) -> bool {
1684 Self::Primitive(_) => true,
1685 Self::BorrowedRef { ref type_, .. } | Self::RawPointer(_, ref type_) => {
1686 type_.is_primitive()
1692 crate fn projection(&self) -> Option<(&Type, DefId, Symbol)> {
1693 let (self_, trait_, name) = match self {
1694 QPath { self_type, trait_, name } => (self_type, trait_, name),
1697 let trait_did = match **trait_ {
1698 ResolvedPath { did, .. } => did,
1701 Some((&self_, trait_did, *name))
1706 fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
1707 let t: PrimitiveType = match *self {
1708 ResolvedPath { did, .. } => return Some(did.into()),
1709 Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
1710 BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
1711 BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache),
1716 PrimitiveType::Tuple
1719 BareFunction(..) => PrimitiveType::Fn,
1720 Never => PrimitiveType::Never,
1721 Slice(..) => PrimitiveType::Slice,
1722 Array(..) => PrimitiveType::Array,
1723 RawPointer(..) => PrimitiveType::RawPointer,
1724 QPath { ref self_type, .. } => return self_type.inner_def_id(cache),
1725 Generic(_) | Infer | ImplTrait(_) => return None,
1727 cache.and_then(|c| Primitive(t).def_id_full(c))
1731 impl GetDefId for Type {
1732 fn def_id(&self) -> Option<DefId> {
1733 self.inner_def_id(None)
1736 fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
1737 self.inner_def_id(Some(cache))
1741 impl PrimitiveType {
1742 crate fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1743 use ast::{FloatTy, IntTy, UintTy};
1745 hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1746 hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1747 hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1748 hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1749 hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1750 hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1751 hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1752 hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1753 hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1754 hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1755 hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1756 hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1757 hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1758 hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1759 hir::PrimTy::Str => PrimitiveType::Str,
1760 hir::PrimTy::Bool => PrimitiveType::Bool,
1761 hir::PrimTy::Char => PrimitiveType::Char,
1765 crate fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1767 sym::isize => Some(PrimitiveType::Isize),
1768 sym::i8 => Some(PrimitiveType::I8),
1769 sym::i16 => Some(PrimitiveType::I16),
1770 sym::i32 => Some(PrimitiveType::I32),
1771 sym::i64 => Some(PrimitiveType::I64),
1772 sym::i128 => Some(PrimitiveType::I128),
1773 sym::usize => Some(PrimitiveType::Usize),
1774 sym::u8 => Some(PrimitiveType::U8),
1775 sym::u16 => Some(PrimitiveType::U16),
1776 sym::u32 => Some(PrimitiveType::U32),
1777 sym::u64 => Some(PrimitiveType::U64),
1778 sym::u128 => Some(PrimitiveType::U128),
1779 sym::bool => Some(PrimitiveType::Bool),
1780 sym::char => Some(PrimitiveType::Char),
1781 sym::str => Some(PrimitiveType::Str),
1782 sym::f32 => Some(PrimitiveType::F32),
1783 sym::f64 => Some(PrimitiveType::F64),
1784 sym::array => Some(PrimitiveType::Array),
1785 sym::slice => Some(PrimitiveType::Slice),
1786 sym::tuple => Some(PrimitiveType::Tuple),
1787 sym::unit => Some(PrimitiveType::Unit),
1788 sym::pointer => Some(PrimitiveType::RawPointer),
1789 sym::reference => Some(PrimitiveType::Reference),
1790 kw::Fn => Some(PrimitiveType::Fn),
1791 sym::never => Some(PrimitiveType::Never),
1796 crate fn as_str(&self) -> &'static str {
1797 use self::PrimitiveType::*;
1820 RawPointer => "pointer",
1821 Reference => "reference",
1827 crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static ArrayVec<DefId, 4> {
1828 Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
1831 crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, ArrayVec<DefId, 4>> {
1832 static CELL: OnceCell<FxHashMap<PrimitiveType, ArrayVec<DefId, 4>>> = OnceCell::new();
1834 CELL.get_or_init(move || {
1835 use self::PrimitiveType::*;
1837 let single = |a: Option<DefId>| a.into_iter().collect();
1838 let both = |a: Option<DefId>, b: Option<DefId>| -> ArrayVec<_, 4> {
1839 a.into_iter().chain(b).collect()
1842 let lang_items = tcx.lang_items();
1844 Isize => single(lang_items.isize_impl()),
1845 I8 => single(lang_items.i8_impl()),
1846 I16 => single(lang_items.i16_impl()),
1847 I32 => single(lang_items.i32_impl()),
1848 I64 => single(lang_items.i64_impl()),
1849 I128 => single(lang_items.i128_impl()),
1850 Usize => single(lang_items.usize_impl()),
1851 U8 => single(lang_items.u8_impl()),
1852 U16 => single(lang_items.u16_impl()),
1853 U32 => single(lang_items.u32_impl()),
1854 U64 => single(lang_items.u64_impl()),
1855 U128 => single(lang_items.u128_impl()),
1856 F32 => both(lang_items.f32_impl(), lang_items.f32_runtime_impl()),
1857 F64 => both(lang_items.f64_impl(), lang_items.f64_runtime_impl()),
1858 Char => single(lang_items.char_impl()),
1859 Bool => single(lang_items.bool_impl()),
1860 Str => both(lang_items.str_impl(), lang_items.str_alloc_impl()),
1865 .chain(lang_items.slice_u8_impl())
1866 .chain(lang_items.slice_alloc_impl())
1867 .chain(lang_items.slice_u8_alloc_impl())
1870 Array => single(lang_items.array_impl()),
1871 Tuple => ArrayVec::new(),
1872 Unit => ArrayVec::new(),
1877 .chain(lang_items.mut_ptr_impl())
1878 .chain(lang_items.const_slice_ptr_impl())
1879 .chain(lang_items.mut_slice_ptr_impl())
1882 Reference => ArrayVec::new(),
1883 Fn => ArrayVec::new(),
1884 Never => ArrayVec::new(),
1889 crate fn to_url_str(&self) -> &'static str {
1893 crate fn as_sym(&self) -> Symbol {
1894 use PrimitiveType::*;
1896 Isize => sym::isize,
1902 Usize => sym::usize,
1913 Array => sym::array,
1914 Slice => sym::slice,
1915 Tuple => sym::tuple,
1917 RawPointer => sym::pointer,
1918 Reference => sym::reference,
1920 Never => sym::never,
1925 impl From<ast::IntTy> for PrimitiveType {
1926 fn from(int_ty: ast::IntTy) -> PrimitiveType {
1928 ast::IntTy::Isize => PrimitiveType::Isize,
1929 ast::IntTy::I8 => PrimitiveType::I8,
1930 ast::IntTy::I16 => PrimitiveType::I16,
1931 ast::IntTy::I32 => PrimitiveType::I32,
1932 ast::IntTy::I64 => PrimitiveType::I64,
1933 ast::IntTy::I128 => PrimitiveType::I128,
1938 impl From<ast::UintTy> for PrimitiveType {
1939 fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1941 ast::UintTy::Usize => PrimitiveType::Usize,
1942 ast::UintTy::U8 => PrimitiveType::U8,
1943 ast::UintTy::U16 => PrimitiveType::U16,
1944 ast::UintTy::U32 => PrimitiveType::U32,
1945 ast::UintTy::U64 => PrimitiveType::U64,
1946 ast::UintTy::U128 => PrimitiveType::U128,
1951 impl From<ast::FloatTy> for PrimitiveType {
1952 fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1954 ast::FloatTy::F32 => PrimitiveType::F32,
1955 ast::FloatTy::F64 => PrimitiveType::F64,
1960 impl From<ty::IntTy> for PrimitiveType {
1961 fn from(int_ty: ty::IntTy) -> PrimitiveType {
1963 ty::IntTy::Isize => PrimitiveType::Isize,
1964 ty::IntTy::I8 => PrimitiveType::I8,
1965 ty::IntTy::I16 => PrimitiveType::I16,
1966 ty::IntTy::I32 => PrimitiveType::I32,
1967 ty::IntTy::I64 => PrimitiveType::I64,
1968 ty::IntTy::I128 => PrimitiveType::I128,
1973 impl From<ty::UintTy> for PrimitiveType {
1974 fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1976 ty::UintTy::Usize => PrimitiveType::Usize,
1977 ty::UintTy::U8 => PrimitiveType::U8,
1978 ty::UintTy::U16 => PrimitiveType::U16,
1979 ty::UintTy::U32 => PrimitiveType::U32,
1980 ty::UintTy::U64 => PrimitiveType::U64,
1981 ty::UintTy::U128 => PrimitiveType::U128,
1986 impl From<ty::FloatTy> for PrimitiveType {
1987 fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1989 ty::FloatTy::F32 => PrimitiveType::F32,
1990 ty::FloatTy::F64 => PrimitiveType::F64,
1995 impl From<hir::PrimTy> for PrimitiveType {
1996 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1998 hir::PrimTy::Int(int_ty) => int_ty.into(),
1999 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
2000 hir::PrimTy::Float(float_ty) => float_ty.into(),
2001 hir::PrimTy::Str => PrimitiveType::Str,
2002 hir::PrimTy::Bool => PrimitiveType::Bool,
2003 hir::PrimTy::Char => PrimitiveType::Char,
2008 #[derive(Copy, Clone, Debug)]
2009 crate enum Visibility {
2012 /// Visibility inherited from parent.
2014 /// For example, this is the visibility of private items and of enum variants.
2016 /// `pub(crate)`, `pub(super)`, or `pub(in path::to::somewhere)`
2021 crate fn is_public(&self) -> bool {
2022 matches!(self, Visibility::Public)
2026 #[derive(Clone, Debug)]
2027 crate struct Struct {
2028 crate struct_type: CtorKind,
2029 crate generics: Generics,
2030 crate fields: Vec<Item>,
2031 crate fields_stripped: bool,
2034 #[derive(Clone, Debug)]
2035 crate struct Union {
2036 crate generics: Generics,
2037 crate fields: Vec<Item>,
2038 crate fields_stripped: bool,
2041 /// This is a more limited form of the standard Struct, different in that
2042 /// it lacks the things most items have (name, id, parameterization). Found
2043 /// only as a variant in an enum.
2044 #[derive(Clone, Debug)]
2045 crate struct VariantStruct {
2046 crate struct_type: CtorKind,
2047 crate fields: Vec<Item>,
2048 crate fields_stripped: bool,
2051 #[derive(Clone, Debug)]
2053 crate variants: IndexVec<VariantIdx, Item>,
2054 crate generics: Generics,
2055 crate variants_stripped: bool,
2058 #[derive(Clone, Debug)]
2059 crate enum Variant {
2062 Struct(VariantStruct),
2065 /// Small wrapper around [`rustc_span::Span]` that adds helper methods
2066 /// and enforces calling [`rustc_span::Span::source_callsite()`].
2067 #[derive(Copy, Clone, Debug)]
2068 crate struct Span(rustc_span::Span);
2071 crate fn from_rustc_span(sp: rustc_span::Span) -> Self {
2072 // Get the macro invocation instead of the definition,
2073 // in case the span is result of a macro expansion.
2074 // (See rust-lang/rust#39726)
2075 Self(sp.source_callsite())
2078 crate fn inner(&self) -> rustc_span::Span {
2082 crate fn dummy() -> Self {
2083 Self(rustc_span::DUMMY_SP)
2086 crate fn is_dummy(&self) -> bool {
2090 crate fn filename(&self, sess: &Session) -> FileName {
2091 sess.source_map().span_to_filename(self.0)
2094 crate fn lo(&self, sess: &Session) -> Loc {
2095 sess.source_map().lookup_char_pos(self.0.lo())
2098 crate fn hi(&self, sess: &Session) -> Loc {
2099 sess.source_map().lookup_char_pos(self.0.hi())
2102 crate fn cnum(&self, sess: &Session) -> CrateNum {
2103 // FIXME: is there a time when the lo and hi crate would be different?
2104 self.lo(sess).file.cnum
2108 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2112 crate segments: Vec<PathSegment>,
2116 crate fn last(&self) -> Symbol {
2117 self.segments.last().expect("segments were empty").name
2120 crate fn last_name(&self) -> SymbolStr {
2121 self.segments.last().expect("segments were empty").name.as_str()
2124 crate fn whole_name(&self) -> String {
2125 String::from(if self.global { "::" } else { "" })
2126 + &self.segments.iter().map(|s| s.name.to_string()).collect::<Vec<_>>().join("::")
2130 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2131 crate enum GenericArg {
2137 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2138 crate enum GenericArgs {
2139 AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
2140 Parenthesized { inputs: Vec<Type>, output: Option<Type> },
2143 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2144 crate struct PathSegment {
2146 crate args: GenericArgs,
2149 #[derive(Clone, Debug)]
2150 crate struct Typedef {
2152 crate generics: Generics,
2153 /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
2154 /// alias instead of the final type. This will always have the final type, regardless of whether
2155 /// `type_` came from HIR or from metadata.
2157 /// If `item_type.is_none()`, `type_` is guarenteed to come from metadata (and therefore hold the
2159 crate item_type: Option<Type>,
2162 impl GetDefId for Typedef {
2163 fn def_id(&self) -> Option<DefId> {
2167 fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
2168 self.type_.def_id_full(cache)
2172 #[derive(Clone, Debug)]
2173 crate struct OpaqueTy {
2174 crate bounds: Vec<GenericBound>,
2175 crate generics: Generics,
2178 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2179 crate struct BareFunctionDecl {
2180 crate unsafety: hir::Unsafety,
2181 crate generic_params: Vec<GenericParamDef>,
2186 #[derive(Clone, Debug)]
2187 crate struct Static {
2189 crate mutability: Mutability,
2190 crate expr: Option<BodyId>,
2193 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2194 crate struct Constant {
2196 crate kind: ConstantKind,
2199 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2200 crate enum ConstantKind {
2201 /// This is the wrapper around `ty::Const` for a non-local constant. Because it doesn't have a
2202 /// `BodyId`, we need to handle it on its own.
2204 /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified
2205 /// by a DefId. So this field must be different from `Extern`.
2206 TyConst { expr: String },
2207 /// A constant (expression) that's not an item or associated item. These are usually found
2208 /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
2209 /// used to define explicit discriminant values for enum variants.
2210 Anonymous { body: BodyId },
2211 /// A constant from a different crate.
2212 Extern { def_id: DefId },
2213 /// `const FOO: u32 = ...;`
2214 Local { def_id: DefId, body: BodyId },
2218 crate fn expr(&self, tcx: TyCtxt<'_>) -> String {
2220 ConstantKind::TyConst { ref expr } => expr.clone(),
2221 ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2222 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2223 print_const_expr(tcx, body)
2228 crate fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2230 ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
2231 ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2232 print_evaluated_const(tcx, def_id)
2237 crate fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2239 ConstantKind::TyConst { .. } => false,
2240 ConstantKind::Extern { def_id } => def_id.as_local().map_or(false, |def_id| {
2241 is_literal_expr(tcx, tcx.hir().local_def_id_to_hir_id(def_id))
2243 ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2244 is_literal_expr(tcx, body.hir_id)
2250 #[derive(Clone, Debug)]
2253 crate unsafety: hir::Unsafety,
2254 crate generics: Generics,
2255 crate trait_: Option<Type>,
2257 crate items: Vec<Item>,
2258 crate negative_polarity: bool,
2259 crate synthetic: bool,
2260 crate blanket_impl: Option<Type>,
2264 crate fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxHashSet<Symbol> {
2267 .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.ident.name).collect())
2268 .unwrap_or_default()
2272 #[derive(Clone, Debug)]
2273 crate struct Import {
2274 crate kind: ImportKind,
2275 crate source: ImportSource,
2276 crate should_be_displayed: bool,
2280 crate fn new_simple(name: Symbol, source: ImportSource, should_be_displayed: bool) -> Self {
2281 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2284 crate fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2285 Self { kind: ImportKind::Glob, source, should_be_displayed }
2289 #[derive(Clone, Debug)]
2290 crate enum ImportKind {
2291 // use source as str;
2297 #[derive(Clone, Debug)]
2298 crate struct ImportSource {
2300 crate did: Option<DefId>,
2303 #[derive(Clone, Debug)]
2304 crate struct Macro {
2305 crate source: String,
2306 crate imported_from: Option<Symbol>,
2309 #[derive(Clone, Debug)]
2310 crate struct ProcMacro {
2311 crate kind: MacroKind,
2312 crate helpers: Vec<Symbol>,
2315 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
2316 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
2317 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2318 crate struct TypeBinding {
2320 crate kind: TypeBindingKind,
2323 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2324 crate enum TypeBindingKind {
2325 Equality { ty: Type },
2326 Constraint { bounds: Vec<GenericBound> },
2330 crate fn ty(&self) -> &Type {
2332 TypeBindingKind::Equality { ref ty } => ty,
2333 _ => panic!("expected equality type binding for parenthesized generic args"),