]> git.proxmox.com Git - rustc.git/blame - src/librustdoc/clean/types.rs
New upstream version 1.44.1+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 10
74b04a01
XL
11use rustc_ast::ast::{self, AttrStyle, Ident};
12use rustc_ast::attr;
13use rustc_ast::util::comments::strip_doc_comment_decoration;
dfeec247
XL
14use rustc_data_structures::fx::{FxHashMap, FxHashSet};
15use rustc_hir as hir;
16use rustc_hir::def::Res;
ba9703b0
XL
17use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
18use rustc_hir::lang_items;
dfeec247 19use rustc_hir::Mutability;
60c5eb7d 20use rustc_index::vec::IndexVec;
ba9703b0 21use rustc_middle::middle::stability;
dfeec247
XL
22use rustc_span::hygiene::MacroKind;
23use rustc_span::source_map::DUMMY_SP;
24use rustc_span::symbol::{sym, Symbol};
25use rustc_span::{self, FileName};
ba9703b0 26use rustc_target::abi::VariantIdx;
60c5eb7d 27use rustc_target::spec::abi::Abi;
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
74b04a01 38use self::FnRetTy::*;
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
74b04a01 204 if !classes.is_empty() { 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> {
74b04a01 424 use rustc_ast::ast::NestedMetaItem::MetaItem;
60c5eb7d
XL
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()
74b04a01 568 .find(|a| a.doc_str().is_some())
dfeec247 569 .map_or(true, |a| a.style == AttrStyle::Inner);
60c5eb7d
XL
570
571 Attributes {
572 doc_strings,
573 other_attrs,
574 cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) },
575 span: sp,
576 links: vec![],
577 inner_docs,
578 }
579 }
580
581 /// Finds the `doc` attribute as a NameValue and returns the corresponding
582 /// value found.
583 pub fn doc_value(&self) -> Option<&str> {
584 self.doc_strings.first().map(|s| s.as_str())
585 }
586
587 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
588 /// with newlines.
589 pub fn collapsed_doc_value(&self) -> Option<String> {
dfeec247 590 if !self.doc_strings.is_empty() { Some(self.doc_strings.iter().collect()) } else { None }
60c5eb7d
XL
591 }
592
593 /// Gets links as a vector
594 ///
595 /// Cache must be populated before call
596 pub fn links(&self, krate: &CrateNum) -> Vec<(String, String)> {
597 use crate::html::format::href;
598
dfeec247
XL
599 self.links
600 .iter()
601 .filter_map(|&(ref s, did, ref fragment)| {
602 match did {
603 Some(did) => {
604 if let Some((mut href, ..)) = href(did) {
605 if let Some(ref fragment) = *fragment {
606 href.push_str("#");
607 href.push_str(fragment);
608 }
609 Some((s.clone(), href))
610 } else {
611 None
60c5eb7d 612 }
60c5eb7d 613 }
dfeec247
XL
614 None => {
615 if let Some(ref fragment) = *fragment {
616 let cache = cache();
617 let url = match cache.extern_locations.get(krate) {
618 Some(&(_, ref src, ExternalLocation::Local)) => {
619 src.to_str().expect("invalid file path")
620 }
621 Some(&(_, _, ExternalLocation::Remote(ref s))) => s,
622 Some(&(_, _, ExternalLocation::Unknown)) | None => {
623 "https://doc.rust-lang.org/nightly"
624 }
625 };
626 // This is a primitive so the url is done "by hand".
627 let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
628 Some((
629 s.clone(),
630 format!(
631 "{}{}std/primitive.{}.html{}",
632 url,
633 if !url.ends_with('/') { "/" } else { "" },
634 &fragment[..tail],
635 &fragment[tail..]
636 ),
637 ))
638 } else {
639 panic!("This isn't a primitive?!");
640 }
60c5eb7d
XL
641 }
642 }
dfeec247
XL
643 })
644 .collect()
60c5eb7d
XL
645 }
646}
647
648impl PartialEq for Attributes {
649 fn eq(&self, rhs: &Self) -> bool {
dfeec247
XL
650 self.doc_strings == rhs.doc_strings
651 && self.cfg == rhs.cfg
652 && self.span == rhs.span
653 && self.links == rhs.links
654 && self
655 .other_attrs
656 .iter()
657 .map(|attr| attr.id)
658 .eq(rhs.other_attrs.iter().map(|attr| attr.id))
60c5eb7d
XL
659 }
660}
661
662impl Eq for Attributes {}
663
664impl Hash for Attributes {
665 fn hash<H: Hasher>(&self, hasher: &mut H) {
666 self.doc_strings.hash(hasher);
667 self.cfg.hash(hasher);
668 self.span.hash(hasher);
669 self.links.hash(hasher);
670 for attr in &self.other_attrs {
671 attr.id.hash(hasher);
672 }
673 }
674}
675
676impl AttributesExt for Attributes {
677 fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
678 self.other_attrs.lists(name)
679 }
680}
681
682#[derive(Clone, PartialEq, Eq, Debug, Hash)]
683pub enum GenericBound {
684 TraitBound(PolyTrait, hir::TraitBoundModifier),
685 Outlives(Lifetime),
686}
687
688impl GenericBound {
689 pub fn maybe_sized(cx: &DocContext<'_>) -> GenericBound {
690 let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None);
691 let empty = cx.tcx.intern_substs(&[]);
dfeec247 692 let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
60c5eb7d 693 inline::record_extern_fqn(cx, did, TypeKind::Trait);
dfeec247
XL
694 GenericBound::TraitBound(
695 PolyTrait {
696 trait_: ResolvedPath { path, param_names: None, did, is_generic: false },
697 generic_params: Vec::new(),
60c5eb7d 698 },
dfeec247
XL
699 hir::TraitBoundModifier::Maybe,
700 )
60c5eb7d
XL
701 }
702
703 pub fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
dfeec247 704 use rustc_hir::TraitBoundModifier as TBM;
60c5eb7d
XL
705 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
706 if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
707 return true;
708 }
709 }
710 false
711 }
712
713 pub fn get_poly_trait(&self) -> Option<PolyTrait> {
714 if let GenericBound::TraitBound(ref p, _) = *self {
dfeec247 715 return Some(p.clone());
60c5eb7d
XL
716 }
717 None
718 }
719
720 pub fn get_trait_type(&self) -> Option<Type> {
721 if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
722 Some(trait_.clone())
723 } else {
724 None
725 }
726 }
727}
728
729#[derive(Clone, PartialEq, Eq, Debug, Hash)]
730pub struct Lifetime(pub String);
731
732impl Lifetime {
733 pub fn get_ref<'a>(&'a self) -> &'a str {
734 let Lifetime(ref s) = *self;
735 let s: &'a str = s;
736 s
737 }
738
739 pub fn statik() -> Lifetime {
740 Lifetime("'static".to_string())
741 }
742}
743
744#[derive(Clone, Debug)]
745pub enum WherePredicate {
746 BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
747 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
748 EqPredicate { lhs: Type, rhs: Type },
749}
750
751impl WherePredicate {
752 pub fn get_bounds(&self) -> Option<&[GenericBound]> {
753 match *self {
754 WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
755 WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
756 _ => None,
757 }
758 }
759}
760
761#[derive(Clone, PartialEq, Eq, Debug, Hash)]
762pub enum GenericParamDefKind {
763 Lifetime,
764 Type {
765 did: DefId,
766 bounds: Vec<GenericBound>,
767 default: Option<Type>,
768 synthetic: Option<hir::SyntheticTyParamKind>,
769 },
770 Const {
771 did: DefId,
772 ty: Type,
773 },
774}
775
776impl GenericParamDefKind {
777 pub fn is_type(&self) -> bool {
778 match *self {
779 GenericParamDefKind::Type { .. } => true,
780 _ => false,
781 }
782 }
783
784 // FIXME(eddyb) this either returns the default of a type parameter, or the
785 // type of a `const` parameter. It seems that the intention is to *visit*
786 // any embedded types, but `get_type` seems to be the wrong name for that.
787 pub fn get_type(&self) -> Option<Type> {
788 match self {
789 GenericParamDefKind::Type { default, .. } => default.clone(),
790 GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
791 GenericParamDefKind::Lifetime => None,
792 }
793 }
794}
795
796#[derive(Clone, PartialEq, Eq, Debug, Hash)]
797pub struct GenericParamDef {
798 pub name: String,
799 pub kind: GenericParamDefKind,
800}
801
802impl GenericParamDef {
803 pub fn is_synthetic_type_param(&self) -> bool {
804 match self.kind {
dfeec247 805 GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => false,
60c5eb7d
XL
806 GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
807 }
808 }
809
810 pub fn is_type(&self) -> bool {
811 self.kind.is_type()
812 }
813
814 pub fn get_type(&self) -> Option<Type> {
815 self.kind.get_type()
816 }
817
818 pub fn get_bounds(&self) -> Option<&[GenericBound]> {
819 match self.kind {
820 GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
821 _ => None,
822 }
823 }
824}
825
826// maybe use a Generic enum and use Vec<Generic>?
827#[derive(Clone, Debug, Default)]
828pub struct Generics {
829 pub params: Vec<GenericParamDef>,
830 pub where_predicates: Vec<WherePredicate>,
831}
832
833#[derive(Clone, Debug)]
834pub struct Method {
835 pub generics: Generics,
836 pub decl: FnDecl,
837 pub header: hir::FnHeader,
838 pub defaultness: Option<hir::Defaultness>,
ba9703b0
XL
839 pub all_types: Vec<(Type, TypeKind)>,
840 pub ret_types: Vec<(Type, TypeKind)>,
60c5eb7d
XL
841}
842
843#[derive(Clone, Debug)]
844pub struct TyMethod {
845 pub header: hir::FnHeader,
846 pub decl: FnDecl,
847 pub generics: Generics,
ba9703b0
XL
848 pub all_types: Vec<(Type, TypeKind)>,
849 pub ret_types: Vec<(Type, TypeKind)>,
60c5eb7d
XL
850}
851
852#[derive(Clone, Debug)]
853pub struct Function {
854 pub decl: FnDecl,
855 pub generics: Generics,
856 pub header: hir::FnHeader,
ba9703b0
XL
857 pub all_types: Vec<(Type, TypeKind)>,
858 pub ret_types: Vec<(Type, TypeKind)>,
60c5eb7d
XL
859}
860
861#[derive(Clone, PartialEq, Eq, Debug, Hash)]
862pub struct FnDecl {
863 pub inputs: Arguments,
74b04a01 864 pub output: FnRetTy,
60c5eb7d
XL
865 pub c_variadic: bool,
866 pub attrs: Attributes,
867}
868
869impl FnDecl {
870 pub fn self_type(&self) -> Option<SelfTy> {
871 self.inputs.values.get(0).and_then(|v| v.to_self())
872 }
873
874 /// Returns the sugared return type for an async function.
875 ///
876 /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
877 /// will return `i32`.
878 ///
879 /// # Panics
880 ///
881 /// This function will panic if the return type does not match the expected sugaring for async
882 /// functions.
74b04a01 883 pub fn sugared_async_return_type(&self) -> FnRetTy {
60c5eb7d 884 match &self.output {
74b04a01 885 FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
dfeec247
XL
886 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
887 let bindings = trait_.bindings().unwrap();
74b04a01 888 FnRetTy::Return(bindings[0].ty().clone())
60c5eb7d 889 }
dfeec247
XL
890 _ => panic!("unexpected desugaring of async function"),
891 },
60c5eb7d
XL
892 _ => panic!("unexpected desugaring of async function"),
893 }
894 }
895}
896
897#[derive(Clone, PartialEq, Eq, Debug, Hash)]
898pub struct Arguments {
899 pub values: Vec<Argument>,
900}
901
902#[derive(Clone, PartialEq, Eq, Debug, Hash)]
903pub struct Argument {
904 pub type_: Type,
905 pub name: String,
906}
907
908#[derive(Clone, PartialEq, Debug)]
909pub enum SelfTy {
910 SelfValue,
911 SelfBorrowed(Option<Lifetime>, Mutability),
912 SelfExplicit(Type),
913}
914
915impl Argument {
916 pub fn to_self(&self) -> Option<SelfTy> {
917 if self.name != "self" {
918 return None;
919 }
920 if self.type_.is_self_type() {
921 return Some(SelfValue);
922 }
923 match self.type_ {
dfeec247 924 BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
60c5eb7d
XL
925 Some(SelfBorrowed(lifetime.clone(), mutability))
926 }
dfeec247 927 _ => Some(SelfExplicit(self.type_.clone())),
60c5eb7d
XL
928 }
929 }
930}
931
932#[derive(Clone, PartialEq, Eq, Debug, Hash)]
74b04a01 933pub enum FnRetTy {
60c5eb7d
XL
934 Return(Type),
935 DefaultReturn,
936}
937
74b04a01 938impl GetDefId for FnRetTy {
60c5eb7d
XL
939 fn def_id(&self) -> Option<DefId> {
940 match *self {
941 Return(ref ty) => ty.def_id(),
942 DefaultReturn => None,
943 }
944 }
945}
946
947#[derive(Clone, Debug)]
948pub struct Trait {
949 pub auto: bool,
950 pub unsafety: hir::Unsafety,
951 pub items: Vec<Item>,
952 pub generics: Generics,
953 pub bounds: Vec<GenericBound>,
60c5eb7d
XL
954 pub is_auto: bool,
955}
956
957#[derive(Clone, Debug)]
958pub struct TraitAlias {
959 pub generics: Generics,
960 pub bounds: Vec<GenericBound>,
961}
962
963/// A trait reference, which may have higher ranked lifetimes.
964#[derive(Clone, PartialEq, Eq, Debug, Hash)]
965pub struct PolyTrait {
966 pub trait_: Type,
967 pub generic_params: Vec<GenericParamDef>,
968}
969
970/// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
971/// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
972/// importantly, it does not preserve mutability or boxes.
973#[derive(Clone, PartialEq, Eq, Debug, Hash)]
974pub enum Type {
975 /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
976 ResolvedPath {
977 path: Path,
978 param_names: Option<Vec<GenericBound>>,
979 did: DefId,
980 /// `true` if is a `T::Name` path for associated types.
981 is_generic: bool,
982 },
983 /// For parameterized types, so the consumer of the JSON don't go
984 /// looking for types which don't exist anywhere.
985 Generic(String),
986 /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
987 /// arrays, slices, and tuples.
988 Primitive(PrimitiveType),
989 /// `extern "ABI" fn`
990 BareFunction(Box<BareFunctionDecl>),
991 Tuple(Vec<Type>),
992 Slice(Box<Type>),
993 Array(Box<Type>, String),
994 Never,
995 RawPointer(Mutability, Box<Type>),
996 BorrowedRef {
997 lifetime: Option<Lifetime>,
998 mutability: Mutability,
999 type_: Box<Type>,
1000 },
1001
1002 // `<Type as Trait>::Name`
1003 QPath {
1004 name: String,
1005 self_type: Box<Type>,
dfeec247 1006 trait_: Box<Type>,
60c5eb7d
XL
1007 },
1008
1009 // `_`
1010 Infer,
1011
1012 // `impl TraitA + TraitB + ...`
1013 ImplTrait(Vec<GenericBound>),
1014}
1015
1016#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1017pub enum PrimitiveType {
dfeec247
XL
1018 Isize,
1019 I8,
1020 I16,
1021 I32,
1022 I64,
1023 I128,
1024 Usize,
1025 U8,
1026 U16,
1027 U32,
1028 U64,
1029 U128,
1030 F32,
1031 F64,
60c5eb7d
XL
1032 Char,
1033 Bool,
1034 Str,
1035 Slice,
1036 Array,
1037 Tuple,
1038 Unit,
1039 RawPointer,
1040 Reference,
1041 Fn,
1042 Never,
1043}
1044
ba9703b0 1045#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
60c5eb7d
XL
1046pub enum TypeKind {
1047 Enum,
1048 Function,
1049 Module,
1050 Const,
1051 Static,
1052 Struct,
1053 Union,
1054 Trait,
1055 Typedef,
1056 Foreign,
1057 Macro,
1058 Attr,
1059 Derive,
1060 TraitAlias,
1061}
1062
1063pub trait GetDefId {
1064 fn def_id(&self) -> Option<DefId>;
1065}
1066
1067impl<T: GetDefId> GetDefId for Option<T> {
1068 fn def_id(&self) -> Option<DefId> {
1069 self.as_ref().and_then(|d| d.def_id())
1070 }
1071}
1072
1073impl Type {
1074 pub fn primitive_type(&self) -> Option<PrimitiveType> {
1075 match *self {
dfeec247 1076 Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
60c5eb7d
XL
1077 Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1078 Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
dfeec247
XL
1079 Tuple(ref tys) => {
1080 if tys.is_empty() {
1081 Some(PrimitiveType::Unit)
1082 } else {
1083 Some(PrimitiveType::Tuple)
1084 }
1085 }
60c5eb7d
XL
1086 RawPointer(..) => Some(PrimitiveType::RawPointer),
1087 BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
1088 BareFunction(..) => Some(PrimitiveType::Fn),
1089 Never => Some(PrimitiveType::Never),
1090 _ => None,
1091 }
1092 }
1093
1094 pub fn is_generic(&self) -> bool {
1095 match *self {
1096 ResolvedPath { is_generic, .. } => is_generic,
1097 _ => false,
1098 }
1099 }
1100
1101 pub fn is_self_type(&self) -> bool {
1102 match *self {
1103 Generic(ref name) => name == "Self",
dfeec247 1104 _ => false,
60c5eb7d
XL
1105 }
1106 }
1107
1108 pub fn generics(&self) -> Option<Vec<Type>> {
1109 match *self {
dfeec247
XL
1110 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1111 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
1112 Some(
1113 args.iter()
1114 .filter_map(|arg| match arg {
1115 GenericArg::Type(ty) => Some(ty.clone()),
1116 _ => None,
1117 })
1118 .collect(),
1119 )
1120 } else {
1121 None
1122 }
1123 }),
60c5eb7d
XL
1124 _ => None,
1125 }
1126 }
1127
1128 pub fn bindings(&self) -> Option<&[TypeBinding]> {
1129 match *self {
dfeec247
XL
1130 ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1131 if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
1132 Some(&**bindings)
1133 } else {
1134 None
1135 }
1136 }),
1137 _ => None,
60c5eb7d
XL
1138 }
1139 }
1140
1141 pub fn is_full_generic(&self) -> bool {
1142 match *self {
1143 Type::Generic(_) => true,
1144 _ => false,
1145 }
1146 }
1147
1148 pub fn projection(&self) -> Option<(&Type, DefId, &str)> {
1149 let (self_, trait_, name) = match self {
dfeec247 1150 QPath { ref self_type, ref trait_, ref name } => (self_type, trait_, name),
60c5eb7d
XL
1151 _ => return None,
1152 };
1153 let trait_did = match **trait_ {
1154 ResolvedPath { did, .. } => did,
1155 _ => return None,
1156 };
1157 Some((&self_, trait_did, name))
1158 }
60c5eb7d
XL
1159}
1160
1161impl GetDefId for Type {
1162 fn def_id(&self) -> Option<DefId> {
1163 match *self {
1164 ResolvedPath { did, .. } => Some(did),
1165 Primitive(p) => crate::html::render::cache().primitive_locations.get(&p).cloned(),
dfeec247
XL
1166 BorrowedRef { type_: box Generic(..), .. } => {
1167 Primitive(PrimitiveType::Reference).def_id()
1168 }
60c5eb7d 1169 BorrowedRef { ref type_, .. } => type_.def_id(),
dfeec247
XL
1170 Tuple(ref tys) => {
1171 if tys.is_empty() {
1172 Primitive(PrimitiveType::Unit).def_id()
1173 } else {
1174 Primitive(PrimitiveType::Tuple).def_id()
1175 }
1176 }
60c5eb7d
XL
1177 BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
1178 Never => Primitive(PrimitiveType::Never).def_id(),
1179 Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
1180 Array(..) => Primitive(PrimitiveType::Array).def_id(),
1181 RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(),
1182 QPath { ref self_type, .. } => self_type.def_id(),
1183 _ => None,
1184 }
1185 }
1186}
1187
1188impl PrimitiveType {
1189 pub fn from_str(s: &str) -> Option<PrimitiveType> {
1190 match s {
1191 "isize" => Some(PrimitiveType::Isize),
1192 "i8" => Some(PrimitiveType::I8),
1193 "i16" => Some(PrimitiveType::I16),
1194 "i32" => Some(PrimitiveType::I32),
1195 "i64" => Some(PrimitiveType::I64),
1196 "i128" => Some(PrimitiveType::I128),
1197 "usize" => Some(PrimitiveType::Usize),
1198 "u8" => Some(PrimitiveType::U8),
1199 "u16" => Some(PrimitiveType::U16),
1200 "u32" => Some(PrimitiveType::U32),
1201 "u64" => Some(PrimitiveType::U64),
1202 "u128" => Some(PrimitiveType::U128),
1203 "bool" => Some(PrimitiveType::Bool),
1204 "char" => Some(PrimitiveType::Char),
1205 "str" => Some(PrimitiveType::Str),
1206 "f32" => Some(PrimitiveType::F32),
1207 "f64" => Some(PrimitiveType::F64),
1208 "array" => Some(PrimitiveType::Array),
1209 "slice" => Some(PrimitiveType::Slice),
1210 "tuple" => Some(PrimitiveType::Tuple),
1211 "unit" => Some(PrimitiveType::Unit),
1212 "pointer" => Some(PrimitiveType::RawPointer),
1213 "reference" => Some(PrimitiveType::Reference),
1214 "fn" => Some(PrimitiveType::Fn),
1215 "never" => Some(PrimitiveType::Never),
1216 _ => None,
1217 }
1218 }
1219
1220 pub fn as_str(&self) -> &'static str {
1221 use self::PrimitiveType::*;
1222 match *self {
1223 Isize => "isize",
1224 I8 => "i8",
1225 I16 => "i16",
1226 I32 => "i32",
1227 I64 => "i64",
1228 I128 => "i128",
1229 Usize => "usize",
1230 U8 => "u8",
1231 U16 => "u16",
1232 U32 => "u32",
1233 U64 => "u64",
1234 U128 => "u128",
1235 F32 => "f32",
1236 F64 => "f64",
1237 Str => "str",
1238 Bool => "bool",
1239 Char => "char",
1240 Array => "array",
1241 Slice => "slice",
1242 Tuple => "tuple",
1243 Unit => "unit",
1244 RawPointer => "pointer",
1245 Reference => "reference",
1246 Fn => "fn",
1247 Never => "never",
1248 }
1249 }
1250
1251 pub fn to_url_str(&self) -> &'static str {
1252 self.as_str()
1253 }
1254}
1255
1256impl From<ast::IntTy> for PrimitiveType {
1257 fn from(int_ty: ast::IntTy) -> PrimitiveType {
1258 match int_ty {
1259 ast::IntTy::Isize => PrimitiveType::Isize,
1260 ast::IntTy::I8 => PrimitiveType::I8,
1261 ast::IntTy::I16 => PrimitiveType::I16,
1262 ast::IntTy::I32 => PrimitiveType::I32,
1263 ast::IntTy::I64 => PrimitiveType::I64,
1264 ast::IntTy::I128 => PrimitiveType::I128,
1265 }
1266 }
1267}
1268
1269impl From<ast::UintTy> for PrimitiveType {
1270 fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1271 match uint_ty {
1272 ast::UintTy::Usize => PrimitiveType::Usize,
1273 ast::UintTy::U8 => PrimitiveType::U8,
1274 ast::UintTy::U16 => PrimitiveType::U16,
1275 ast::UintTy::U32 => PrimitiveType::U32,
1276 ast::UintTy::U64 => PrimitiveType::U64,
1277 ast::UintTy::U128 => PrimitiveType::U128,
1278 }
1279 }
1280}
1281
1282impl From<ast::FloatTy> for PrimitiveType {
1283 fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1284 match float_ty {
1285 ast::FloatTy::F32 => PrimitiveType::F32,
1286 ast::FloatTy::F64 => PrimitiveType::F64,
1287 }
1288 }
1289}
1290
74b04a01
XL
1291impl From<hir::PrimTy> for PrimitiveType {
1292 fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1293 match prim_ty {
1294 hir::PrimTy::Int(int_ty) => int_ty.into(),
1295 hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1296 hir::PrimTy::Float(float_ty) => float_ty.into(),
1297 hir::PrimTy::Str => PrimitiveType::Str,
1298 hir::PrimTy::Bool => PrimitiveType::Bool,
1299 hir::PrimTy::Char => PrimitiveType::Char,
1300 }
1301 }
1302}
1303
60c5eb7d
XL
1304#[derive(Clone, PartialEq, Eq, Debug)]
1305pub enum Visibility {
1306 Public,
1307 Inherited,
1308 Crate,
1309 Restricted(DefId, Path),
1310}
1311
1312#[derive(Clone, Debug)]
1313pub struct Struct {
1314 pub struct_type: doctree::StructType,
1315 pub generics: Generics,
1316 pub fields: Vec<Item>,
1317 pub fields_stripped: bool,
1318}
1319
1320#[derive(Clone, Debug)]
1321pub struct Union {
1322 pub struct_type: doctree::StructType,
1323 pub generics: Generics,
1324 pub fields: Vec<Item>,
1325 pub fields_stripped: bool,
1326}
1327
1328/// This is a more limited form of the standard Struct, different in that
1329/// it lacks the things most items have (name, id, parameterization). Found
1330/// only as a variant in an enum.
1331#[derive(Clone, Debug)]
1332pub struct VariantStruct {
1333 pub struct_type: doctree::StructType,
1334 pub fields: Vec<Item>,
1335 pub fields_stripped: bool,
1336}
1337
1338#[derive(Clone, Debug)]
1339pub struct Enum {
1340 pub variants: IndexVec<VariantIdx, Item>,
1341 pub generics: Generics,
1342 pub variants_stripped: bool,
1343}
1344
1345#[derive(Clone, Debug)]
1346pub struct Variant {
1347 pub kind: VariantKind,
1348}
1349
1350#[derive(Clone, Debug)]
1351pub enum VariantKind {
1352 CLike,
1353 Tuple(Vec<Type>),
1354 Struct(VariantStruct),
1355}
1356
1357#[derive(Clone, Debug)]
1358pub struct Span {
1359 pub filename: FileName,
ba9703b0 1360 pub cnum: CrateNum,
60c5eb7d
XL
1361 pub loline: usize,
1362 pub locol: usize,
1363 pub hiline: usize,
1364 pub hicol: usize,
dfeec247 1365 pub original: rustc_span::Span,
60c5eb7d
XL
1366}
1367
1368impl Span {
1369 pub fn empty() -> Span {
1370 Span {
1371 filename: FileName::Anon(0),
ba9703b0 1372 cnum: LOCAL_CRATE,
dfeec247
XL
1373 loline: 0,
1374 locol: 0,
1375 hiline: 0,
1376 hicol: 0,
1377 original: rustc_span::DUMMY_SP,
60c5eb7d
XL
1378 }
1379 }
1380
dfeec247 1381 pub fn span(&self) -> rustc_span::Span {
60c5eb7d
XL
1382 self.original
1383 }
1384}
1385
1386#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1387pub struct Path {
1388 pub global: bool,
1389 pub res: Res,
1390 pub segments: Vec<PathSegment>,
1391}
1392
1393impl Path {
1394 pub fn last_name(&self) -> &str {
1395 self.segments.last().expect("segments were empty").name.as_str()
1396 }
1397}
1398
1399#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1400pub enum GenericArg {
1401 Lifetime(Lifetime),
1402 Type(Type),
1403 Const(Constant),
1404}
1405
1406#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1407pub enum GenericArgs {
dfeec247
XL
1408 AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
1409 Parenthesized { inputs: Vec<Type>, output: Option<Type> },
60c5eb7d
XL
1410}
1411
1412#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1413pub struct PathSegment {
1414 pub name: String,
1415 pub args: GenericArgs,
1416}
1417
1418#[derive(Clone, Debug)]
1419pub struct Typedef {
1420 pub type_: Type,
1421 pub generics: Generics,
dfeec247
XL
1422 // Type of target item.
1423 pub item_type: Option<Type>,
1424}
1425
1426impl GetDefId for Typedef {
1427 fn def_id(&self) -> Option<DefId> {
1428 self.type_.def_id()
1429 }
60c5eb7d
XL
1430}
1431
1432#[derive(Clone, Debug)]
1433pub struct OpaqueTy {
1434 pub bounds: Vec<GenericBound>,
1435 pub generics: Generics,
1436}
1437
1438#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1439pub struct BareFunctionDecl {
1440 pub unsafety: hir::Unsafety,
1441 pub generic_params: Vec<GenericParamDef>,
1442 pub decl: FnDecl,
1443 pub abi: Abi,
1444}
1445
1446#[derive(Clone, Debug)]
1447pub struct Static {
1448 pub type_: Type,
1449 pub mutability: Mutability,
1450 /// It's useful to have the value of a static documented, but I have no
1451 /// desire to represent expressions (that'd basically be all of the AST,
1452 /// which is huge!). So, have a string.
1453 pub expr: String,
1454}
1455
1456#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1457pub struct Constant {
1458 pub type_: Type,
1459 pub expr: String,
dfeec247
XL
1460 pub value: Option<String>,
1461 pub is_literal: bool,
60c5eb7d
XL
1462}
1463
1464#[derive(Clone, PartialEq, Debug)]
1465pub enum ImplPolarity {
1466 Positive,
1467 Negative,
1468}
1469
1470#[derive(Clone, Debug)]
1471pub struct Impl {
1472 pub unsafety: hir::Unsafety,
1473 pub generics: Generics,
1474 pub provided_trait_methods: FxHashSet<String>,
1475 pub trait_: Option<Type>,
1476 pub for_: Type,
1477 pub items: Vec<Item>,
1478 pub polarity: Option<ImplPolarity>,
1479 pub synthetic: bool,
1480 pub blanket_impl: Option<Type>,
1481}
1482
1483#[derive(Clone, Debug)]
1484pub enum Import {
1485 // use source as str;
1486 Simple(String, ImportSource),
1487 // use source::*;
dfeec247 1488 Glob(ImportSource),
60c5eb7d
XL
1489}
1490
1491#[derive(Clone, Debug)]
1492pub struct ImportSource {
1493 pub path: Path,
1494 pub did: Option<DefId>,
1495}
1496
1497#[derive(Clone, Debug)]
1498pub struct Macro {
1499 pub source: String,
1500 pub imported_from: Option<String>,
1501}
1502
1503#[derive(Clone, Debug)]
1504pub struct ProcMacro {
1505 pub kind: MacroKind,
1506 pub helpers: Vec<String>,
1507}
1508
1509#[derive(Clone, Debug)]
1510pub struct Stability {
1511 pub level: stability::StabilityLevel,
1512 pub feature: Option<String>,
1513 pub since: String,
1514 pub deprecation: Option<Deprecation>,
1515 pub unstable_reason: Option<String>,
1516 pub issue: Option<NonZeroU32>,
1517}
1518
1519#[derive(Clone, Debug)]
1520pub struct Deprecation {
1521 pub since: Option<String>,
1522 pub note: Option<String>,
1523}
1524
1525/// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
1526/// `A: Send + Sync` in `Foo<A: Send + Sync>`).
1527#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1528pub struct TypeBinding {
1529 pub name: String,
1530 pub kind: TypeBindingKind,
1531}
1532
1533#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1534pub enum TypeBindingKind {
dfeec247
XL
1535 Equality { ty: Type },
1536 Constraint { bounds: Vec<GenericBound> },
60c5eb7d
XL
1537}
1538
1539impl TypeBinding {
1540 pub fn ty(&self) -> &Type {
1541 match self.kind {
1542 TypeBindingKind::Equality { ref ty } => ty,
1543 _ => panic!("expected equality type binding for parenthesized generic args"),
1544 }
1545 }
1546}