1 use std::cell::RefCell;
2 use std::default::Default;
4 use std::hash::{Hash, Hasher};
5 use std::iter::FromIterator;
6 use std::lazy::SyncOnceCell as OnceCell;
12 use rustc_ast::util::comments::beautify_doc_string;
13 use rustc_ast::{self as ast, AttrStyle};
14 use rustc_ast::{FloatTy, IntTy, UintTy};
15 use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
16 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
17 use rustc_feature::UnstableFeatures;
19 use rustc_hir::def::Res;
20 use rustc_hir::def_id::{CrateNum, DefId};
21 use rustc_hir::lang_items::LangItem;
22 use rustc_hir::Mutability;
23 use rustc_index::vec::IndexVec;
24 use rustc_middle::ty::TyCtxt;
25 use rustc_session::Session;
26 use rustc_span::hygiene::MacroKind;
27 use rustc_span::source_map::DUMMY_SP;
28 use rustc_span::symbol::{kw, sym, Ident, Symbol, SymbolStr};
29 use rustc_span::{self, FileName, Loc};
30 use rustc_target::abi::VariantIdx;
31 use rustc_target::spec::abi::Abi;
32 use smallvec::{smallvec, SmallVec};
34 use crate::clean::cfg::Cfg;
35 use crate::clean::external_path;
36 use crate::clean::inline;
37 use crate::clean::types::Type::{QPath, ResolvedPath};
38 use crate::clean::Clean;
39 use crate::core::DocContext;
41 use crate::formats::cache::cache;
42 use crate::formats::item_type::ItemType;
43 use crate::html::render::cache::ExternalLocation;
46 use self::ItemKind::*;
50 thread_local!(crate static MAX_DEF_ID: RefCell<FxHashMap<CrateNum, DefId>> = Default::default());
52 #[derive(Clone, Debug)]
55 crate version: Option<String>,
57 crate module: Option<Item>,
58 crate externs: Vec<(CrateNum, ExternalCrate)>,
59 crate primitives: Vec<(DefId, PrimitiveType)>,
60 // These are later on moved into `CACHEKEY`, leaving the map empty.
61 // Only here so that they can be filtered through the rustdoc passes.
62 crate external_traits: Rc<RefCell<FxHashMap<DefId, Trait>>>,
63 crate masked_crates: FxHashSet<CrateNum>,
64 crate collapsed: bool,
67 #[derive(Clone, Debug)]
68 crate struct ExternalCrate {
71 crate attrs: Attributes,
72 crate primitives: Vec<(DefId, PrimitiveType)>,
73 crate keywords: Vec<(DefId, Symbol)>,
76 /// Anything with a source location and set of attributes and, optionally, a
77 /// name. That is, anything that can be documented. This doesn't correspond
78 /// directly to the AST's concept of an item; it's a strict superset.
83 /// Not everything has a name. E.g., impls
84 crate name: Option<Symbol>,
85 crate attrs: Box<Attributes>,
86 crate visibility: Visibility,
87 crate kind: Box<ItemKind>,
91 // `Item` is used a lot. Make sure it doesn't unintentionally get bigger.
92 #[cfg(target_arch = "x86_64")]
93 rustc_data_structures::static_assert_size!(Item, 48);
95 impl fmt::Debug for Item {
96 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
97 let def_id: &dyn fmt::Debug = if self.is_fake() { &"**FAKE**" } else { &self.def_id };
99 fmt.debug_struct("Item")
100 .field("source", &self.source)
101 .field("name", &self.name)
102 .field("attrs", &self.attrs)
103 .field("kind", &self.kind)
104 .field("visibility", &self.visibility)
105 .field("def_id", def_id)
111 crate fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx Stability> {
112 if self.is_fake() { None } else { tcx.lookup_stability(self.def_id) }
115 crate fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ConstStability> {
116 if self.is_fake() { None } else { tcx.lookup_const_stability(self.def_id) }
119 crate fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
120 if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id) }
123 /// Finds the `doc` attribute as a NameValue and returns the corresponding
125 crate fn doc_value(&self) -> Option<String> {
126 self.attrs.doc_value()
129 /// Convenience wrapper around [`Self::from_def_id_and_parts`] which converts
130 /// `hir_id` to a [`DefId`]
131 pub fn from_hir_id_and_parts(
133 name: Option<Symbol>,
137 Item::from_def_id_and_parts(cx.tcx.hir().local_def_id(hir_id).to_def_id(), name, kind, cx)
140 pub fn from_def_id_and_parts(
142 name: Option<Symbol>,
146 debug!("name={:?}, def_id={:?}", name, def_id);
148 // `span_if_local()` lies about functions and only gives the span of the function signature
149 let source = def_id.as_local().map_or_else(
150 || cx.tcx.def_span(def_id),
152 let hir = cx.tcx.hir();
153 hir.span_with_body(hir.local_def_id_to_hir_id(local))
161 source: source.clean(cx),
162 attrs: box cx.tcx.get_attrs(def_id).clean(cx),
163 visibility: cx.tcx.visibility(def_id).clean(cx),
167 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
169 crate fn collapsed_doc_value(&self) -> Option<String> {
170 self.attrs.collapsed_doc_value()
173 crate fn links(&self) -> Vec<RenderedLink> {
174 self.attrs.links(&self.def_id.krate)
177 crate fn is_crate(&self) -> bool {
180 StrippedItem(box ModuleItem(Module { is_crate: true, .. }))
181 | ModuleItem(Module { is_crate: true, .. })
184 crate fn is_mod(&self) -> bool {
185 self.type_() == ItemType::Module
187 crate fn is_trait(&self) -> bool {
188 self.type_() == ItemType::Trait
190 crate fn is_struct(&self) -> bool {
191 self.type_() == ItemType::Struct
193 crate fn is_enum(&self) -> bool {
194 self.type_() == ItemType::Enum
196 crate fn is_variant(&self) -> bool {
197 self.type_() == ItemType::Variant
199 crate fn is_associated_type(&self) -> bool {
200 self.type_() == ItemType::AssocType
202 crate fn is_associated_const(&self) -> bool {
203 self.type_() == ItemType::AssocConst
205 crate fn is_method(&self) -> bool {
206 self.type_() == ItemType::Method
208 crate fn is_ty_method(&self) -> bool {
209 self.type_() == ItemType::TyMethod
211 crate fn is_typedef(&self) -> bool {
212 self.type_() == ItemType::Typedef
214 crate fn is_primitive(&self) -> bool {
215 self.type_() == ItemType::Primitive
217 crate fn is_union(&self) -> bool {
218 self.type_() == ItemType::Union
220 crate fn is_import(&self) -> bool {
221 self.type_() == ItemType::Import
223 crate fn is_extern_crate(&self) -> bool {
224 self.type_() == ItemType::ExternCrate
226 crate fn is_keyword(&self) -> bool {
227 self.type_() == ItemType::Keyword
229 crate fn is_stripped(&self) -> bool {
231 StrippedItem(..) => true,
232 ImportItem(ref i) => !i.should_be_displayed,
236 crate fn has_stripped_fields(&self) -> Option<bool> {
238 StructItem(ref _struct) => Some(_struct.fields_stripped),
239 UnionItem(ref union) => Some(union.fields_stripped),
240 VariantItem(Variant::Struct(ref vstruct)) => Some(vstruct.fields_stripped),
245 crate fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
246 self.stability(tcx).as_ref().and_then(|ref s| {
247 let mut classes = Vec::with_capacity(2);
249 if s.level.is_unstable() {
250 classes.push("unstable");
253 // FIXME: what about non-staged API items that are deprecated?
254 if self.deprecation(tcx).is_some() {
255 classes.push("deprecated");
258 if !classes.is_empty() { Some(classes.join(" ")) } else { None }
262 crate fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
263 match self.stability(tcx)?.level {
264 StabilityLevel::Stable { since, .. } => Some(since.as_str()),
265 StabilityLevel::Unstable { .. } => None,
269 crate fn const_stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
270 match self.const_stability(tcx)?.level {
271 StabilityLevel::Stable { since, .. } => Some(since.as_str()),
272 StabilityLevel::Unstable { .. } => None,
276 crate fn is_non_exhaustive(&self) -> bool {
277 self.attrs.other_attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
280 /// Returns a documentation-level item type from the item.
281 crate fn type_(&self) -> ItemType {
285 crate fn is_default(&self) -> bool {
287 ItemKind::MethodItem(_, Some(defaultness)) => {
288 defaultness.has_value() && !defaultness.is_final()
294 /// See the documentation for [`next_def_id()`].
296 /// [`next_def_id()`]: DocContext::next_def_id()
297 crate fn is_fake(&self) -> bool {
298 MAX_DEF_ID.with(|m| {
299 m.borrow().get(&self.def_id.krate).map(|id| self.def_id >= *id).unwrap_or(false)
304 #[derive(Clone, Debug)]
305 crate enum ItemKind {
306 ExternCrateItem(Symbol, Option<Symbol>),
311 FunctionItem(Function),
313 TypedefItem(Typedef, bool /* is associated type */),
314 OpaqueTyItem(OpaqueTy),
316 ConstantItem(Constant),
318 TraitAliasItem(TraitAlias),
320 /// A method signature only. Used for required methods in traits (ie,
321 /// non-default-methods).
322 TyMethodItem(Function),
323 /// A method with a body.
324 MethodItem(Function, Option<hir::Defaultness>),
325 StructFieldItem(Type),
326 VariantItem(Variant),
327 /// `fn`s from an extern block
328 ForeignFunctionItem(Function),
329 /// `static`s from an extern block
330 ForeignStaticItem(Static),
331 /// `type`s from an extern block
334 ProcMacroItem(ProcMacro),
335 PrimitiveItem(PrimitiveType),
336 AssocConstItem(Type, Option<String>),
337 /// An associated item in a trait or trait impl.
339 /// The bounds may be non-empty if there is a `where` clause.
340 /// The `Option<Type>` is the default concrete type (e.g. `trait Trait { type Target = usize; }`)
341 AssocTypeItem(Vec<GenericBound>, Option<Type>),
342 /// An item that has been stripped by a rustdoc pass
343 StrippedItem(Box<ItemKind>),
348 /// Some items contain others such as structs (for their fields) and Enums
349 /// (for their variants). This method returns those contained items.
350 crate fn inner_items(&self) -> impl Iterator<Item = &Item> {
352 StructItem(s) => s.fields.iter(),
353 UnionItem(u) => u.fields.iter(),
354 VariantItem(Variant::Struct(v)) => v.fields.iter(),
355 EnumItem(e) => e.variants.iter(),
356 TraitItem(t) => t.items.iter(),
357 ImplItem(i) => i.items.iter(),
358 ModuleItem(m) => m.items.iter(),
359 ExternCrateItem(_, _)
371 | ForeignFunctionItem(_)
372 | ForeignStaticItem(_)
377 | AssocConstItem(_, _)
378 | AssocTypeItem(_, _)
380 | KeywordItem(_) => [].iter(),
384 crate fn is_type_alias(&self) -> bool {
385 matches!(self, ItemKind::TypedefItem(..) | ItemKind::AssocTypeItem(..))
389 #[derive(Clone, Debug)]
390 crate struct Module {
391 crate items: Vec<Item>,
392 crate is_crate: bool,
395 crate struct ListAttributesIter<'a> {
396 attrs: slice::Iter<'a, ast::Attribute>,
397 current_list: vec::IntoIter<ast::NestedMetaItem>,
401 impl<'a> Iterator for ListAttributesIter<'a> {
402 type Item = ast::NestedMetaItem;
404 fn next(&mut self) -> Option<Self::Item> {
405 if let Some(nested) = self.current_list.next() {
409 for attr in &mut self.attrs {
410 if let Some(list) = attr.meta_item_list() {
411 if attr.has_name(self.name) {
412 self.current_list = list.into_iter();
413 if let Some(nested) = self.current_list.next() {
423 fn size_hint(&self) -> (usize, Option<usize>) {
424 let lower = self.current_list.len();
429 crate trait AttributesExt {
430 /// Finds an attribute as List and returns the list of attributes nested inside.
431 fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
434 impl AttributesExt for [ast::Attribute] {
435 fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
436 ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), name }
440 crate trait NestedAttributesExt {
441 /// Returns `true` if the attribute list contains a specific `Word`
442 fn has_word(self, word: Symbol) -> bool;
443 fn get_word_attr(self, word: Symbol) -> (Option<ast::NestedMetaItem>, bool);
446 impl<I: Iterator<Item = ast::NestedMetaItem> + IntoIterator<Item = ast::NestedMetaItem>>
447 NestedAttributesExt for I
449 fn has_word(self, word: Symbol) -> bool {
450 self.into_iter().any(|attr| attr.is_word() && attr.has_name(word))
453 fn get_word_attr(mut self, word: Symbol) -> (Option<ast::NestedMetaItem>, bool) {
454 match self.find(|attr| attr.is_word() && attr.has_name(word)) {
455 Some(a) => (Some(a), true),
456 None => (None, false),
461 /// A portion of documentation, extracted from a `#[doc]` attribute.
463 /// Each variant contains the line number within the complete doc-comment where the fragment
464 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
466 /// Included files are kept separate from inline doc comments so that proper line-number
467 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
468 /// kept separate because of issue #42760.
469 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
470 crate struct DocFragment {
472 crate span: rustc_span::Span,
473 /// The module this doc-comment came from.
475 /// This allows distinguishing between the original documentation and a pub re-export.
476 /// If it is `None`, the item was not re-exported.
477 crate parent_module: Option<DefId>,
479 crate kind: DocFragmentKind,
480 crate need_backline: bool,
484 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
485 crate enum DocFragmentKind {
486 /// A doc fragment created from a `///` or `//!` doc comment.
488 /// A doc fragment created from a "raw" `#[doc=""]` attribute.
490 /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
491 /// given filename and the file contents.
492 Include { filename: Symbol },
495 // The goal of this function is to apply the `DocFragment` transformations that are required when
496 // transforming into the final markdown. So the transformations in here are:
498 // * Applying the computed indent to each lines in each doc fragment (a `DocFragment` can contain
499 // multiple lines in case of `#[doc = ""]`).
500 // * Adding backlines between `DocFragment`s and adding an extra one if required (stored in the
501 // `need_backline` field).
502 fn add_doc_fragment(out: &mut String, frag: &DocFragment) {
503 let s = frag.doc.as_str();
504 let mut iter = s.lines().peekable();
505 while let Some(line) = iter.next() {
506 if line.chars().any(|c| !c.is_whitespace()) {
507 assert!(line.len() >= frag.indent);
508 out.push_str(&line[frag.indent..]);
512 if iter.peek().is_some() {
516 if frag.need_backline {
521 impl<'a> FromIterator<&'a DocFragment> for String {
522 fn from_iter<T>(iter: T) -> Self
524 T: IntoIterator<Item = &'a DocFragment>,
526 let mut prev_kind: Option<DocFragmentKind> = None;
527 iter.into_iter().fold(String::new(), |mut acc, frag| {
531 .map(|p| matches!(p, DocFragmentKind::Include { .. }) && p != frag.kind)
536 add_doc_fragment(&mut acc, &frag);
537 prev_kind = Some(frag.kind);
543 #[derive(Clone, Debug, Default)]
544 crate struct Attributes {
545 crate doc_strings: Vec<DocFragment>,
546 crate other_attrs: Vec<ast::Attribute>,
547 crate cfg: Option<Arc<Cfg>>,
548 crate span: Option<rustc_span::Span>,
549 /// map from Rust paths to resolved defs and potential URL fragments
550 crate links: Vec<ItemLink>,
551 crate inner_docs: bool,
554 #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
555 /// A link that has not yet been rendered.
557 /// This link will be turned into a rendered link by [`Attributes::links`]
558 crate struct ItemLink {
559 /// The original link written in the markdown
560 pub(crate) link: String,
561 /// The link text displayed in the HTML.
563 /// This may not be the same as `link` if there was a disambiguator
564 /// in an intra-doc link (e.g. \[`fn@f`\])
565 pub(crate) link_text: String,
566 pub(crate) did: Option<DefId>,
567 /// The url fragment to append to the link
568 pub(crate) fragment: Option<String>,
571 pub struct RenderedLink {
572 /// The text the link was original written as.
574 /// This could potentially include disambiguators and backticks.
575 pub(crate) original_text: String,
576 /// The text to display in the HTML
577 pub(crate) new_text: String,
578 /// The URL to put in the `href`
579 pub(crate) href: String,
583 /// Extracts the content from an attribute `#[doc(cfg(content))]`.
584 crate fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
585 use rustc_ast::NestedMetaItem::MetaItem;
587 if let ast::MetaItemKind::List(ref nmis) = mi.kind {
589 if let MetaItem(ref cfg_mi) = nmis[0] {
590 if cfg_mi.has_name(sym::cfg) {
591 if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.kind {
592 if cfg_nmis.len() == 1 {
593 if let MetaItem(ref content_mi) = cfg_nmis[0] {
594 return Some(content_mi);
606 /// Reads a `MetaItem` from within an attribute, looks for whether it is a
607 /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
609 crate fn extract_include(mi: &ast::MetaItem) -> Option<(Symbol, Symbol)> {
610 mi.meta_item_list().and_then(|list| {
612 if meta.has_name(sym::include) {
613 // the actual compiled `#[doc(include="filename")]` gets expanded to
614 // `#[doc(include(file="filename", contents="file contents")]` so we need to
615 // look for that instead
616 return meta.meta_item_list().and_then(|list| {
617 let mut filename: Option<Symbol> = None;
618 let mut contents: Option<Symbol> = None;
621 if it.has_name(sym::file) {
622 if let Some(name) = it.value_str() {
623 filename = Some(name);
625 } else if it.has_name(sym::contents) {
626 if let Some(docs) = it.value_str() {
627 contents = Some(docs);
632 if let (Some(filename), Some(contents)) = (filename, contents) {
633 Some((filename, contents))
645 crate fn has_doc_flag(&self, flag: Symbol) -> bool {
646 for attr in &self.other_attrs {
647 if !attr.has_name(sym::doc) {
651 if let Some(items) = attr.meta_item_list() {
652 if items.iter().filter_map(|i| i.meta_item()).any(|it| it.has_name(flag)) {
662 diagnostic: &::rustc_errors::Handler,
663 attrs: &[ast::Attribute],
664 additional_attrs: Option<(&[ast::Attribute], DefId)>,
666 let mut doc_strings: Vec<DocFragment> = vec![];
668 let mut cfg = Cfg::True;
669 let mut doc_line = 0;
671 fn update_need_backline(doc_strings: &mut Vec<DocFragment>, frag: &DocFragment) {
672 if let Some(prev) = doc_strings.last_mut() {
673 if matches!(prev.kind, DocFragmentKind::Include { .. })
674 || prev.kind != frag.kind
675 || prev.parent_module != frag.parent_module
677 // add a newline for extra padding between segments
678 prev.need_backline = prev.kind == DocFragmentKind::SugaredDoc
679 || prev.kind == DocFragmentKind::RawDoc
681 prev.need_backline = true;
686 let clean_attr = |(attr, parent_module): (&ast::Attribute, _)| {
687 if let Some(value) = attr.doc_str() {
688 trace!("got doc_str={:?}", value);
689 let value = beautify_doc_string(value);
690 let kind = if attr.is_doc_comment() {
691 DocFragmentKind::SugaredDoc
693 DocFragmentKind::RawDoc
697 doc_line += value.as_str().lines().count();
698 let frag = DocFragment {
704 need_backline: false,
708 update_need_backline(&mut doc_strings, &frag);
710 doc_strings.push(frag);
713 sp = Some(attr.span);
717 if attr.has_name(sym::doc) {
718 if let Some(mi) = attr.meta() {
719 if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
720 // Extracted #[doc(cfg(...))]
721 match Cfg::parse(cfg_mi) {
722 Ok(new_cfg) => cfg &= new_cfg,
723 Err(e) => diagnostic.span_err(e.span, e.msg),
725 } else if let Some((filename, contents)) = Attributes::extract_include(&mi)
728 doc_line += contents.as_str().lines().count();
729 let frag = DocFragment {
733 kind: DocFragmentKind::Include { filename },
735 need_backline: false,
738 update_need_backline(&mut doc_strings, &frag);
739 doc_strings.push(frag);
747 // Additional documentation should be shown before the original documentation
748 let other_attrs = additional_attrs
750 .map(|(attrs, id)| attrs.iter().map(move |attr| (attr, Some(id))))
752 .chain(attrs.iter().map(|attr| (attr, None)))
753 .filter_map(clean_attr)
756 // treat #[target_feature(enable = "feat")] attributes as if they were
757 // #[doc(cfg(target_feature = "feat"))] attributes as well
758 for attr in attrs.lists(sym::target_feature) {
759 if attr.has_name(sym::enable) {
760 if let Some(feat) = attr.value_str() {
761 let meta = attr::mk_name_value_item_str(
762 Ident::with_dummy_span(sym::target_feature),
766 if let Ok(feat_cfg) = Cfg::parse(&meta) {
773 let inner_docs = attrs
775 .find(|a| a.doc_str().is_some())
776 .map_or(true, |a| a.style == AttrStyle::Inner);
781 cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) },
788 /// Finds the `doc` attribute as a NameValue and returns the corresponding
790 crate fn doc_value(&self) -> Option<String> {
791 let mut iter = self.doc_strings.iter();
793 let ori = iter.next()?;
794 let mut out = String::new();
795 add_doc_fragment(&mut out, &ori);
796 while let Some(new_frag) = iter.next() {
797 if matches!(ori.kind, DocFragmentKind::Include { .. })
798 || new_frag.kind != ori.kind
799 || new_frag.parent_module != ori.parent_module
803 add_doc_fragment(&mut out, &new_frag);
805 if out.is_empty() { None } else { Some(out) }
808 /// Return the doc-comments on this item, grouped by the module they came from.
810 /// The module can be different if this is a re-export with added documentation.
811 crate fn collapsed_doc_value_by_module_level(&self) -> FxHashMap<Option<DefId>, String> {
812 let mut ret = FxHashMap::default();
814 for new_frag in self.doc_strings.iter() {
815 let out = ret.entry(new_frag.parent_module).or_default();
816 add_doc_fragment(out, &new_frag);
821 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
823 crate fn collapsed_doc_value(&self) -> Option<String> {
824 if self.doc_strings.is_empty() { None } else { Some(self.doc_strings.iter().collect()) }
827 /// Gets links as a vector
829 /// Cache must be populated before call
830 crate fn links(&self, krate: &CrateNum) -> Vec<RenderedLink> {
831 use crate::html::format::href;
832 use crate::html::render::CURRENT_DEPTH;
836 .filter_map(|ItemLink { link: s, link_text, did, fragment }| {
839 if let Some((mut href, ..)) = href(did) {
840 if let Some(ref fragment) = *fragment {
842 href.push_str(fragment);
845 original_text: s.clone(),
846 new_text: link_text.clone(),
854 if let Some(ref fragment) = *fragment {
856 let url = match cache.extern_locations.get(krate) {
857 Some(&(_, _, ExternalLocation::Local)) => {
858 let depth = CURRENT_DEPTH.with(|l| l.get());
861 Some(&(_, _, ExternalLocation::Remote(ref s))) => s.to_string(),
862 Some(&(_, _, ExternalLocation::Unknown)) | None => String::from(
863 // NOTE: intentionally doesn't pass crate name to avoid having
864 // different primitive links between crates
865 if UnstableFeatures::from_environment(None).is_nightly_build() {
866 "https://doc.rust-lang.org/nightly"
868 "https://doc.rust-lang.org"
872 // This is a primitive so the url is done "by hand".
873 let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
875 original_text: s.clone(),
876 new_text: link_text.clone(),
878 "{}{}std/primitive.{}.html{}",
880 if !url.ends_with('/') { "/" } else { "" },
886 panic!("This isn't a primitive?!");
894 crate fn get_doc_aliases(&self) -> FxHashSet<String> {
897 .filter(|a| a.has_name(sym::alias))
898 .filter_map(|a| a.value_str().map(|s| s.to_string()))
899 .filter(|v| !v.is_empty())
900 .collect::<FxHashSet<_>>()
904 impl PartialEq for Attributes {
905 fn eq(&self, rhs: &Self) -> bool {
906 self.doc_strings == rhs.doc_strings
907 && self.cfg == rhs.cfg
908 && self.span == rhs.span
909 && self.links == rhs.links
914 .eq(rhs.other_attrs.iter().map(|attr| attr.id))
918 impl Eq for Attributes {}
920 impl Hash for Attributes {
921 fn hash<H: Hasher>(&self, hasher: &mut H) {
922 self.doc_strings.hash(hasher);
923 self.cfg.hash(hasher);
924 self.span.hash(hasher);
925 self.links.hash(hasher);
926 for attr in &self.other_attrs {
927 attr.id.hash(hasher);
932 impl AttributesExt for Attributes {
933 fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
934 self.other_attrs.lists(name)
938 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
939 crate enum GenericBound {
940 TraitBound(PolyTrait, hir::TraitBoundModifier),
945 crate fn maybe_sized(cx: &DocContext<'_>) -> GenericBound {
946 let did = cx.tcx.require_lang_item(LangItem::Sized, None);
947 let empty = cx.tcx.intern_substs(&[]);
948 let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
949 inline::record_extern_fqn(cx, did, TypeKind::Trait);
950 GenericBound::TraitBound(
952 trait_: ResolvedPath { path, param_names: None, did, is_generic: false },
953 generic_params: Vec::new(),
955 hir::TraitBoundModifier::Maybe,
959 crate fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
960 use rustc_hir::TraitBoundModifier as TBM;
961 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
962 if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
969 crate fn get_poly_trait(&self) -> Option<PolyTrait> {
970 if let GenericBound::TraitBound(ref p, _) = *self {
971 return Some(p.clone());
976 crate fn get_trait_type(&self) -> Option<Type> {
977 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
985 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
986 crate struct Lifetime(pub Symbol);
989 crate fn get_ref(&self) -> SymbolStr {
993 crate fn statik() -> Lifetime {
994 Lifetime(kw::StaticLifetime)
997 crate fn elided() -> Lifetime {
998 Lifetime(kw::UnderscoreLifetime)
1002 #[derive(Clone, Debug)]
1003 crate enum WherePredicate {
1004 BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
1005 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1006 EqPredicate { lhs: Type, rhs: Type },
1009 impl WherePredicate {
1010 crate fn get_bounds(&self) -> Option<&[GenericBound]> {
1012 WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
1013 WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
1019 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1020 crate enum GenericParamDefKind {
1024 bounds: Vec<GenericBound>,
1025 default: Option<Type>,
1026 synthetic: Option<hir::SyntheticTyParamKind>,
1034 impl GenericParamDefKind {
1035 crate fn is_type(&self) -> bool {
1036 matches!(self, GenericParamDefKind::Type { .. })
1039 // FIXME(eddyb) this either returns the default of a type parameter, or the
1040 // type of a `const` parameter. It seems that the intention is to *visit*
1041 // any embedded types, but `get_type` seems to be the wrong name for that.
1042 crate fn get_type(&self) -> Option<Type> {
1044 GenericParamDefKind::Type { default, .. } => default.clone(),
1045 GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
1046 GenericParamDefKind::Lifetime => None,
1051 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1052 crate struct GenericParamDef {
1054 crate kind: GenericParamDefKind,
1057 impl GenericParamDef {
1058 crate fn is_synthetic_type_param(&self) -> bool {
1060 GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => false,
1061 GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
1065 crate fn is_type(&self) -> bool {
1069 crate fn get_type(&self) -> Option<Type> {
1070 self.kind.get_type()
1073 crate fn get_bounds(&self) -> Option<&[GenericBound]> {
1075 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1081 // maybe use a Generic enum and use Vec<Generic>?
1082 #[derive(Clone, Debug, Default)]
1083 crate struct Generics {
1084 crate params: Vec<GenericParamDef>,
1085 crate where_predicates: Vec<WherePredicate>,
1088 #[derive(Clone, Debug)]
1089 crate struct Function {
1091 crate generics: Generics,
1092 crate header: hir::FnHeader,
1093 crate all_types: Vec<(Type, TypeKind)>,
1094 crate ret_types: Vec<(Type, TypeKind)>,
1097 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1098 crate struct FnDecl {
1099 crate inputs: Arguments,
1100 crate output: FnRetTy,
1101 crate c_variadic: bool,
1102 crate attrs: Attributes,
1106 crate fn self_type(&self) -> Option<SelfTy> {
1107 self.inputs.values.get(0).and_then(|v| v.to_self())
1110 /// Returns the sugared return type for an async function.
1112 /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
1113 /// will return `i32`.
1117 /// This function will panic if the return type does not match the expected sugaring for async
1119 crate fn sugared_async_return_type(&self) -> FnRetTy {
1120 match &self.output {
1121 FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
1122 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
1123 let bindings = trait_.bindings().unwrap();
1124 FnRetTy::Return(bindings[0].ty().clone())
1126 _ => panic!("unexpected desugaring of async function"),
1128 _ => panic!("unexpected desugaring of async function"),
1133 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1134 crate struct Arguments {
1135 crate values: Vec<Argument>,
1138 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1139 crate struct Argument {
1144 #[derive(Clone, PartialEq, Debug)]
1147 SelfBorrowed(Option<Lifetime>, Mutability),
1152 crate fn to_self(&self) -> Option<SelfTy> {
1153 if self.name != kw::SelfLower {
1156 if self.type_.is_self_type() {
1157 return Some(SelfValue);
1160 BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
1161 Some(SelfBorrowed(lifetime.clone(), mutability))
1163 _ => Some(SelfExplicit(self.type_.clone())),
1168 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1169 crate enum FnRetTy {
1174 impl GetDefId for FnRetTy {
1175 fn def_id(&self) -> Option<DefId> {
1177 Return(ref ty) => ty.def_id(),
1178 DefaultReturn => None,
1183 #[derive(Clone, Debug)]
1184 crate struct Trait {
1185 crate unsafety: hir::Unsafety,
1186 crate items: Vec<Item>,
1187 crate generics: Generics,
1188 crate bounds: Vec<GenericBound>,
1189 crate is_spotlight: bool,
1190 crate is_auto: bool,
1193 #[derive(Clone, Debug)]
1194 crate struct TraitAlias {
1195 crate generics: Generics,
1196 crate bounds: Vec<GenericBound>,
1199 /// A trait reference, which may have higher ranked lifetimes.
1200 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1201 crate struct PolyTrait {
1203 crate generic_params: Vec<GenericParamDef>,
1206 /// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
1207 /// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
1208 /// importantly, it does not preserve mutability or boxes.
1209 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1211 /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
1214 param_names: Option<Vec<GenericBound>>,
1216 /// `true` if is a `T::Name` path for associated types.
1219 /// For parameterized types, so the consumer of the JSON don't go
1220 /// looking for types which don't exist anywhere.
1222 /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
1223 /// arrays, slices, and tuples.
1224 Primitive(PrimitiveType),
1225 /// `extern "ABI" fn`
1226 BareFunction(Box<BareFunctionDecl>),
1229 /// The `String` field is about the size or the constant representing the array's length.
1230 Array(Box<Type>, String),
1232 RawPointer(Mutability, Box<Type>),
1234 lifetime: Option<Lifetime>,
1235 mutability: Mutability,
1239 // `<Type as Trait>::Name`
1242 self_type: Box<Type>,
1249 // `impl TraitA + TraitB + ...`
1250 ImplTrait(Vec<GenericBound>),
1253 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1254 /// N.B. this has to be different from `hir::PrimTy` because it also includes types that aren't
1255 /// paths, like `Unit`.
1256 crate enum PrimitiveType {
1284 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1285 crate enum TypeKind {
1302 crate trait GetDefId {
1303 fn def_id(&self) -> Option<DefId>;
1306 impl<T: GetDefId> GetDefId for Option<T> {
1307 fn def_id(&self) -> Option<DefId> {
1308 self.as_ref().and_then(|d| d.def_id())
1313 crate fn primitive_type(&self) -> Option<PrimitiveType> {
1315 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1316 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1317 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1320 Some(PrimitiveType::Unit)
1322 Some(PrimitiveType::Tuple)
1325 RawPointer(..) => Some(PrimitiveType::RawPointer),
1326 BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
1327 BareFunction(..) => Some(PrimitiveType::Fn),
1328 Never => Some(PrimitiveType::Never),
1333 crate fn is_generic(&self) -> bool {
1335 ResolvedPath { is_generic, .. } => is_generic,
1340 crate fn is_self_type(&self) -> bool {
1342 Generic(name) => name == kw::SelfUpper,
1347 crate fn generics(&self) -> Option<Vec<Type>> {
1349 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1350 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
1353 .filter_map(|arg| match arg {
1354 GenericArg::Type(ty) => Some(ty.clone()),
1367 crate fn bindings(&self) -> Option<&[TypeBinding]> {
1369 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1370 if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
1380 crate fn is_full_generic(&self) -> bool {
1381 matches!(self, Type::Generic(_))
1384 crate fn projection(&self) -> Option<(&Type, DefId, Symbol)> {
1385 let (self_, trait_, name) = match self {
1386 QPath { self_type, trait_, name } => (self_type, trait_, name),
1389 let trait_did = match **trait_ {
1390 ResolvedPath { did, .. } => did,
1393 Some((&self_, trait_did, *name))
1397 impl GetDefId for Type {
1398 fn def_id(&self) -> Option<DefId> {
1400 ResolvedPath { did, .. } => Some(did),
1401 Primitive(p) => cache().primitive_locations.get(&p).cloned(),
1402 BorrowedRef { type_: box Generic(..), .. } => {
1403 Primitive(PrimitiveType::Reference).def_id()
1405 BorrowedRef { ref type_, .. } => type_.def_id(),
1408 Primitive(PrimitiveType::Unit).def_id()
1410 Primitive(PrimitiveType::Tuple).def_id()
1413 BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
1414 Never => Primitive(PrimitiveType::Never).def_id(),
1415 Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
1416 Array(..) => Primitive(PrimitiveType::Array).def_id(),
1417 RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(),
1418 QPath { ref self_type, .. } => self_type.def_id(),
1424 impl PrimitiveType {
1425 crate fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1427 hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1428 hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1429 hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1430 hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1431 hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1432 hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1433 hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1434 hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1435 hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1436 hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1437 hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1438 hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1439 hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1440 hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1441 hir::PrimTy::Str => PrimitiveType::Str,
1442 hir::PrimTy::Bool => PrimitiveType::Bool,
1443 hir::PrimTy::Char => PrimitiveType::Char,
1447 crate fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1449 sym::isize => Some(PrimitiveType::Isize),
1450 sym::i8 => Some(PrimitiveType::I8),
1451 sym::i16 => Some(PrimitiveType::I16),
1452 sym::i32 => Some(PrimitiveType::I32),
1453 sym::i64 => Some(PrimitiveType::I64),
1454 sym::i128 => Some(PrimitiveType::I128),
1455 sym::usize => Some(PrimitiveType::Usize),
1456 sym::u8 => Some(PrimitiveType::U8),
1457 sym::u16 => Some(PrimitiveType::U16),
1458 sym::u32 => Some(PrimitiveType::U32),
1459 sym::u64 => Some(PrimitiveType::U64),
1460 sym::u128 => Some(PrimitiveType::U128),
1461 sym::bool => Some(PrimitiveType::Bool),
1462 sym::char => Some(PrimitiveType::Char),
1463 sym::str => Some(PrimitiveType::Str),
1464 sym::f32 => Some(PrimitiveType::F32),
1465 sym::f64 => Some(PrimitiveType::F64),
1466 sym::array => Some(PrimitiveType::Array),
1467 sym::slice => Some(PrimitiveType::Slice),
1468 sym::tuple => Some(PrimitiveType::Tuple),
1469 sym::unit => Some(PrimitiveType::Unit),
1470 sym::pointer => Some(PrimitiveType::RawPointer),
1471 sym::reference => Some(PrimitiveType::Reference),
1472 kw::Fn => Some(PrimitiveType::Fn),
1473 sym::never => Some(PrimitiveType::Never),
1478 crate fn as_str(&self) -> &'static str {
1479 use self::PrimitiveType::*;
1502 RawPointer => "pointer",
1503 Reference => "reference",
1509 crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static SmallVec<[DefId; 4]> {
1510 Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
1513 crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>> {
1514 static CELL: OnceCell<FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>>> = OnceCell::new();
1516 CELL.get_or_init(move || {
1517 use self::PrimitiveType::*;
1519 /// A macro to create a FxHashMap.
1524 /// let letters = map!{"a" => "b", "c" => "d"};
1527 /// Trailing commas are allowed.
1528 /// Commas between elements are required (even if the expression is a block).
1530 ($( $key: expr => $val: expr ),* $(,)*) => {{
1531 let mut map = ::rustc_data_structures::fx::FxHashMap::default();
1532 $( map.insert($key, $val); )*
1537 let single = |a: Option<DefId>| a.into_iter().collect();
1538 let both = |a: Option<DefId>, b: Option<DefId>| -> SmallVec<_> {
1539 a.into_iter().chain(b).collect()
1542 let lang_items = tcx.lang_items();
1544 Isize => single(lang_items.isize_impl()),
1545 I8 => single(lang_items.i8_impl()),
1546 I16 => single(lang_items.i16_impl()),
1547 I32 => single(lang_items.i32_impl()),
1548 I64 => single(lang_items.i64_impl()),
1549 I128 => single(lang_items.i128_impl()),
1550 Usize => single(lang_items.usize_impl()),
1551 U8 => single(lang_items.u8_impl()),
1552 U16 => single(lang_items.u16_impl()),
1553 U32 => single(lang_items.u32_impl()),
1554 U64 => single(lang_items.u64_impl()),
1555 U128 => single(lang_items.u128_impl()),
1556 F32 => both(lang_items.f32_impl(), lang_items.f32_runtime_impl()),
1557 F64 => both(lang_items.f64_impl(), lang_items.f64_runtime_impl()),
1558 Char => single(lang_items.char_impl()),
1559 Bool => single(lang_items.bool_impl()),
1560 Str => both(lang_items.str_impl(), lang_items.str_alloc_impl()),
1565 .chain(lang_items.slice_u8_impl())
1566 .chain(lang_items.slice_alloc_impl())
1567 .chain(lang_items.slice_u8_alloc_impl())
1570 Array => single(lang_items.array_impl()),
1571 Tuple => smallvec![],
1572 Unit => smallvec![],
1577 .chain(lang_items.mut_ptr_impl())
1578 .chain(lang_items.const_slice_ptr_impl())
1579 .chain(lang_items.mut_slice_ptr_impl())
1582 Reference => smallvec![],
1584 Never => smallvec![],
1589 crate fn to_url_str(&self) -> &'static str {
1593 crate fn as_sym(&self) -> Symbol {
1594 use PrimitiveType::*;
1596 Isize => sym::isize,
1602 Usize => sym::usize,
1613 Array => sym::array,
1614 Slice => sym::slice,
1615 Tuple => sym::tuple,
1617 RawPointer => sym::pointer,
1618 Reference => sym::reference,
1620 Never => sym::never,
1625 impl From<ast::IntTy> for PrimitiveType {
1626 fn from(int_ty: ast::IntTy) -> PrimitiveType {
1628 ast::IntTy::Isize => PrimitiveType::Isize,
1629 ast::IntTy::I8 => PrimitiveType::I8,
1630 ast::IntTy::I16 => PrimitiveType::I16,
1631 ast::IntTy::I32 => PrimitiveType::I32,
1632 ast::IntTy::I64 => PrimitiveType::I64,
1633 ast::IntTy::I128 => PrimitiveType::I128,
1638 impl From<ast::UintTy> for PrimitiveType {
1639 fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1641 ast::UintTy::Usize => PrimitiveType::Usize,
1642 ast::UintTy::U8 => PrimitiveType::U8,
1643 ast::UintTy::U16 => PrimitiveType::U16,
1644 ast::UintTy::U32 => PrimitiveType::U32,
1645 ast::UintTy::U64 => PrimitiveType::U64,
1646 ast::UintTy::U128 => PrimitiveType::U128,
1651 impl From<ast::FloatTy> for PrimitiveType {
1652 fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1654 ast::FloatTy::F32 => PrimitiveType::F32,
1655 ast::FloatTy::F64 => PrimitiveType::F64,
1660 impl From<hir::PrimTy> for PrimitiveType {
1661 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1663 hir::PrimTy::Int(int_ty) => int_ty.into(),
1664 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1665 hir::PrimTy::Float(float_ty) => float_ty.into(),
1666 hir::PrimTy::Str => PrimitiveType::Str,
1667 hir::PrimTy::Bool => PrimitiveType::Bool,
1668 hir::PrimTy::Char => PrimitiveType::Char,
1673 #[derive(Copy, Clone, Debug)]
1674 crate enum Visibility {
1681 crate fn is_public(&self) -> bool {
1682 matches!(self, Visibility::Public)
1686 #[derive(Clone, Debug)]
1687 crate struct Struct {
1688 crate struct_type: doctree::StructType,
1689 crate generics: Generics,
1690 crate fields: Vec<Item>,
1691 crate fields_stripped: bool,
1694 #[derive(Clone, Debug)]
1695 crate struct Union {
1696 crate struct_type: doctree::StructType,
1697 crate generics: Generics,
1698 crate fields: Vec<Item>,
1699 crate fields_stripped: bool,
1702 /// This is a more limited form of the standard Struct, different in that
1703 /// it lacks the things most items have (name, id, parameterization). Found
1704 /// only as a variant in an enum.
1705 #[derive(Clone, Debug)]
1706 crate struct VariantStruct {
1707 crate struct_type: doctree::StructType,
1708 crate fields: Vec<Item>,
1709 crate fields_stripped: bool,
1712 #[derive(Clone, Debug)]
1714 crate variants: IndexVec<VariantIdx, Item>,
1715 crate generics: Generics,
1716 crate variants_stripped: bool,
1719 #[derive(Clone, Debug)]
1720 crate enum Variant {
1723 Struct(VariantStruct),
1726 /// Small wrapper around `rustc_span::Span` that adds helper methods and enforces calling `source_callsite`.
1727 #[derive(Clone, Debug)]
1728 crate struct Span(rustc_span::Span);
1731 crate fn from_rustc_span(sp: rustc_span::Span) -> Self {
1732 // Get the macro invocation instead of the definition,
1733 // in case the span is result of a macro expansion.
1734 // (See rust-lang/rust#39726)
1735 Self(sp.source_callsite())
1738 crate fn dummy() -> Self {
1739 Self(rustc_span::DUMMY_SP)
1742 crate fn span(&self) -> rustc_span::Span {
1746 crate fn filename(&self, sess: &Session) -> FileName {
1747 sess.source_map().span_to_filename(self.0)
1750 crate fn lo(&self, sess: &Session) -> Loc {
1751 sess.source_map().lookup_char_pos(self.0.lo())
1754 crate fn hi(&self, sess: &Session) -> Loc {
1755 sess.source_map().lookup_char_pos(self.0.hi())
1758 crate fn cnum(&self, sess: &Session) -> CrateNum {
1759 // FIXME: is there a time when the lo and hi crate would be different?
1760 self.lo(sess).file.cnum
1764 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1768 crate segments: Vec<PathSegment>,
1772 crate fn last(&self) -> Symbol {
1773 self.segments.last().expect("segments were empty").name
1776 crate fn last_name(&self) -> SymbolStr {
1777 self.segments.last().expect("segments were empty").name.as_str()
1780 crate fn whole_name(&self) -> String {
1781 String::from(if self.global { "::" } else { "" })
1782 + &self.segments.iter().map(|s| s.name.to_string()).collect::<Vec<_>>().join("::")
1786 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1787 crate enum GenericArg {
1793 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1794 crate enum GenericArgs {
1795 AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
1796 Parenthesized { inputs: Vec<Type>, output: Option<Type> },
1799 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1800 crate struct PathSegment {
1802 crate args: GenericArgs,
1805 #[derive(Clone, Debug)]
1806 crate struct Typedef {
1808 crate generics: Generics,
1809 /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
1810 /// alias instead of the final type. This will always have the final type, regardless of whether
1811 /// `type_` came from HIR or from metadata.
1813 /// If `item_type.is_none()`, `type_` is guarenteed to come from metadata (and therefore hold the
1815 crate item_type: Option<Type>,
1818 impl GetDefId for Typedef {
1819 fn def_id(&self) -> Option<DefId> {
1824 #[derive(Clone, Debug)]
1825 crate struct OpaqueTy {
1826 crate bounds: Vec<GenericBound>,
1827 crate generics: Generics,
1830 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1831 crate struct BareFunctionDecl {
1832 crate unsafety: hir::Unsafety,
1833 crate generic_params: Vec<GenericParamDef>,
1838 #[derive(Clone, Debug)]
1839 crate struct Static {
1841 crate mutability: Mutability,
1842 /// It's useful to have the value of a static documented, but I have no
1843 /// desire to represent expressions (that'd basically be all of the AST,
1844 /// which is huge!). So, have a string.
1848 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
1849 crate struct Constant {
1852 crate value: Option<String>,
1853 crate is_literal: bool,
1856 #[derive(Clone, Debug)]
1858 crate unsafety: hir::Unsafety,
1859 crate generics: Generics,
1860 crate provided_trait_methods: FxHashSet<Symbol>,
1861 crate trait_: Option<Type>,
1863 crate items: Vec<Item>,
1864 crate negative_polarity: bool,
1865 crate synthetic: bool,
1866 crate blanket_impl: Option<Type>,
1869 #[derive(Clone, Debug)]
1870 crate struct Import {
1871 crate kind: ImportKind,
1872 crate source: ImportSource,
1873 crate should_be_displayed: bool,
1877 crate fn new_simple(name: Symbol, source: ImportSource, should_be_displayed: bool) -> Self {
1878 Self { kind: ImportKind::Simple(name), source, should_be_displayed }
1881 crate fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
1882 Self { kind: ImportKind::Glob, source, should_be_displayed }
1886 #[derive(Clone, Debug)]
1887 crate enum ImportKind {
1888 // use source as str;
1894 #[derive(Clone, Debug)]
1895 crate struct ImportSource {
1897 crate did: Option<DefId>,
1900 #[derive(Clone, Debug)]
1901 crate struct Macro {
1902 crate source: String,
1903 crate imported_from: Option<Symbol>,
1906 #[derive(Clone, Debug)]
1907 crate struct ProcMacro {
1908 crate kind: MacroKind,
1909 crate helpers: Vec<Symbol>,
1912 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
1913 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
1914 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1915 crate struct TypeBinding {
1917 crate kind: TypeBindingKind,
1920 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1921 crate enum TypeBindingKind {
1922 Equality { ty: Type },
1923 Constraint { bounds: Vec<GenericBound> },
1927 crate fn ty(&self) -> &Type {
1929 TypeBindingKind::Equality { ref ty } => ty,
1930 _ => panic!("expected equality type binding for parenthesized generic args"),