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