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