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