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