rust/compiler/rustc_hir/src/def.rs

780 lines
26 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use crate::hir;
use rustc_ast as ast;
use rustc_ast::NodeId;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::ToStableHashKey;
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,
}
/// 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,
}
/// 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 {
of_trait: bool,
},
Closure,
Generator,
}
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 generators 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::Generator => "generator",
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 generators 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::Generator
| DefKind::Use
| DefKind::ForeignMod
| DefKind::GlobalAsm
| DefKind::Impl { .. } => None,
}
}
#[inline]
pub fn is_fn_like(self) -> bool {
matches!(self, DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Generator)
}
/// 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, 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"
}
}
}
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 = FxHashMap<(Symbol, Namespace), Option<Res<NodeId>>>;