1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825
use crate::definitions::DefPathData;
use crate::hir;
use rustc_ast as ast;
use rustc_ast::NodeId;
use rustc_data_structures::stable_hasher::ToStableHashKey;
use rustc_data_structures::unord::UnordMap;
use rustc_macros::HashStable_Generic;
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::kw;
use rustc_span::Symbol;
use std::array::IntoIter;
use std::fmt::Debug;
/// Encodes if a `DefKind::Ctor` is the constructor of an enum variant or a struct.
#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)]
pub enum CtorOf {
/// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit struct.
Struct,
/// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit variant.
Variant,
}
/// What kind of constructor something is.
#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)]
pub enum CtorKind {
/// Constructor function automatically created by a tuple struct/variant.
Fn,
/// Constructor constant automatically created by a unit struct/variant.
Const,
}
/// An attribute that is not a macro; e.g., `#[inline]` or `#[rustfmt::skip]`.
#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)]
pub enum NonMacroAttrKind {
/// Single-segment attribute defined by the language (`#[inline]`)
Builtin(Symbol),
/// Multi-segment custom attribute living in a "tool module" (`#[rustfmt::skip]`).
Tool,
/// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`).
DeriveHelper,
/// Single-segment custom attribute registered by a derive macro
/// but used before that derive macro was expanded (deprecated).
DeriveHelperCompat,
}
/// What kind of definition something is; e.g., `mod` vs `struct`.
/// `enum DefPathData` may need to be updated if a new variant is added here.
#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)]
pub enum DefKind {
// Type namespace
Mod,
/// Refers to the struct itself, [`DefKind::Ctor`] refers to its constructor if it exists.
Struct,
Union,
Enum,
/// Refers to the variant itself, [`DefKind::Ctor`] refers to its constructor if it exists.
Variant,
Trait,
/// Type alias: `type Foo = Bar;`
TyAlias,
/// Type from an `extern` block.
ForeignTy,
/// Trait alias: `trait IntIterator = Iterator<Item = i32>;`
TraitAlias,
/// Associated type: `trait MyTrait { type Assoc; }`
AssocTy,
/// Type parameter: the `T` in `struct Vec<T> { ... }`
TyParam,
// Value namespace
Fn,
Const,
/// Constant generic parameter: `struct Foo<const N: usize> { ... }`
ConstParam,
Static {
/// Whether it's a `static mut` or just a `static`.
mutability: ast::Mutability,
/// Whether it's an anonymous static generated for nested allocations.
nested: bool,
},
/// Refers to the struct or enum variant's constructor.
///
/// The reason `Ctor` exists in addition to [`DefKind::Struct`] and
/// [`DefKind::Variant`] is because structs and enum variants exist
/// in the *type* namespace, whereas struct and enum variant *constructors*
/// exist in the *value* namespace.
///
/// You may wonder why enum variants exist in the type namespace as opposed
/// to the value namespace. Check out [RFC 2593] for intuition on why that is.
///
/// [RFC 2593]: https://github.com/rust-lang/rfcs/pull/2593
Ctor(CtorOf, CtorKind),
/// Associated function: `impl MyStruct { fn associated() {} }`
/// or `trait Foo { fn associated() {} }`
AssocFn,
/// Associated constant: `trait MyTrait { const ASSOC: usize; }`
AssocConst,
// Macro namespace
Macro(MacroKind),
// Not namespaced (or they are, but we don't treat them so)
ExternCrate,
Use,
/// An `extern` block.
ForeignMod,
/// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]`
AnonConst,
/// An inline constant, e.g. `const { 1 + 2 }`
InlineConst,
/// Opaque type, aka `impl Trait`.
OpaqueTy,
Field,
/// Lifetime parameter: the `'a` in `struct Foo<'a> { ... }`
LifetimeParam,
/// A use of `global_asm!`.
GlobalAsm,
Impl {
of_trait: bool,
},
/// A closure, coroutine, or coroutine-closure.
///
/// These are all represented with the same `ExprKind::Closure` in the AST and HIR,
/// which makes it difficult to distinguish these during def collection. Therefore,
/// we treat them all the same, and code which needs to distinguish them can match
/// or `hir::ClosureKind` or `type_of`.
Closure,
}
impl DefKind {
/// Get an English description for the item's kind.
///
/// If you have access to `TyCtxt`, use `TyCtxt::def_descr` or
/// `TyCtxt::def_kind_descr` instead, because they give better
/// information for coroutines and associated functions.
pub fn descr(self, def_id: DefId) -> &'static str {
match self {
DefKind::Fn => "function",
DefKind::Mod if def_id.is_crate_root() && !def_id.is_local() => "crate",
DefKind::Mod => "module",
DefKind::Static { .. } => "static",
DefKind::Enum => "enum",
DefKind::Variant => "variant",
DefKind::Ctor(CtorOf::Variant, CtorKind::Fn) => "tuple variant",
DefKind::Ctor(CtorOf::Variant, CtorKind::Const) => "unit variant",
DefKind::Struct => "struct",
DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct",
DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct",
DefKind::OpaqueTy => "opaque type",
DefKind::TyAlias => "type alias",
DefKind::TraitAlias => "trait alias",
DefKind::AssocTy => "associated type",
DefKind::Union => "union",
DefKind::Trait => "trait",
DefKind::ForeignTy => "foreign type",
DefKind::AssocFn => "associated function",
DefKind::Const => "constant",
DefKind::AssocConst => "associated constant",
DefKind::TyParam => "type parameter",
DefKind::ConstParam => "const parameter",
DefKind::Macro(macro_kind) => macro_kind.descr(),
DefKind::LifetimeParam => "lifetime parameter",
DefKind::Use => "import",
DefKind::ForeignMod => "foreign module",
DefKind::AnonConst => "constant expression",
DefKind::InlineConst => "inline constant",
DefKind::Field => "field",
DefKind::Impl { .. } => "implementation",
DefKind::Closure => "closure",
DefKind::ExternCrate => "extern crate",
DefKind::GlobalAsm => "global assembly block",
}
}
/// Gets an English article for the definition.
///
/// If you have access to `TyCtxt`, use `TyCtxt::def_descr_article` or
/// `TyCtxt::def_kind_descr_article` instead, because they give better
/// information for coroutines and associated functions.
pub fn article(&self) -> &'static str {
match *self {
DefKind::AssocTy
| DefKind::AssocConst
| DefKind::AssocFn
| DefKind::Enum
| DefKind::OpaqueTy
| DefKind::Impl { .. }
| DefKind::Use
| DefKind::InlineConst
| DefKind::ExternCrate => "an",
DefKind::Macro(macro_kind) => macro_kind.article(),
_ => "a",
}
}
pub fn ns(&self) -> Option<Namespace> {
match self {
DefKind::Mod
| DefKind::Struct
| DefKind::Union
| DefKind::Enum
| DefKind::Variant
| DefKind::Trait
| DefKind::OpaqueTy
| DefKind::TyAlias
| DefKind::ForeignTy
| DefKind::TraitAlias
| DefKind::AssocTy
| DefKind::TyParam => Some(Namespace::TypeNS),
DefKind::Fn
| DefKind::Const
| DefKind::ConstParam
| DefKind::Static { .. }
| DefKind::Ctor(..)
| DefKind::AssocFn
| DefKind::AssocConst => Some(Namespace::ValueNS),
DefKind::Macro(..) => Some(Namespace::MacroNS),
// Not namespaced.
DefKind::AnonConst
| DefKind::InlineConst
| DefKind::Field
| DefKind::LifetimeParam
| DefKind::ExternCrate
| DefKind::Closure
| DefKind::Use
| DefKind::ForeignMod
| DefKind::GlobalAsm
| DefKind::Impl { .. } => None,
}
}
pub fn def_path_data(self, name: Symbol) -> DefPathData {
match self {
DefKind::Struct | DefKind::Union if name == kw::Empty => DefPathData::AnonAdt,
DefKind::Mod
| DefKind::Struct
| DefKind::Union
| DefKind::Enum
| DefKind::Variant
| DefKind::Trait
| DefKind::TyAlias
| DefKind::ForeignTy
| DefKind::TraitAlias
| DefKind::AssocTy
| DefKind::TyParam
| DefKind::ExternCrate => DefPathData::TypeNs(name),
// It's not exactly an anon const, but wrt DefPathData, there
// is no difference.
DefKind::Static { nested: true, .. } => DefPathData::AnonConst,
DefKind::Fn
| DefKind::Const
| DefKind::ConstParam
| DefKind::Static { .. }
| DefKind::AssocFn
| DefKind::AssocConst
| DefKind::Field => DefPathData::ValueNs(name),
DefKind::Macro(..) => DefPathData::MacroNs(name),
DefKind::LifetimeParam => DefPathData::LifetimeNs(name),
DefKind::Ctor(..) => DefPathData::Ctor,
DefKind::Use => DefPathData::Use,
DefKind::ForeignMod => DefPathData::ForeignMod,
DefKind::AnonConst => DefPathData::AnonConst,
DefKind::InlineConst => DefPathData::AnonConst,
DefKind::OpaqueTy => DefPathData::OpaqueTy,
DefKind::GlobalAsm => DefPathData::GlobalAsm,
DefKind::Impl { .. } => DefPathData::Impl,
DefKind::Closure => DefPathData::Closure,
}
}
#[inline]
pub fn is_fn_like(self) -> bool {
matches!(self, DefKind::Fn | DefKind::AssocFn | DefKind::Closure)
}
/// Whether `query get_codegen_attrs` should be used with this definition.
pub fn has_codegen_attrs(self) -> bool {
match self {
DefKind::Fn
| DefKind::AssocFn
| DefKind::Ctor(..)
| DefKind::Closure
| DefKind::Static { .. } => true,
DefKind::Mod
| DefKind::Struct
| DefKind::Union
| DefKind::Enum
| DefKind::Variant
| DefKind::Trait
| DefKind::TyAlias
| DefKind::ForeignTy
| DefKind::TraitAlias
| DefKind::AssocTy
| DefKind::Const
| DefKind::AssocConst
| DefKind::Macro(..)
| DefKind::Use
| DefKind::ForeignMod
| DefKind::OpaqueTy
| DefKind::Impl { .. }
| DefKind::Field
| DefKind::TyParam
| DefKind::ConstParam
| DefKind::LifetimeParam
| DefKind::AnonConst
| DefKind::InlineConst
| DefKind::GlobalAsm
| DefKind::ExternCrate => false,
}
}
}
/// The resolution of a path or export.
///
/// For every path or identifier in Rust, the compiler must determine
/// what the path refers to. This process is called name resolution,
/// and `Res` is the primary result of name resolution.
///
/// For example, everything prefixed with `/* Res */` in this example has
/// an associated `Res`:
///
/// ```
/// fn str_to_string(s: & /* Res */ str) -> /* Res */ String {
/// /* Res */ String::from(/* Res */ s)
/// }
///
/// /* Res */ str_to_string("hello");
/// ```
///
/// The associated `Res`s will be:
///
/// - `str` will resolve to [`Res::PrimTy`];
/// - `String` will resolve to [`Res::Def`], and the `Res` will include the [`DefId`]
/// for `String` as defined in the standard library;
/// - `String::from` will also resolve to [`Res::Def`], with the [`DefId`]
/// pointing to `String::from`;
/// - `s` will resolve to [`Res::Local`];
/// - the call to `str_to_string` will resolve to [`Res::Def`], with the [`DefId`]
/// pointing to the definition of `str_to_string` in the current crate.
//
#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)]
pub enum Res<Id = hir::HirId> {
/// Definition having a unique ID (`DefId`), corresponds to something defined in user code.
///
/// **Not bound to a specific namespace.**
Def(DefKind, DefId),
// Type namespace
/// A primitive type such as `i32` or `str`.
///
/// **Belongs to the type namespace.**
PrimTy(hir::PrimTy),
/// The `Self` type, as used within a trait.
///
/// **Belongs to the type namespace.**
///
/// See the examples on [`Res::SelfTyAlias`] for details.
SelfTyParam {
/// The trait this `Self` is a generic parameter for.
trait_: DefId,
},
/// The `Self` type, as used somewhere other than within a trait.
///
/// **Belongs to the type namespace.**
///
/// Examples:
/// ```
/// struct Bar(Box<Self>); // SelfTyAlias
///
/// trait Foo {
/// fn foo() -> Box<Self>; // SelfTyParam
/// }
///
/// impl Bar {
/// fn blah() {
/// let _: Self; // SelfTyAlias
/// }
/// }
///
/// impl Foo for Bar {
/// fn foo() -> Box<Self> { // SelfTyAlias
/// let _: Self; // SelfTyAlias
///
/// todo!()
/// }
/// }
/// ```
/// *See also [`Res::SelfCtor`].*
///
SelfTyAlias {
/// The item introducing the `Self` type alias. Can be used in the `type_of` query
/// to get the underlying type.
alias_to: DefId,
/// Whether the `Self` type is disallowed from mentioning generics (i.e. when used in an
/// anonymous constant).
///
/// HACK(min_const_generics): self types also have an optional requirement to **not**
/// mention any generic parameters to allow the following with `min_const_generics`:
/// ```
/// # struct Foo;
/// impl Foo { fn test() -> [u8; std::mem::size_of::<Self>()] { todo!() } }
///
/// struct Bar([u8; baz::<Self>()]);
/// const fn baz<T>() -> usize { 10 }
/// ```
/// We do however allow `Self` in repeat expression even if it is generic to not break code
/// which already works on stable while causing the `const_evaluatable_unchecked` future
/// compat lint:
/// ```
/// fn foo<T>() {
/// let _bar = [1_u8; std::mem::size_of::<*mut T>()];
/// }
/// ```
// FIXME(generic_const_exprs): Remove this bodge once that feature is stable.
forbid_generic: bool,
/// Is this within an `impl Foo for bar`?
is_trait_impl: bool,
},
// Value namespace
/// The `Self` constructor, along with the [`DefId`]
/// of the impl it is associated with.
///
/// **Belongs to the value namespace.**
///
/// *See also [`Res::SelfTyParam`] and [`Res::SelfTyAlias`].*
SelfCtor(DefId),
/// A local variable or function parameter.
///
/// **Belongs to the value namespace.**
Local(Id),
/// A tool attribute module; e.g., the `rustfmt` in `#[rustfmt::skip]`.
///
/// **Belongs to the type namespace.**
ToolMod,
// Macro namespace
/// An attribute that is *not* implemented via macro.
/// E.g., `#[inline]` and `#[rustfmt::skip]`, which are essentially directives,
/// as opposed to `#[test]`, which is a builtin macro.
///
/// **Belongs to the macro namespace.**
NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]`
// All namespaces
/// Name resolution failed. We use a dummy `Res` variant so later phases
/// of the compiler won't crash and can instead report more errors.
///
/// **Not bound to a specific namespace.**
Err,
}
/// The result of resolving a path before lowering to HIR,
/// with "module" segments resolved and associated item
/// segments deferred to type checking.
/// `base_res` is the resolution of the resolved part of the
/// path, `unresolved_segments` is the number of unresolved
/// segments.
///
/// ```text
/// module::Type::AssocX::AssocY::MethodOrAssocType
/// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// base_res unresolved_segments = 3
///
/// <T as Trait>::AssocX::AssocY::MethodOrAssocType
/// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~
/// base_res unresolved_segments = 2
/// ```
#[derive(Copy, Clone, Debug)]
pub struct PartialRes {
base_res: Res<NodeId>,
unresolved_segments: usize,
}
impl PartialRes {
#[inline]
pub fn new(base_res: Res<NodeId>) -> Self {
PartialRes { base_res, unresolved_segments: 0 }
}
#[inline]
pub fn with_unresolved_segments(base_res: Res<NodeId>, mut unresolved_segments: usize) -> Self {
if base_res == Res::Err {
unresolved_segments = 0
}
PartialRes { base_res, unresolved_segments }
}
#[inline]
pub fn base_res(&self) -> Res<NodeId> {
self.base_res
}
#[inline]
pub fn unresolved_segments(&self) -> usize {
self.unresolved_segments
}
#[inline]
pub fn full_res(&self) -> Option<Res<NodeId>> {
(self.unresolved_segments == 0).then_some(self.base_res)
}
#[inline]
pub fn expect_full_res(&self) -> Res<NodeId> {
self.full_res().expect("unexpected unresolved segments")
}
}
/// Different kinds of symbols can coexist even if they share the same textual name.
/// Therefore, they each have a separate universe (known as a "namespace").
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]
#[derive(HashStable_Generic)]
pub enum Namespace {
/// The type namespace includes `struct`s, `enum`s, `union`s, `trait`s, and `mod`s
/// (and, by extension, crates).
///
/// Note that the type namespace includes other items; this is not an
/// exhaustive list.
TypeNS,
/// The value namespace includes `fn`s, `const`s, `static`s, and local variables (including function arguments).
ValueNS,
/// The macro namespace includes `macro_rules!` macros, declarative `macro`s,
/// procedural macros, attribute macros, `derive` macros, and non-macro attributes
/// like `#[inline]` and `#[rustfmt::skip]`.
MacroNS,
}
impl Namespace {
/// The English description of the namespace.
pub fn descr(self) -> &'static str {
match self {
Self::TypeNS => "type",
Self::ValueNS => "value",
Self::MacroNS => "macro",
}
}
}
impl<CTX: crate::HashStableContext> ToStableHashKey<CTX> for Namespace {
type KeyType = Namespace;
#[inline]
fn to_stable_hash_key(&self, _: &CTX) -> Namespace {
*self
}
}
/// Just a helper ‒ separate structure for each namespace.
#[derive(Copy, Clone, Default, Debug)]
pub struct PerNS<T> {
pub value_ns: T,
pub type_ns: T,
pub macro_ns: T,
}
impl<T> PerNS<T> {
pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> PerNS<U> {
PerNS { value_ns: f(self.value_ns), type_ns: f(self.type_ns), macro_ns: f(self.macro_ns) }
}
pub fn into_iter(self) -> IntoIter<T, 3> {
[self.value_ns, self.type_ns, self.macro_ns].into_iter()
}
pub fn iter(&self) -> IntoIter<&T, 3> {
[&self.value_ns, &self.type_ns, &self.macro_ns].into_iter()
}
}
impl<T> ::std::ops::Index<Namespace> for PerNS<T> {
type Output = T;
fn index(&self, ns: Namespace) -> &T {
match ns {
Namespace::ValueNS => &self.value_ns,
Namespace::TypeNS => &self.type_ns,
Namespace::MacroNS => &self.macro_ns,
}
}
}
impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> {
fn index_mut(&mut self, ns: Namespace) -> &mut T {
match ns {
Namespace::ValueNS => &mut self.value_ns,
Namespace::TypeNS => &mut self.type_ns,
Namespace::MacroNS => &mut self.macro_ns,
}
}
}
impl<T> PerNS<Option<T>> {
/// Returns `true` if all the items in this collection are `None`.
pub fn is_empty(&self) -> bool {
self.type_ns.is_none() && self.value_ns.is_none() && self.macro_ns.is_none()
}
/// Returns an iterator over the items which are `Some`.
pub fn present_items(self) -> impl Iterator<Item = T> {
[self.type_ns, self.value_ns, self.macro_ns].into_iter().flatten()
}
}
impl CtorKind {
pub fn from_ast(vdata: &ast::VariantData) -> Option<(CtorKind, NodeId)> {
match *vdata {
ast::VariantData::Tuple(_, node_id) => Some((CtorKind::Fn, node_id)),
ast::VariantData::Unit(node_id) => Some((CtorKind::Const, node_id)),
ast::VariantData::Struct { .. } => None,
}
}
}
impl NonMacroAttrKind {
pub fn descr(self) -> &'static str {
match self {
NonMacroAttrKind::Builtin(..) => "built-in attribute",
NonMacroAttrKind::Tool => "tool attribute",
NonMacroAttrKind::DeriveHelper | NonMacroAttrKind::DeriveHelperCompat => {
"derive helper attribute"
}
}
}
// Currently trivial, but exists in case a new kind is added in the future whose name starts
// with a vowel.
pub fn article(self) -> &'static str {
"a"
}
/// Users of some attributes cannot mark them as used, so they are considered always used.
pub fn is_used(self) -> bool {
match self {
NonMacroAttrKind::Tool
| NonMacroAttrKind::DeriveHelper
| NonMacroAttrKind::DeriveHelperCompat => true,
NonMacroAttrKind::Builtin(..) => false,
}
}
}
impl<Id> Res<Id> {
/// Return the `DefId` of this `Def` if it has an ID, else panic.
pub fn def_id(&self) -> DefId
where
Id: Debug,
{
self.opt_def_id().unwrap_or_else(|| panic!("attempted .def_id() on invalid res: {self:?}"))
}
/// Return `Some(..)` with the `DefId` of this `Res` if it has a ID, else `None`.
pub fn opt_def_id(&self) -> Option<DefId> {
match *self {
Res::Def(_, id) => Some(id),
Res::Local(..)
| Res::PrimTy(..)
| Res::SelfTyParam { .. }
| Res::SelfTyAlias { .. }
| Res::SelfCtor(..)
| Res::ToolMod
| Res::NonMacroAttr(..)
| Res::Err => None,
}
}
/// Return the `DefId` of this `Res` if it represents a module.
pub fn mod_def_id(&self) -> Option<DefId> {
match *self {
Res::Def(DefKind::Mod, id) => Some(id),
_ => None,
}
}
/// A human readable name for the res kind ("function", "module", etc.).
pub fn descr(&self) -> &'static str {
match *self {
Res::Def(kind, def_id) => kind.descr(def_id),
Res::SelfCtor(..) => "self constructor",
Res::PrimTy(..) => "builtin type",
Res::Local(..) => "local variable",
Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => "self type",
Res::ToolMod => "tool module",
Res::NonMacroAttr(attr_kind) => attr_kind.descr(),
Res::Err => "unresolved item",
}
}
/// Gets an English article for the `Res`.
pub fn article(&self) -> &'static str {
match *self {
Res::Def(kind, _) => kind.article(),
Res::NonMacroAttr(kind) => kind.article(),
Res::Err => "an",
_ => "a",
}
}
pub fn map_id<R>(self, mut map: impl FnMut(Id) -> R) -> Res<R> {
match self {
Res::Def(kind, id) => Res::Def(kind, id),
Res::SelfCtor(id) => Res::SelfCtor(id),
Res::PrimTy(id) => Res::PrimTy(id),
Res::Local(id) => Res::Local(map(id)),
Res::SelfTyParam { trait_ } => Res::SelfTyParam { trait_ },
Res::SelfTyAlias { alias_to, forbid_generic, is_trait_impl } => {
Res::SelfTyAlias { alias_to, forbid_generic, is_trait_impl }
}
Res::ToolMod => Res::ToolMod,
Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
Res::Err => Res::Err,
}
}
pub fn apply_id<R, E>(self, mut map: impl FnMut(Id) -> Result<R, E>) -> Result<Res<R>, E> {
Ok(match self {
Res::Def(kind, id) => Res::Def(kind, id),
Res::SelfCtor(id) => Res::SelfCtor(id),
Res::PrimTy(id) => Res::PrimTy(id),
Res::Local(id) => Res::Local(map(id)?),
Res::SelfTyParam { trait_ } => Res::SelfTyParam { trait_ },
Res::SelfTyAlias { alias_to, forbid_generic, is_trait_impl } => {
Res::SelfTyAlias { alias_to, forbid_generic, is_trait_impl }
}
Res::ToolMod => Res::ToolMod,
Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
Res::Err => Res::Err,
})
}
#[track_caller]
pub fn expect_non_local<OtherId>(self) -> Res<OtherId> {
self.map_id(
#[track_caller]
|_| panic!("unexpected `Res::Local`"),
)
}
pub fn macro_kind(self) -> Option<MacroKind> {
match self {
Res::Def(DefKind::Macro(kind), _) => Some(kind),
Res::NonMacroAttr(..) => Some(MacroKind::Attr),
_ => None,
}
}
/// Returns `None` if this is `Res::Err`
pub fn ns(&self) -> Option<Namespace> {
match self {
Res::Def(kind, ..) => kind.ns(),
Res::PrimTy(..) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::ToolMod => {
Some(Namespace::TypeNS)
}
Res::SelfCtor(..) | Res::Local(..) => Some(Namespace::ValueNS),
Res::NonMacroAttr(..) => Some(Namespace::MacroNS),
Res::Err => None,
}
}
/// Always returns `true` if `self` is `Res::Err`
pub fn matches_ns(&self, ns: Namespace) -> bool {
self.ns().map_or(true, |actual_ns| actual_ns == ns)
}
/// Returns whether such a resolved path can occur in a tuple struct/variant pattern
pub fn expected_in_tuple_struct_pat(&self) -> bool {
matches!(self, Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) | Res::SelfCtor(..))
}
/// Returns whether such a resolved path can occur in a unit struct/variant pattern
pub fn expected_in_unit_struct_pat(&self) -> bool {
matches!(self, Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::SelfCtor(..))
}
}
/// Resolution for a lifetime appearing in a type.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum LifetimeRes {
/// Successfully linked the lifetime to a generic parameter.
Param {
/// Id of the generic parameter that introduced it.
param: LocalDefId,
/// Id of the introducing place. That can be:
/// - an item's id, for the item's generic parameters;
/// - a TraitRef's ref_id, identifying the `for<...>` binder;
/// - a BareFn type's id.
///
/// This information is used for impl-trait lifetime captures, to know when to or not to
/// capture any given lifetime.
binder: NodeId,
},
/// Created a generic parameter for an anonymous lifetime.
Fresh {
/// Id of the generic parameter that introduced it.
///
/// Creating the associated `LocalDefId` is the responsibility of lowering.
param: NodeId,
/// Id of the introducing place. See `Param`.
binder: NodeId,
},
/// This variant is used for anonymous lifetimes that we did not resolve during
/// late resolution. Those lifetimes will be inferred by typechecking.
Infer,
/// Explicit `'static` lifetime.
Static,
/// Resolution failure.
Error,
/// HACK: This is used to recover the NodeId of an elided lifetime.
ElidedAnchor { start: NodeId, end: NodeId },
}
pub type DocLinkResMap = UnordMap<(Symbol, Namespace), Option<Res<NodeId>>>;