]> git.proxmox.com Git - rustc.git/blame - src/librustdoc/clean/types.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustdoc / clean / types.rs
CommitLineData
dfeec247
XL
1use std::cell::RefCell;
2use std::default::Default;
60c5eb7d
XL
3use std::fmt;
4use std::hash::{Hash, Hasher};
60c5eb7d 5use std::iter::FromIterator;
3dfed10e 6use std::lazy::SyncOnceCell as OnceCell;
dfeec247 7use std::num::NonZeroU32;
60c5eb7d 8use std::rc::Rc;
60c5eb7d 9use std::sync::Arc;
dfeec247 10use std::{slice, vec};
60c5eb7d 11
74b04a01 12use rustc_ast::attr;
3dfed10e
XL
13use rustc_ast::util::comments::beautify_doc_string;
14use rustc_ast::{self as ast, AttrStyle};
dfeec247
XL
15use rustc_data_structures::fx::{FxHashMap, FxHashSet};
16use rustc_hir as hir;
17use rustc_hir::def::Res;
ba9703b0 18use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
3dfed10e 19use rustc_hir::lang_items::LangItem;
dfeec247 20use rustc_hir::Mutability;
60c5eb7d 21use rustc_index::vec::IndexVec;
ba9703b0 22use rustc_middle::middle::stability;
3dfed10e 23use rustc_middle::ty::{AssocKind, TyCtxt};
dfeec247
XL
24use rustc_span::hygiene::MacroKind;
25use rustc_span::source_map::DUMMY_SP;
3dfed10e 26use rustc_span::symbol::{kw, sym, Ident, Symbol};
dfeec247 27use rustc_span::{self, FileName};
ba9703b0 28use rustc_target::abi::VariantIdx;
60c5eb7d 29use rustc_target::spec::abi::Abi;
3dfed10e 30use smallvec::{smallvec, SmallVec};
60c5eb7d 31
60c5eb7d 32use crate::clean::cfg::Cfg;
60c5eb7d 33use crate::clean::external_path;
dfeec247 34use crate::clean::inline;
60c5eb7d 35use crate::clean::types::Type::{QPath, ResolvedPath};
dfeec247 36use crate::core::DocContext;
60c5eb7d 37use crate::doctree;
3dfed10e
XL
38use crate::formats::cache::cache;
39use crate::formats::item_type::ItemType;
40use crate::html::render::cache::ExternalLocation;
60c5eb7d 41
74b04a01 42use self::FnRetTy::*;
60c5eb7d
XL
43use self::ItemEnum::*;
44use self::SelfTy::*;
dfeec247 45use self::Type::*;
60c5eb7d
XL
46
47thread_local!(pub static MAX_DEF_ID: RefCell<FxHashMap<CrateNum, DefId>> = Default::default());
48
49#[derive(Clone, Debug)]
50pub struct Crate {
51 pub name: String,
52 pub version: Option<String>,
53 pub src: FileName,
54 pub module: Option<Item>,
55 pub externs: Vec<(CrateNum, ExternalCrate)>,
56 pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
57 // These are later on moved into `CACHEKEY`, leaving the map empty.
58 // Only here so that they can be filtered through the rustdoc passes.
59 pub external_traits: Rc<RefCell<FxHashMap<DefId, Trait>>>,
60 pub masked_crates: FxHashSet<CrateNum>,
61 pub collapsed: bool,
62}
63
64#[derive(Clone, Debug)]
65pub struct ExternalCrate {
66 pub name: String,
67 pub src: FileName,
68 pub attrs: Attributes,
69 pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
70 pub keywords: Vec<(DefId, String, Attributes)>,
71}
72
73/// Anything with a source location and set of attributes and, optionally, a
74/// name. That is, anything that can be documented. This doesn't correspond
75/// directly to the AST's concept of an item; it's a strict superset.
76#[derive(Clone)]
77pub struct Item {
78 /// Stringified span
79 pub source: Span,
80 /// Not everything has a name. E.g., impls
81 pub name: Option<String>,
82 pub attrs: Attributes,
83 pub inner: ItemEnum,
84 pub visibility: Visibility,
85 pub def_id: DefId,
86 pub stability: Option<Stability>,
87 pub deprecation: Option<Deprecation>,
88}
89
90impl fmt::Debug for Item {
91 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
f035d41b 92 let fake = self.is_fake();
60c5eb7d
XL
93 let def_id: &dyn fmt::Debug = if fake { &"**FAKE**" } else { &self.def_id };
94
95 fmt.debug_struct("Item")
96 .field("source", &self.source)
97 .field("name", &self.name)
98 .field("attrs", &self.attrs)
99 .field("inner", &self.inner)
100 .field("visibility", &self.visibility)
101 .field("def_id", def_id)
102 .field("stability", &self.stability)
103 .field("deprecation", &self.deprecation)
104 .finish()
105 }
106}
107
108impl Item {
109 /// Finds the `doc` attribute as a NameValue and returns the corresponding
110 /// value found.
111 pub fn doc_value(&self) -> Option<&str> {
112 self.attrs.doc_value()
113 }
114
115 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
116 /// with newlines.
117 pub fn collapsed_doc_value(&self) -> Option<String> {
118 self.attrs.collapsed_doc_value()
119 }
120
121 pub fn links(&self) -> Vec<(String, String)> {
122 self.attrs.links(&self.def_id.krate)
123 }
124
125 pub fn is_crate(&self) -> bool {
126 match self.inner {
dfeec247
XL
127 StrippedItem(box ModuleItem(Module { is_crate: true, .. }))
128 | ModuleItem(Module { is_crate: true, .. }) => true,
60c5eb7d
XL
129 _ => false,
130 }
131 }
132 pub fn is_mod(&self) -> bool {
133 self.type_() == ItemType::Module
134 }
135 pub fn is_trait(&self) -> bool {
136 self.type_() == ItemType::Trait
137 }
138 pub fn is_struct(&self) -> bool {
139 self.type_() == ItemType::Struct
140 }
141 pub fn is_enum(&self) -> bool {
142 self.type_() == ItemType::Enum
143 }
144 pub fn is_variant(&self) -> bool {
145 self.type_() == ItemType::Variant
146 }
147 pub fn is_associated_type(&self) -> bool {
148 self.type_() == ItemType::AssocType
149 }
150 pub fn is_associated_const(&self) -> bool {
151 self.type_() == ItemType::AssocConst
152 }
153 pub fn is_method(&self) -> bool {
154 self.type_() == ItemType::Method
155 }
156 pub fn is_ty_method(&self) -> bool {
157 self.type_() == ItemType::TyMethod
158 }
159 pub fn is_typedef(&self) -> bool {
160 self.type_() == ItemType::Typedef
161 }
162 pub fn is_primitive(&self) -> bool {
163 self.type_() == ItemType::Primitive
164 }
165 pub fn is_union(&self) -> bool {
166 self.type_() == ItemType::Union
167 }
168 pub fn is_import(&self) -> bool {
169 self.type_() == ItemType::Import
170 }
171 pub fn is_extern_crate(&self) -> bool {
172 self.type_() == ItemType::ExternCrate
173 }
174 pub fn is_keyword(&self) -> bool {
175 self.type_() == ItemType::Keyword
176 }
177 pub fn is_stripped(&self) -> bool {
dfeec247
XL
178 match self.inner {
179 StrippedItem(..) => true,
180 _ => false,
181 }
60c5eb7d
XL
182 }
183 pub fn has_stripped_fields(&self) -> Option<bool> {
184 match self.inner {
185 StructItem(ref _struct) => Some(_struct.fields_stripped),
186 UnionItem(ref union) => Some(union.fields_stripped),
dfeec247 187 VariantItem(Variant { kind: VariantKind::Struct(ref vstruct) }) => {
60c5eb7d 188 Some(vstruct.fields_stripped)
dfeec247 189 }
60c5eb7d
XL
190 _ => None,
191 }
192 }
193
194 pub fn stability_class(&self) -> Option<String> {
195 self.stability.as_ref().and_then(|ref s| {
196 let mut classes = Vec::with_capacity(2);
197
198 if s.level == stability::Unstable {
199 classes.push("unstable");
200 }
201
3dfed10e
XL
202 // FIXME: what about non-staged API items that are deprecated?
203 if self.deprecation.is_some() {
60c5eb7d
XL
204 classes.push("deprecated");
205 }
206
74b04a01 207 if !classes.is_empty() { Some(classes.join(" ")) } else { None }
60c5eb7d
XL
208 })
209 }
210
211 pub fn stable_since(&self) -> Option<&str> {
212 self.stability.as_ref().map(|s| &s.since[..])
213 }
214
215 pub fn is_non_exhaustive(&self) -> bool {
3dfed10e 216 self.attrs.other_attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
60c5eb7d
XL
217 }
218
219 /// Returns a documentation-level item type from the item.
220 pub fn type_(&self) -> ItemType {
221 ItemType::from(self)
222 }
223
60c5eb7d
XL
224 pub fn is_default(&self) -> bool {
225 match self.inner {
226 ItemEnum::MethodItem(ref meth) => {
227 if let Some(defaultness) = meth.defaultness {
228 defaultness.has_value() && !defaultness.is_final()
229 } else {
230 false
231 }
232 }
233 _ => false,
234 }
235 }
f035d41b
XL
236
237 /// See comments on next_def_id
238 pub fn is_fake(&self) -> bool {
239 MAX_DEF_ID.with(|m| {
240 m.borrow().get(&self.def_id.krate).map(|id| self.def_id >= *id).unwrap_or(false)
241 })
242 }
60c5eb7d
XL
243}
244
245#[derive(Clone, Debug)]
246pub enum ItemEnum {
247 ExternCrateItem(String, Option<String>),
248 ImportItem(Import),
249 StructItem(Struct),
250 UnionItem(Union),
251 EnumItem(Enum),
252 FunctionItem(Function),
253 ModuleItem(Module),
254 TypedefItem(Typedef, bool /* is associated type */),
255 OpaqueTyItem(OpaqueTy, bool /* is associated type */),
256 StaticItem(Static),
257 ConstantItem(Constant),
258 TraitItem(Trait),
259 TraitAliasItem(TraitAlias),
260 ImplItem(Impl),
261 /// A method signature only. Used for required methods in traits (ie,
262 /// non-default-methods).
263 TyMethodItem(TyMethod),
264 /// A method with a body.
265 MethodItem(Method),
266 StructFieldItem(Type),
267 VariantItem(Variant),
268 /// `fn`s from an extern block
269 ForeignFunctionItem(Function),
270 /// `static`s from an extern block
271 ForeignStaticItem(Static),
272 /// `type`s from an extern block
273 ForeignTypeItem,
274 MacroItem(Macro),
275 ProcMacroItem(ProcMacro),
276 PrimitiveItem(PrimitiveType),
277 AssocConstItem(Type, Option<String>),
278 AssocTypeItem(Vec<GenericBound>, Option<Type>),
279 /// An item that has been stripped by a rustdoc pass
280 StrippedItem(Box<ItemEnum>),
281 KeywordItem(String),
282}
283
284impl ItemEnum {
3dfed10e 285 pub fn is_type_alias(&self) -> bool {
60c5eb7d 286 match *self {
dfeec247 287 ItemEnum::TypedefItem(_, _) | ItemEnum::AssocTypeItem(_, _) => true,
60c5eb7d
XL
288 _ => false,
289 }
290 }
3dfed10e
XL
291
292 pub fn as_assoc_kind(&self) -> Option<AssocKind> {
293 match *self {
294 ItemEnum::AssocConstItem(..) => Some(AssocKind::Const),
295 ItemEnum::AssocTypeItem(..) => Some(AssocKind::Type),
296 ItemEnum::TyMethodItem(..) | ItemEnum::MethodItem(..) => Some(AssocKind::Fn),
297 _ => None,
298 }
299 }
60c5eb7d
XL
300}
301
302#[derive(Clone, Debug)]
303pub struct Module {
304 pub items: Vec<Item>,
305 pub is_crate: bool,
306}
307
308pub struct ListAttributesIter<'a> {
309 attrs: slice::Iter<'a, ast::Attribute>,
310 current_list: vec::IntoIter<ast::NestedMetaItem>,
311 name: Symbol,
312}
313
314impl<'a> Iterator for ListAttributesIter<'a> {
315 type Item = ast::NestedMetaItem;
316
317 fn next(&mut self) -> Option<Self::Item> {
318 if let Some(nested) = self.current_list.next() {
319 return Some(nested);
320 }
321
322 for attr in &mut self.attrs {
323 if let Some(list) = attr.meta_item_list() {
3dfed10e 324 if attr.has_name(self.name) {
60c5eb7d
XL
325 self.current_list = list.into_iter();
326 if let Some(nested) = self.current_list.next() {
327 return Some(nested);
328 }
329 }
330 }
331 }
332
333 None
334 }
335
336 fn size_hint(&self) -> (usize, Option<usize>) {
337 let lower = self.current_list.len();
338 (lower, None)
339 }
340}
341
342pub trait AttributesExt {
343 /// Finds an attribute as List and returns the list of attributes nested inside.
344 fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
345}
346
347impl AttributesExt for [ast::Attribute] {
348 fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
dfeec247 349 ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), name }
60c5eb7d
XL
350 }
351}
352
353pub trait NestedAttributesExt {
354 /// Returns `true` if the attribute list contains a specific `Word`
355 fn has_word(self, word: Symbol) -> bool;
356}
357
dfeec247 358impl<I: IntoIterator<Item = ast::NestedMetaItem>> NestedAttributesExt for I {
60c5eb7d 359 fn has_word(self, word: Symbol) -> bool {
3dfed10e 360 self.into_iter().any(|attr| attr.is_word() && attr.has_name(word))
60c5eb7d
XL
361 }
362}
363
364/// A portion of documentation, extracted from a `#[doc]` attribute.
365///
366/// Each variant contains the line number within the complete doc-comment where the fragment
367/// starts, as well as the Span where the corresponding doc comment or attribute is located.
368///
369/// Included files are kept separate from inline doc comments so that proper line-number
370/// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
371/// kept separate because of issue #42760.
372#[derive(Clone, PartialEq, Eq, Debug, Hash)]
373pub enum DocFragment {
374 /// A doc fragment created from a `///` or `//!` doc comment.
dfeec247 375 SugaredDoc(usize, rustc_span::Span, String),
60c5eb7d 376 /// A doc fragment created from a "raw" `#[doc=""]` attribute.
dfeec247 377 RawDoc(usize, rustc_span::Span, String),
60c5eb7d
XL
378 /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
379 /// given filename and the file contents.
dfeec247 380 Include(usize, rustc_span::Span, String, String),
60c5eb7d
XL
381}
382
383impl DocFragment {
384 pub fn as_str(&self) -> &str {
385 match *self {
386 DocFragment::SugaredDoc(_, _, ref s) => &s[..],
387 DocFragment::RawDoc(_, _, ref s) => &s[..],
388 DocFragment::Include(_, _, _, ref s) => &s[..],
389 }
390 }
391
dfeec247 392 pub fn span(&self) -> rustc_span::Span {
60c5eb7d 393 match *self {
dfeec247
XL
394 DocFragment::SugaredDoc(_, span, _)
395 | DocFragment::RawDoc(_, span, _)
396 | DocFragment::Include(_, span, _, _) => span,
60c5eb7d
XL
397 }
398 }
399}
400
401impl<'a> FromIterator<&'a DocFragment> for String {
402 fn from_iter<T>(iter: T) -> Self
403 where
dfeec247 404 T: IntoIterator<Item = &'a DocFragment>,
60c5eb7d
XL
405 {
406 iter.into_iter().fold(String::new(), |mut acc, frag| {
407 if !acc.is_empty() {
408 acc.push('\n');
409 }
410 match *frag {
411 DocFragment::SugaredDoc(_, _, ref docs)
dfeec247
XL
412 | DocFragment::RawDoc(_, _, ref docs)
413 | DocFragment::Include(_, _, _, ref docs) => acc.push_str(docs),
60c5eb7d
XL
414 }
415
416 acc
417 })
418 }
419}
420
421#[derive(Clone, Debug, Default)]
422pub struct Attributes {
423 pub doc_strings: Vec<DocFragment>,
424 pub other_attrs: Vec<ast::Attribute>,
425 pub cfg: Option<Arc<Cfg>>,
dfeec247 426 pub span: Option<rustc_span::Span>,
60c5eb7d
XL
427 /// map from Rust paths to resolved defs and potential URL fragments
428 pub links: Vec<(String, Option<DefId>, Option<String>)>,
429 pub inner_docs: bool,
430}
431
432impl Attributes {
433 /// Extracts the content from an attribute `#[doc(cfg(content))]`.
434 pub fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
3dfed10e 435 use rustc_ast::NestedMetaItem::MetaItem;
60c5eb7d
XL
436
437 if let ast::MetaItemKind::List(ref nmis) = mi.kind {
438 if nmis.len() == 1 {
439 if let MetaItem(ref cfg_mi) = nmis[0] {
3dfed10e 440 if cfg_mi.has_name(sym::cfg) {
60c5eb7d
XL
441 if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.kind {
442 if cfg_nmis.len() == 1 {
443 if let MetaItem(ref content_mi) = cfg_nmis[0] {
444 return Some(content_mi);
445 }
446 }
447 }
448 }
449 }
450 }
451 }
452
453 None
454 }
455
456 /// Reads a `MetaItem` from within an attribute, looks for whether it is a
457 /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
458 /// its expansion.
459 pub fn extract_include(mi: &ast::MetaItem) -> Option<(String, String)> {
460 mi.meta_item_list().and_then(|list| {
461 for meta in list {
3dfed10e 462 if meta.has_name(sym::include) {
60c5eb7d
XL
463 // the actual compiled `#[doc(include="filename")]` gets expanded to
464 // `#[doc(include(file="filename", contents="file contents")]` so we need to
465 // look for that instead
466 return meta.meta_item_list().and_then(|list| {
467 let mut filename: Option<String> = None;
468 let mut contents: Option<String> = None;
469
470 for it in list {
3dfed10e 471 if it.has_name(sym::file) {
60c5eb7d
XL
472 if let Some(name) = it.value_str() {
473 filename = Some(name.to_string());
474 }
3dfed10e 475 } else if it.has_name(sym::contents) {
60c5eb7d
XL
476 if let Some(docs) = it.value_str() {
477 contents = Some(docs.to_string());
478 }
479 }
480 }
481
482 if let (Some(filename), Some(contents)) = (filename, contents) {
483 Some((filename, contents))
484 } else {
485 None
486 }
487 });
488 }
489 }
490
491 None
492 })
493 }
494
495 pub fn has_doc_flag(&self, flag: Symbol) -> bool {
496 for attr in &self.other_attrs {
3dfed10e 497 if !attr.has_name(sym::doc) {
dfeec247
XL
498 continue;
499 }
60c5eb7d
XL
500
501 if let Some(items) = attr.meta_item_list() {
3dfed10e 502 if items.iter().filter_map(|i| i.meta_item()).any(|it| it.has_name(flag)) {
60c5eb7d
XL
503 return true;
504 }
505 }
506 }
507
508 false
509 }
510
dfeec247 511 pub fn from_ast(diagnostic: &::rustc_errors::Handler, attrs: &[ast::Attribute]) -> Attributes {
60c5eb7d
XL
512 let mut doc_strings = vec![];
513 let mut sp = None;
514 let mut cfg = Cfg::True;
515 let mut doc_line = 0;
516
dfeec247
XL
517 let other_attrs = attrs
518 .iter()
519 .filter_map(|attr| {
520 if let Some(value) = attr.doc_str() {
3dfed10e
XL
521 let value = beautify_doc_string(value);
522 let mk_fragment: fn(_, _, _) -> _ = if attr.is_doc_comment() {
523 DocFragment::SugaredDoc
dfeec247 524 } else {
3dfed10e 525 DocFragment::RawDoc
dfeec247 526 };
60c5eb7d 527
dfeec247
XL
528 let line = doc_line;
529 doc_line += value.lines().count();
530 doc_strings.push(mk_fragment(line, attr.span, value));
60c5eb7d 531
dfeec247
XL
532 if sp.is_none() {
533 sp = Some(attr.span);
534 }
535 None
536 } else {
3dfed10e 537 if attr.has_name(sym::doc) {
dfeec247
XL
538 if let Some(mi) = attr.meta() {
539 if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
540 // Extracted #[doc(cfg(...))]
541 match Cfg::parse(cfg_mi) {
542 Ok(new_cfg) => cfg &= new_cfg,
543 Err(e) => diagnostic.span_err(e.span, e.msg),
544 }
545 } else if let Some((filename, contents)) =
546 Attributes::extract_include(&mi)
547 {
548 let line = doc_line;
549 doc_line += contents.lines().count();
550 doc_strings.push(DocFragment::Include(
551 line, attr.span, filename, contents,
552 ));
60c5eb7d 553 }
60c5eb7d
XL
554 }
555 }
dfeec247 556 Some(attr.clone())
60c5eb7d 557 }
60c5eb7d 558 })
dfeec247 559 .collect();
60c5eb7d
XL
560
561 // treat #[target_feature(enable = "feat")] attributes as if they were
562 // #[doc(cfg(target_feature = "feat"))] attributes as well
563 for attr in attrs.lists(sym::target_feature) {
3dfed10e 564 if attr.has_name(sym::enable) {
60c5eb7d
XL
565 if let Some(feat) = attr.value_str() {
566 let meta = attr::mk_name_value_item_str(
dfeec247
XL
567 Ident::with_dummy_span(sym::target_feature),
568 feat,
569 DUMMY_SP,
60c5eb7d
XL
570 );
571 if let Ok(feat_cfg) = Cfg::parse(&meta) {
572 cfg &= feat_cfg;
573 }
574 }
575 }
576 }
577
dfeec247
XL
578 let inner_docs = attrs
579 .iter()
74b04a01 580 .find(|a| a.doc_str().is_some())
dfeec247 581 .map_or(true, |a| a.style == AttrStyle::Inner);
60c5eb7d
XL
582
583 Attributes {
584 doc_strings,
585 other_attrs,
586 cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) },
587 span: sp,
588 links: vec![],
589 inner_docs,
590 }
591 }
592
593 /// Finds the `doc` attribute as a NameValue and returns the corresponding
594 /// value found.
595 pub fn doc_value(&self) -> Option<&str> {
596 self.doc_strings.first().map(|s| s.as_str())
597 }
598
599 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
600 /// with newlines.
601 pub fn collapsed_doc_value(&self) -> Option<String> {
dfeec247 602 if !self.doc_strings.is_empty() { Some(self.doc_strings.iter().collect()) } else { None }
60c5eb7d
XL
603 }
604
605 /// Gets links as a vector
606 ///
607 /// Cache must be populated before call
608 pub fn links(&self, krate: &CrateNum) -> Vec<(String, String)> {
609 use crate::html::format::href;
f035d41b 610 use crate::html::render::CURRENT_DEPTH;
60c5eb7d 611
dfeec247
XL
612 self.links
613 .iter()
614 .filter_map(|&(ref s, did, ref fragment)| {
615 match did {
616 Some(did) => {
617 if let Some((mut href, ..)) = href(did) {
618 if let Some(ref fragment) = *fragment {
619 href.push_str("#");
620 href.push_str(fragment);
621 }
622 Some((s.clone(), href))
623 } else {
624 None
60c5eb7d 625 }
60c5eb7d 626 }
dfeec247
XL
627 None => {
628 if let Some(ref fragment) = *fragment {
629 let cache = cache();
630 let url = match cache.extern_locations.get(krate) {
f035d41b
XL
631 Some(&(_, _, ExternalLocation::Local)) => {
632 let depth = CURRENT_DEPTH.with(|l| l.get());
633 "../".repeat(depth)
dfeec247 634 }
f035d41b 635 Some(&(_, _, ExternalLocation::Remote(ref s))) => s.to_string(),
dfeec247 636 Some(&(_, _, ExternalLocation::Unknown)) | None => {
f035d41b 637 String::from("https://doc.rust-lang.org/nightly")
dfeec247
XL
638 }
639 };
640 // This is a primitive so the url is done "by hand".
641 let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
642 Some((
643 s.clone(),
644 format!(
645 "{}{}std/primitive.{}.html{}",
646 url,
647 if !url.ends_with('/') { "/" } else { "" },
648 &fragment[..tail],
649 &fragment[tail..]
650 ),
651 ))
652 } else {
653 panic!("This isn't a primitive?!");
654 }
60c5eb7d
XL
655 }
656 }
dfeec247
XL
657 })
658 .collect()
60c5eb7d 659 }
f9f354fc
XL
660
661 pub fn get_doc_aliases(&self) -> FxHashSet<String> {
662 self.other_attrs
663 .lists(sym::doc)
3dfed10e 664 .filter(|a| a.has_name(sym::alias))
f9f354fc
XL
665 .filter_map(|a| a.value_str().map(|s| s.to_string().replace("\"", "")))
666 .filter(|v| !v.is_empty())
667 .collect::<FxHashSet<_>>()
668 }
60c5eb7d
XL
669}
670
671impl PartialEq for Attributes {
672 fn eq(&self, rhs: &Self) -> bool {
dfeec247
XL
673 self.doc_strings == rhs.doc_strings
674 && self.cfg == rhs.cfg
675 && self.span == rhs.span
676 && self.links == rhs.links
677 && self
678 .other_attrs
679 .iter()
680 .map(|attr| attr.id)
681 .eq(rhs.other_attrs.iter().map(|attr| attr.id))
60c5eb7d
XL
682 }
683}
684
685impl Eq for Attributes {}
686
687impl Hash for Attributes {
688 fn hash<H: Hasher>(&self, hasher: &mut H) {
689 self.doc_strings.hash(hasher);
690 self.cfg.hash(hasher);
691 self.span.hash(hasher);
692 self.links.hash(hasher);
693 for attr in &self.other_attrs {
694 attr.id.hash(hasher);
695 }
696 }
697}
698
699impl AttributesExt for Attributes {
700 fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
701 self.other_attrs.lists(name)
702 }
703}
704
705#[derive(Clone, PartialEq, Eq, Debug, Hash)]
706pub enum GenericBound {
707 TraitBound(PolyTrait, hir::TraitBoundModifier),
708 Outlives(Lifetime),
709}
710
711impl GenericBound {
712 pub fn maybe_sized(cx: &DocContext<'_>) -> GenericBound {
3dfed10e 713 let did = cx.tcx.require_lang_item(LangItem::Sized, None);
60c5eb7d 714 let empty = cx.tcx.intern_substs(&[]);
dfeec247 715 let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
60c5eb7d 716 inline::record_extern_fqn(cx, did, TypeKind::Trait);
dfeec247
XL
717 GenericBound::TraitBound(
718 PolyTrait {
719 trait_: ResolvedPath { path, param_names: None, did, is_generic: false },
720 generic_params: Vec::new(),
60c5eb7d 721 },
dfeec247
XL
722 hir::TraitBoundModifier::Maybe,
723 )
60c5eb7d
XL
724 }
725
726 pub fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
dfeec247 727 use rustc_hir::TraitBoundModifier as TBM;
60c5eb7d
XL
728 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
729 if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
730 return true;
731 }
732 }
733 false
734 }
735
736 pub fn get_poly_trait(&self) -> Option<PolyTrait> {
737 if let GenericBound::TraitBound(ref p, _) = *self {
dfeec247 738 return Some(p.clone());
60c5eb7d
XL
739 }
740 None
741 }
742
743 pub fn get_trait_type(&self) -> Option<Type> {
744 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
745 Some(trait_.clone())
746 } else {
747 None
748 }
749 }
750}
751
752#[derive(Clone, PartialEq, Eq, Debug, Hash)]
753pub struct Lifetime(pub String);
754
755impl Lifetime {
756 pub fn get_ref<'a>(&'a self) -> &'a str {
757 let Lifetime(ref s) = *self;
758 let s: &'a str = s;
759 s
760 }
761
762 pub fn statik() -> Lifetime {
763 Lifetime("'static".to_string())
764 }
3dfed10e
XL
765
766 pub fn elided() -> Lifetime {
767 Lifetime("'_".to_string())
768 }
60c5eb7d
XL
769}
770
771#[derive(Clone, Debug)]
772pub enum WherePredicate {
773 BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
774 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
775 EqPredicate { lhs: Type, rhs: Type },
776}
777
778impl WherePredicate {
779 pub fn get_bounds(&self) -> Option<&[GenericBound]> {
780 match *self {
781 WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
782 WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
783 _ => None,
784 }
785 }
786}
787
788#[derive(Clone, PartialEq, Eq, Debug, Hash)]
789pub enum GenericParamDefKind {
790 Lifetime,
791 Type {
792 did: DefId,
793 bounds: Vec<GenericBound>,
794 default: Option<Type>,
795 synthetic: Option<hir::SyntheticTyParamKind>,
796 },
797 Const {
798 did: DefId,
799 ty: Type,
800 },
801}
802
803impl GenericParamDefKind {
804 pub fn is_type(&self) -> bool {
805 match *self {
806 GenericParamDefKind::Type { .. } => true,
807 _ => false,
808 }
809 }
810
811 // FIXME(eddyb) this either returns the default of a type parameter, or the
812 // type of a `const` parameter. It seems that the intention is to *visit*
813 // any embedded types, but `get_type` seems to be the wrong name for that.
814 pub fn get_type(&self) -> Option<Type> {
815 match self {
816 GenericParamDefKind::Type { default, .. } => default.clone(),
817 GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
818 GenericParamDefKind::Lifetime => None,
819 }
820 }
821}
822
823#[derive(Clone, PartialEq, Eq, Debug, Hash)]
824pub struct GenericParamDef {
825 pub name: String,
826 pub kind: GenericParamDefKind,
827}
828
829impl GenericParamDef {
830 pub fn is_synthetic_type_param(&self) -> bool {
831 match self.kind {
dfeec247 832 GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => false,
60c5eb7d
XL
833 GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
834 }
835 }
836
837 pub fn is_type(&self) -> bool {
838 self.kind.is_type()
839 }
840
841 pub fn get_type(&self) -> Option<Type> {
842 self.kind.get_type()
843 }
844
845 pub fn get_bounds(&self) -> Option<&[GenericBound]> {
846 match self.kind {
847 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
848 _ => None,
849 }
850 }
851}
852
853// maybe use a Generic enum and use Vec<Generic>?
854#[derive(Clone, Debug, Default)]
855pub struct Generics {
856 pub params: Vec<GenericParamDef>,
857 pub where_predicates: Vec<WherePredicate>,
858}
859
860#[derive(Clone, Debug)]
861pub struct Method {
862 pub generics: Generics,
863 pub decl: FnDecl,
864 pub header: hir::FnHeader,
865 pub defaultness: Option<hir::Defaultness>,
ba9703b0
XL
866 pub all_types: Vec<(Type, TypeKind)>,
867 pub ret_types: Vec<(Type, TypeKind)>,
60c5eb7d
XL
868}
869
870#[derive(Clone, Debug)]
871pub struct TyMethod {
872 pub header: hir::FnHeader,
873 pub decl: FnDecl,
874 pub generics: Generics,
ba9703b0
XL
875 pub all_types: Vec<(Type, TypeKind)>,
876 pub ret_types: Vec<(Type, TypeKind)>,
60c5eb7d
XL
877}
878
879#[derive(Clone, Debug)]
880pub struct Function {
881 pub decl: FnDecl,
882 pub generics: Generics,
883 pub header: hir::FnHeader,
ba9703b0
XL
884 pub all_types: Vec<(Type, TypeKind)>,
885 pub ret_types: Vec<(Type, TypeKind)>,
60c5eb7d
XL
886}
887
888#[derive(Clone, PartialEq, Eq, Debug, Hash)]
889pub struct FnDecl {
890 pub inputs: Arguments,
74b04a01 891 pub output: FnRetTy,
60c5eb7d
XL
892 pub c_variadic: bool,
893 pub attrs: Attributes,
894}
895
896impl FnDecl {
897 pub fn self_type(&self) -> Option<SelfTy> {
898 self.inputs.values.get(0).and_then(|v| v.to_self())
899 }
900
901 /// Returns the sugared return type for an async function.
902 ///
903 /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
904 /// will return `i32`.
905 ///
906 /// # Panics
907 ///
908 /// This function will panic if the return type does not match the expected sugaring for async
909 /// functions.
74b04a01 910 pub fn sugared_async_return_type(&self) -> FnRetTy {
60c5eb7d 911 match &self.output {
74b04a01 912 FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
dfeec247
XL
913 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
914 let bindings = trait_.bindings().unwrap();
74b04a01 915 FnRetTy::Return(bindings[0].ty().clone())
60c5eb7d 916 }
dfeec247
XL
917 _ => panic!("unexpected desugaring of async function"),
918 },
60c5eb7d
XL
919 _ => panic!("unexpected desugaring of async function"),
920 }
921 }
922}
923
924#[derive(Clone, PartialEq, Eq, Debug, Hash)]
925pub struct Arguments {
926 pub values: Vec<Argument>,
927}
928
929#[derive(Clone, PartialEq, Eq, Debug, Hash)]
930pub struct Argument {
931 pub type_: Type,
932 pub name: String,
933}
934
935#[derive(Clone, PartialEq, Debug)]
936pub enum SelfTy {
937 SelfValue,
938 SelfBorrowed(Option<Lifetime>, Mutability),
939 SelfExplicit(Type),
940}
941
942impl Argument {
943 pub fn to_self(&self) -> Option<SelfTy> {
944 if self.name != "self" {
945 return None;
946 }
947 if self.type_.is_self_type() {
948 return Some(SelfValue);
949 }
950 match self.type_ {
dfeec247 951 BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
60c5eb7d
XL
952 Some(SelfBorrowed(lifetime.clone(), mutability))
953 }
dfeec247 954 _ => Some(SelfExplicit(self.type_.clone())),
60c5eb7d
XL
955 }
956 }
957}
958
959#[derive(Clone, PartialEq, Eq, Debug, Hash)]
74b04a01 960pub enum FnRetTy {
60c5eb7d
XL
961 Return(Type),
962 DefaultReturn,
963}
964
74b04a01 965impl GetDefId for FnRetTy {
60c5eb7d
XL
966 fn def_id(&self) -> Option<DefId> {
967 match *self {
968 Return(ref ty) => ty.def_id(),
969 DefaultReturn => None,
970 }
971 }
972}
973
974#[derive(Clone, Debug)]
975pub struct Trait {
976 pub auto: bool,
977 pub unsafety: hir::Unsafety,
978 pub items: Vec<Item>,
979 pub generics: Generics,
980 pub bounds: Vec<GenericBound>,
3dfed10e 981 pub is_spotlight: bool,
60c5eb7d
XL
982 pub is_auto: bool,
983}
984
985#[derive(Clone, Debug)]
986pub struct TraitAlias {
987 pub generics: Generics,
988 pub bounds: Vec<GenericBound>,
989}
990
991/// A trait reference, which may have higher ranked lifetimes.
992#[derive(Clone, PartialEq, Eq, Debug, Hash)]
993pub struct PolyTrait {
994 pub trait_: Type,
995 pub generic_params: Vec<GenericParamDef>,
996}
997
998/// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
999/// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
1000/// importantly, it does not preserve mutability or boxes.
1001#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1002pub enum Type {
1003 /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
1004 ResolvedPath {
1005 path: Path,
1006 param_names: Option<Vec<GenericBound>>,
1007 did: DefId,
1008 /// `true` if is a `T::Name` path for associated types.
1009 is_generic: bool,
1010 },
1011 /// For parameterized types, so the consumer of the JSON don't go
1012 /// looking for types which don't exist anywhere.
1013 Generic(String),
1014 /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
1015 /// arrays, slices, and tuples.
1016 Primitive(PrimitiveType),
1017 /// `extern "ABI" fn`
1018 BareFunction(Box<BareFunctionDecl>),
1019 Tuple(Vec<Type>),
1020 Slice(Box<Type>),
1021 Array(Box<Type>, String),
1022 Never,
1023 RawPointer(Mutability, Box<Type>),
1024 BorrowedRef {
1025 lifetime: Option<Lifetime>,
1026 mutability: Mutability,
1027 type_: Box<Type>,
1028 },
1029
1030 // `<Type as Trait>::Name`
1031 QPath {
1032 name: String,
1033 self_type: Box<Type>,
dfeec247 1034 trait_: Box<Type>,
60c5eb7d
XL
1035 },
1036
1037 // `_`
1038 Infer,
1039
1040 // `impl TraitA + TraitB + ...`
1041 ImplTrait(Vec<GenericBound>),
1042}
1043
1044#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1045pub enum PrimitiveType {
dfeec247
XL
1046 Isize,
1047 I8,
1048 I16,
1049 I32,
1050 I64,
1051 I128,
1052 Usize,
1053 U8,
1054 U16,
1055 U32,
1056 U64,
1057 U128,
1058 F32,
1059 F64,
60c5eb7d
XL
1060 Char,
1061 Bool,
1062 Str,
1063 Slice,
1064 Array,
1065 Tuple,
1066 Unit,
1067 RawPointer,
1068 Reference,
1069 Fn,
1070 Never,
1071}
1072
ba9703b0 1073#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
60c5eb7d
XL
1074pub enum TypeKind {
1075 Enum,
1076 Function,
1077 Module,
1078 Const,
1079 Static,
1080 Struct,
1081 Union,
1082 Trait,
1083 Typedef,
1084 Foreign,
1085 Macro,
1086 Attr,
1087 Derive,
1088 TraitAlias,
1089}
1090
1091pub trait GetDefId {
1092 fn def_id(&self) -> Option<DefId>;
1093}
1094
1095impl<T: GetDefId> GetDefId for Option<T> {
1096 fn def_id(&self) -> Option<DefId> {
1097 self.as_ref().and_then(|d| d.def_id())
1098 }
1099}
1100
1101impl Type {
1102 pub fn primitive_type(&self) -> Option<PrimitiveType> {
1103 match *self {
dfeec247 1104 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
60c5eb7d
XL
1105 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1106 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
dfeec247
XL
1107 Tuple(ref tys) => {
1108 if tys.is_empty() {
1109 Some(PrimitiveType::Unit)
1110 } else {
1111 Some(PrimitiveType::Tuple)
1112 }
1113 }
60c5eb7d
XL
1114 RawPointer(..) => Some(PrimitiveType::RawPointer),
1115 BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
1116 BareFunction(..) => Some(PrimitiveType::Fn),
1117 Never => Some(PrimitiveType::Never),
1118 _ => None,
1119 }
1120 }
1121
1122 pub fn is_generic(&self) -> bool {
1123 match *self {
1124 ResolvedPath { is_generic, .. } => is_generic,
1125 _ => false,
1126 }
1127 }
1128
1129 pub fn is_self_type(&self) -> bool {
1130 match *self {
1131 Generic(ref name) => name == "Self",
dfeec247 1132 _ => false,
60c5eb7d
XL
1133 }
1134 }
1135
1136 pub fn generics(&self) -> Option<Vec<Type>> {
1137 match *self {
dfeec247
XL
1138 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1139 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
1140 Some(
1141 args.iter()
1142 .filter_map(|arg| match arg {
1143 GenericArg::Type(ty) => Some(ty.clone()),
1144 _ => None,
1145 })
1146 .collect(),
1147 )
1148 } else {
1149 None
1150 }
1151 }),
60c5eb7d
XL
1152 _ => None,
1153 }
1154 }
1155
1156 pub fn bindings(&self) -> Option<&[TypeBinding]> {
1157 match *self {
dfeec247
XL
1158 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1159 if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
1160 Some(&**bindings)
1161 } else {
1162 None
1163 }
1164 }),
1165 _ => None,
60c5eb7d
XL
1166 }
1167 }
1168
1169 pub fn is_full_generic(&self) -> bool {
1170 match *self {
1171 Type::Generic(_) => true,
1172 _ => false,
1173 }
1174 }
1175
1176 pub fn projection(&self) -> Option<(&Type, DefId, &str)> {
1177 let (self_, trait_, name) = match self {
dfeec247 1178 QPath { ref self_type, ref trait_, ref name } => (self_type, trait_, name),
60c5eb7d
XL
1179 _ => return None,
1180 };
1181 let trait_did = match **trait_ {
1182 ResolvedPath { did, .. } => did,
1183 _ => return None,
1184 };
1185 Some((&self_, trait_did, name))
1186 }
60c5eb7d
XL
1187}
1188
1189impl GetDefId for Type {
1190 fn def_id(&self) -> Option<DefId> {
1191 match *self {
1192 ResolvedPath { did, .. } => Some(did),
3dfed10e 1193 Primitive(p) => cache().primitive_locations.get(&p).cloned(),
dfeec247
XL
1194 BorrowedRef { type_: box Generic(..), .. } => {
1195 Primitive(PrimitiveType::Reference).def_id()
1196 }
60c5eb7d 1197 BorrowedRef { ref type_, .. } => type_.def_id(),
dfeec247
XL
1198 Tuple(ref tys) => {
1199 if tys.is_empty() {
1200 Primitive(PrimitiveType::Unit).def_id()
1201 } else {
1202 Primitive(PrimitiveType::Tuple).def_id()
1203 }
1204 }
60c5eb7d
XL
1205 BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
1206 Never => Primitive(PrimitiveType::Never).def_id(),
1207 Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
1208 Array(..) => Primitive(PrimitiveType::Array).def_id(),
1209 RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(),
1210 QPath { ref self_type, .. } => self_type.def_id(),
1211 _ => None,
1212 }
1213 }
1214}
1215
1216impl PrimitiveType {
3dfed10e 1217 pub fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
60c5eb7d 1218 match s {
3dfed10e
XL
1219 sym::isize => Some(PrimitiveType::Isize),
1220 sym::i8 => Some(PrimitiveType::I8),
1221 sym::i16 => Some(PrimitiveType::I16),
1222 sym::i32 => Some(PrimitiveType::I32),
1223 sym::i64 => Some(PrimitiveType::I64),
1224 sym::i128 => Some(PrimitiveType::I128),
1225 sym::usize => Some(PrimitiveType::Usize),
1226 sym::u8 => Some(PrimitiveType::U8),
1227 sym::u16 => Some(PrimitiveType::U16),
1228 sym::u32 => Some(PrimitiveType::U32),
1229 sym::u64 => Some(PrimitiveType::U64),
1230 sym::u128 => Some(PrimitiveType::U128),
1231 sym::bool => Some(PrimitiveType::Bool),
1232 sym::char => Some(PrimitiveType::Char),
1233 sym::str => Some(PrimitiveType::Str),
1234 sym::f32 => Some(PrimitiveType::F32),
1235 sym::f64 => Some(PrimitiveType::F64),
1236 sym::array => Some(PrimitiveType::Array),
1237 sym::slice => Some(PrimitiveType::Slice),
1238 sym::tuple => Some(PrimitiveType::Tuple),
1239 sym::unit => Some(PrimitiveType::Unit),
1240 sym::pointer => Some(PrimitiveType::RawPointer),
1241 sym::reference => Some(PrimitiveType::Reference),
1242 kw::Fn => Some(PrimitiveType::Fn),
1243 sym::never => Some(PrimitiveType::Never),
60c5eb7d
XL
1244 _ => None,
1245 }
1246 }
1247
1248 pub fn as_str(&self) -> &'static str {
1249 use self::PrimitiveType::*;
1250 match *self {
1251 Isize => "isize",
1252 I8 => "i8",
1253 I16 => "i16",
1254 I32 => "i32",
1255 I64 => "i64",
1256 I128 => "i128",
1257 Usize => "usize",
1258 U8 => "u8",
1259 U16 => "u16",
1260 U32 => "u32",
1261 U64 => "u64",
1262 U128 => "u128",
1263 F32 => "f32",
1264 F64 => "f64",
1265 Str => "str",
1266 Bool => "bool",
1267 Char => "char",
1268 Array => "array",
1269 Slice => "slice",
1270 Tuple => "tuple",
1271 Unit => "unit",
1272 RawPointer => "pointer",
1273 Reference => "reference",
1274 Fn => "fn",
1275 Never => "never",
1276 }
1277 }
1278
3dfed10e
XL
1279 pub fn impls(&self, tcx: TyCtxt<'_>) -> &'static SmallVec<[DefId; 4]> {
1280 Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
1281 }
1282
1283 pub fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>> {
1284 static CELL: OnceCell<FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>>> = OnceCell::new();
1285
1286 CELL.get_or_init(move || {
1287 use self::PrimitiveType::*;
1288
1289 /// A macro to create a FxHashMap.
1290 ///
1291 /// Example:
1292 ///
1293 /// ```
1294 /// let letters = map!{"a" => "b", "c" => "d"};
1295 /// ```
1296 ///
1297 /// Trailing commas are allowed.
1298 /// Commas between elements are required (even if the expression is a block).
1299 macro_rules! map {
1300 ($( $key: expr => $val: expr ),* $(,)*) => {{
1301 let mut map = ::rustc_data_structures::fx::FxHashMap::default();
1302 $( map.insert($key, $val); )*
1303 map
1304 }}
1305 }
1306
1307 let single = |a: Option<DefId>| a.into_iter().collect();
1308 let both = |a: Option<DefId>, b: Option<DefId>| -> SmallVec<_> {
1309 a.into_iter().chain(b).collect()
1310 };
1311
1312 let lang_items = tcx.lang_items();
1313 map! {
1314 Isize => single(lang_items.isize_impl()),
1315 I8 => single(lang_items.i8_impl()),
1316 I16 => single(lang_items.i16_impl()),
1317 I32 => single(lang_items.i32_impl()),
1318 I64 => single(lang_items.i64_impl()),
1319 I128 => single(lang_items.i128_impl()),
1320 Usize => single(lang_items.usize_impl()),
1321 U8 => single(lang_items.u8_impl()),
1322 U16 => single(lang_items.u16_impl()),
1323 U32 => single(lang_items.u32_impl()),
1324 U64 => single(lang_items.u64_impl()),
1325 U128 => single(lang_items.u128_impl()),
1326 F32 => both(lang_items.f32_impl(), lang_items.f32_runtime_impl()),
1327 F64 => both(lang_items.f64_impl(), lang_items.f64_runtime_impl()),
1328 Char => single(lang_items.char_impl()),
1329 Bool => single(lang_items.bool_impl()),
1330 Str => both(lang_items.str_impl(), lang_items.str_alloc_impl()),
1331 Slice => {
1332 lang_items
1333 .slice_impl()
1334 .into_iter()
1335 .chain(lang_items.slice_u8_impl())
1336 .chain(lang_items.slice_alloc_impl())
1337 .chain(lang_items.slice_u8_alloc_impl())
1338 .collect()
1339 },
1340 Array => single(lang_items.array_impl()),
1341 Tuple => smallvec![],
1342 Unit => smallvec![],
1343 RawPointer => {
1344 lang_items
1345 .const_ptr_impl()
1346 .into_iter()
1347 .chain(lang_items.mut_ptr_impl())
1348 .chain(lang_items.const_slice_ptr_impl())
1349 .chain(lang_items.mut_slice_ptr_impl())
1350 .collect()
1351 },
1352 Reference => smallvec![],
1353 Fn => smallvec![],
1354 Never => smallvec![],
1355 }
1356 })
1357 }
1358
60c5eb7d
XL
1359 pub fn to_url_str(&self) -> &'static str {
1360 self.as_str()
1361 }
1362}
1363
1364impl From<ast::IntTy> for PrimitiveType {
1365 fn from(int_ty: ast::IntTy) -> PrimitiveType {
1366 match int_ty {
1367 ast::IntTy::Isize => PrimitiveType::Isize,
1368 ast::IntTy::I8 => PrimitiveType::I8,
1369 ast::IntTy::I16 => PrimitiveType::I16,
1370 ast::IntTy::I32 => PrimitiveType::I32,
1371 ast::IntTy::I64 => PrimitiveType::I64,
1372 ast::IntTy::I128 => PrimitiveType::I128,
1373 }
1374 }
1375}
1376
1377impl From<ast::UintTy> for PrimitiveType {
1378 fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1379 match uint_ty {
1380 ast::UintTy::Usize => PrimitiveType::Usize,
1381 ast::UintTy::U8 => PrimitiveType::U8,
1382 ast::UintTy::U16 => PrimitiveType::U16,
1383 ast::UintTy::U32 => PrimitiveType::U32,
1384 ast::UintTy::U64 => PrimitiveType::U64,
1385 ast::UintTy::U128 => PrimitiveType::U128,
1386 }
1387 }
1388}
1389
1390impl From<ast::FloatTy> for PrimitiveType {
1391 fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1392 match float_ty {
1393 ast::FloatTy::F32 => PrimitiveType::F32,
1394 ast::FloatTy::F64 => PrimitiveType::F64,
1395 }
1396 }
1397}
1398
74b04a01
XL
1399impl From<hir::PrimTy> for PrimitiveType {
1400 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1401 match prim_ty {
1402 hir::PrimTy::Int(int_ty) => int_ty.into(),
1403 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1404 hir::PrimTy::Float(float_ty) => float_ty.into(),
1405 hir::PrimTy::Str => PrimitiveType::Str,
1406 hir::PrimTy::Bool => PrimitiveType::Bool,
1407 hir::PrimTy::Char => PrimitiveType::Char,
1408 }
1409 }
1410}
1411
60c5eb7d
XL
1412#[derive(Clone, PartialEq, Eq, Debug)]
1413pub enum Visibility {
1414 Public,
1415 Inherited,
1416 Crate,
1417 Restricted(DefId, Path),
1418}
1419
1420#[derive(Clone, Debug)]
1421pub struct Struct {
1422 pub struct_type: doctree::StructType,
1423 pub generics: Generics,
1424 pub fields: Vec<Item>,
1425 pub fields_stripped: bool,
1426}
1427
1428#[derive(Clone, Debug)]
1429pub struct Union {
1430 pub struct_type: doctree::StructType,
1431 pub generics: Generics,
1432 pub fields: Vec<Item>,
1433 pub fields_stripped: bool,
1434}
1435
1436/// This is a more limited form of the standard Struct, different in that
1437/// it lacks the things most items have (name, id, parameterization). Found
1438/// only as a variant in an enum.
1439#[derive(Clone, Debug)]
1440pub struct VariantStruct {
1441 pub struct_type: doctree::StructType,
1442 pub fields: Vec<Item>,
1443 pub fields_stripped: bool,
1444}
1445
1446#[derive(Clone, Debug)]
1447pub struct Enum {
1448 pub variants: IndexVec<VariantIdx, Item>,
1449 pub generics: Generics,
1450 pub variants_stripped: bool,
1451}
1452
1453#[derive(Clone, Debug)]
1454pub struct Variant {
1455 pub kind: VariantKind,
1456}
1457
1458#[derive(Clone, Debug)]
1459pub enum VariantKind {
1460 CLike,
1461 Tuple(Vec<Type>),
1462 Struct(VariantStruct),
1463}
1464
1465#[derive(Clone, Debug)]
1466pub struct Span {
1467 pub filename: FileName,
ba9703b0 1468 pub cnum: CrateNum,
60c5eb7d
XL
1469 pub loline: usize,
1470 pub locol: usize,
1471 pub hiline: usize,
1472 pub hicol: usize,
dfeec247 1473 pub original: rustc_span::Span,
60c5eb7d
XL
1474}
1475
1476impl Span {
1477 pub fn empty() -> Span {
1478 Span {
1479 filename: FileName::Anon(0),
ba9703b0 1480 cnum: LOCAL_CRATE,
dfeec247
XL
1481 loline: 0,
1482 locol: 0,
1483 hiline: 0,
1484 hicol: 0,
1485 original: rustc_span::DUMMY_SP,
60c5eb7d
XL
1486 }
1487 }
1488
dfeec247 1489 pub fn span(&self) -> rustc_span::Span {
60c5eb7d
XL
1490 self.original
1491 }
1492}
1493
1494#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1495pub struct Path {
1496 pub global: bool,
1497 pub res: Res,
1498 pub segments: Vec<PathSegment>,
1499}
1500
1501impl Path {
1502 pub fn last_name(&self) -> &str {
1503 self.segments.last().expect("segments were empty").name.as_str()
1504 }
1505}
1506
1507#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1508pub enum GenericArg {
1509 Lifetime(Lifetime),
1510 Type(Type),
1511 Const(Constant),
1512}
1513
1514#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1515pub enum GenericArgs {
dfeec247
XL
1516 AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
1517 Parenthesized { inputs: Vec<Type>, output: Option<Type> },
60c5eb7d
XL
1518}
1519
1520#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1521pub struct PathSegment {
1522 pub name: String,
1523 pub args: GenericArgs,
1524}
1525
1526#[derive(Clone, Debug)]
1527pub struct Typedef {
1528 pub type_: Type,
1529 pub generics: Generics,
dfeec247
XL
1530 // Type of target item.
1531 pub item_type: Option<Type>,
1532}
1533
1534impl GetDefId for Typedef {
1535 fn def_id(&self) -> Option<DefId> {
1536 self.type_.def_id()
1537 }
60c5eb7d
XL
1538}
1539
1540#[derive(Clone, Debug)]
1541pub struct OpaqueTy {
1542 pub bounds: Vec<GenericBound>,
1543 pub generics: Generics,
1544}
1545
1546#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1547pub struct BareFunctionDecl {
1548 pub unsafety: hir::Unsafety,
1549 pub generic_params: Vec<GenericParamDef>,
1550 pub decl: FnDecl,
1551 pub abi: Abi,
1552}
1553
1554#[derive(Clone, Debug)]
1555pub struct Static {
1556 pub type_: Type,
1557 pub mutability: Mutability,
1558 /// It's useful to have the value of a static documented, but I have no
1559 /// desire to represent expressions (that'd basically be all of the AST,
1560 /// which is huge!). So, have a string.
1561 pub expr: String,
1562}
1563
1564#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1565pub struct Constant {
1566 pub type_: Type,
1567 pub expr: String,
dfeec247
XL
1568 pub value: Option<String>,
1569 pub is_literal: bool,
60c5eb7d
XL
1570}
1571
1572#[derive(Clone, PartialEq, Debug)]
1573pub enum ImplPolarity {
1574 Positive,
1575 Negative,
1576}
1577
1578#[derive(Clone, Debug)]
1579pub struct Impl {
1580 pub unsafety: hir::Unsafety,
1581 pub generics: Generics,
1582 pub provided_trait_methods: FxHashSet<String>,
1583 pub trait_: Option<Type>,
1584 pub for_: Type,
1585 pub items: Vec<Item>,
1586 pub polarity: Option<ImplPolarity>,
1587 pub synthetic: bool,
1588 pub blanket_impl: Option<Type>,
1589}
1590
1591#[derive(Clone, Debug)]
1592pub enum Import {
1593 // use source as str;
1594 Simple(String, ImportSource),
1595 // use source::*;
dfeec247 1596 Glob(ImportSource),
60c5eb7d
XL
1597}
1598
1599#[derive(Clone, Debug)]
1600pub struct ImportSource {
1601 pub path: Path,
1602 pub did: Option<DefId>,
1603}
1604
1605#[derive(Clone, Debug)]
1606pub struct Macro {
1607 pub source: String,
1608 pub imported_from: Option<String>,
1609}
1610
1611#[derive(Clone, Debug)]
1612pub struct ProcMacro {
1613 pub kind: MacroKind,
1614 pub helpers: Vec<String>,
1615}
1616
1617#[derive(Clone, Debug)]
1618pub struct Stability {
1619 pub level: stability::StabilityLevel,
3dfed10e 1620 pub feature: String,
60c5eb7d 1621 pub since: String,
60c5eb7d
XL
1622 pub unstable_reason: Option<String>,
1623 pub issue: Option<NonZeroU32>,
1624}
1625
1626#[derive(Clone, Debug)]
1627pub struct Deprecation {
1628 pub since: Option<String>,
1629 pub note: Option<String>,
3dfed10e 1630 pub is_since_rustc_version: bool,
60c5eb7d
XL
1631}
1632
1633/// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
1634/// `A: Send + Sync` in `Foo<A: Send + Sync>`).
1635#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1636pub struct TypeBinding {
1637 pub name: String,
1638 pub kind: TypeBindingKind,
1639}
1640
1641#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1642pub enum TypeBindingKind {
dfeec247
XL
1643 Equality { ty: Type },
1644 Constraint { bounds: Vec<GenericBound> },
60c5eb7d
XL
1645}
1646
1647impl TypeBinding {
1648 pub fn ty(&self) -> &Type {
1649 match self.kind {
1650 TypeBindingKind::Equality { ref ty } => ty,
1651 _ => panic!("expected equality type binding for parenthesized generic args"),
1652 }
1653 }
1654}