summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir/src/def.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_hir/src/def.rs')
-rw-r--r--compiler/rustc_hir/src/def.rs749
1 files changed, 749 insertions, 0 deletions
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
new file mode 100644
index 000000000..be5b7eccb
--- /dev/null
+++ b/compiler/rustc_hir/src/def.rs
@@ -0,0 +1,749 @@
+use crate::hir;
+
+use rustc_ast as ast;
+use rustc_ast::NodeId;
+use rustc_macros::HashStable_Generic;
+use rustc_span::def_id::{DefId, LocalDefId};
+use rustc_span::hygiene::MacroKind;
+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)]
+#[derive(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)]
+#[derive(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,
+ /// Unusable name in value namespace created by a struct variant.
+ Fictive,
+}
+
+/// An attribute that is not a macro; e.g., `#[inline]` or `#[rustfmt::skip]`.
+#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
+#[derive(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,
+ /// Single-segment custom attribute registered with `#[register_attr]`.
+ Registered,
+}
+
+/// What kind of definition something is; e.g., `mod` vs `struct`.
+#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
+#[derive(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(ast::Mutability),
+ /// 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,
+ Closure,
+ Generator,
+}
+
+impl DefKind {
+ 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::Ctor(CtorOf::Variant, CtorKind::Fictive) => "struct variant",
+ DefKind::Struct => "struct",
+ DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct",
+ DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct",
+ DefKind::Ctor(CtorOf::Struct, CtorKind::Fictive) => {
+ panic!("impossible struct constructor")
+ }
+ 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::Generator => "generator",
+ DefKind::ExternCrate => "extern crate",
+ DefKind::GlobalAsm => "global assembly block",
+ }
+ }
+
+ /// Gets an English article for the definition.
+ 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::Generator
+ | DefKind::Use
+ | DefKind::ForeignMod
+ | DefKind::GlobalAsm
+ | DefKind::Impl => None,
+ }
+ }
+
+ #[inline]
+ pub fn is_fn_like(self) -> bool {
+ match self {
+ DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Generator => true,
+ _ => false,
+ }
+ }
+
+ /// 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::Generator
+ | 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)]
+#[derive(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, optionally with the [`DefId`] of the trait it belongs to and
+ /// optionally with the [`DefId`] of the item introducing the `Self` type alias.
+ ///
+ /// **Belongs to the type namespace.**
+ ///
+ /// Examples:
+ /// ```
+ /// struct Bar(Box<Self>);
+ /// // `Res::SelfTy { trait_: None, alias_of: Some(Bar) }`
+ ///
+ /// trait Foo {
+ /// fn foo() -> Box<Self>;
+ /// // `Res::SelfTy { trait_: Some(Foo), alias_of: None }`
+ /// }
+ ///
+ /// impl Bar {
+ /// fn blah() {
+ /// let _: Self;
+ /// // `Res::SelfTy { trait_: None, alias_of: Some(::{impl#0}) }`
+ /// }
+ /// }
+ ///
+ /// impl Foo for Bar {
+ /// fn foo() -> Box<Self> {
+ /// // `Res::SelfTy { trait_: Some(Foo), alias_of: Some(::{impl#1}) }`
+ /// let _: Self;
+ /// // `Res::SelfTy { trait_: Some(Foo), alias_of: Some(::{impl#1}) }`
+ ///
+ /// todo!()
+ /// }
+ /// }
+ /// ```
+ ///
+ /// *See also [`Res::SelfCtor`].*
+ ///
+ /// -----
+ ///
+ /// 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.
+ SelfTy {
+ /// The trait this `Self` is a generic arg for.
+ trait_: Option<DefId>,
+ /// The item introducing the `Self` type alias. Can be used in the `type_of` query
+ /// to get the underlying type. Additionally whether the `Self` type is disallowed
+ /// from mentioning generics (i.e. when used in an anonymous constant).
+ alias_to: Option<(DefId, bool)>,
+ },
+ /// A tool attribute module; e.g., the `rustfmt` in `#[rustfmt::skip]`.
+ ///
+ /// **Belongs to the type namespace.**
+ ToolMod,
+
+ // Value namespace
+ /// The `Self` constructor, along with the [`DefId`]
+ /// of the impl it is associated with.
+ ///
+ /// **Belongs to the value namespace.**
+ ///
+ /// *See also [`Res::SelfTy`].*
+ SelfCtor(DefId),
+ /// A local variable or function parameter.
+ ///
+ /// **Belongs to the value namespace.**
+ Local(Id),
+
+ // 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
+ }
+}
+
+/// 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)]
+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",
+ }
+ }
+}
+
+/// 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) -> CtorKind {
+ match *vdata {
+ ast::VariantData::Tuple(..) => CtorKind::Fn,
+ ast::VariantData::Unit(..) => CtorKind::Const,
+ ast::VariantData::Struct(..) => CtorKind::Fictive,
+ }
+ }
+
+ pub fn from_hir(vdata: &hir::VariantData<'_>) -> CtorKind {
+ match *vdata {
+ hir::VariantData::Tuple(..) => CtorKind::Fn,
+ hir::VariantData::Unit(..) => CtorKind::Const,
+ hir::VariantData::Struct(..) => CtorKind::Fictive,
+ }
+ }
+}
+
+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"
+ }
+ NonMacroAttrKind::Registered => "explicitly registered attribute",
+ }
+ }
+
+ pub fn article(self) -> &'static str {
+ match self {
+ NonMacroAttrKind::Registered => "an",
+ _ => "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(..) | NonMacroAttrKind::Registered => 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::SelfTy { .. }
+ | 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::SelfTy { .. } => "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::SelfTy { trait_, alias_to } => Res::SelfTy { trait_, alias_to },
+ 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::SelfTy { trait_, alias_to } => Res::SelfTy { trait_, alias_to },
+ 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::SelfTy { .. } | 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 },
+}