compiler/rustc_hir/src/def.rs RUST 1,016 lines View on github.com → Search inside
1use std::array::IntoIter;2use std::borrow::Cow;3use std::fmt::Debug;45use rustc_ast as ast;6use rustc_ast::NodeId;7use rustc_data_structures::stable_hasher::ToStableHashKey;8use rustc_data_structures::unord::UnordMap;9use rustc_error_messages::{DiagArgValue, IntoDiagArg};10use rustc_macros::{Decodable, Encodable, StableHash};11use rustc_span::Symbol;12use rustc_span::def_id::{DefId, LocalDefId};13use rustc_span::hygiene::MacroKind;1415use crate::definitions::DefPathData;16use crate::hir;1718/// Encodes if a `DefKind::Ctor` is the constructor of an enum variant or a struct.19#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, StableHash)]20pub enum CtorOf {21    /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit struct.22    Struct,23    /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit variant.24    Variant,25}2627/// What kind of constructor something is.28#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, StableHash)]29pub enum CtorKind {30    /// Constructor function automatically created by a tuple struct/variant.31    Fn,32    /// Constructor constant automatically created by a unit struct/variant.33    Const,34}3536/// A set of macro kinds, for macros that can have more than one kind37#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Hash, Debug)]38#[derive(StableHash)]39pub struct MacroKinds(u8);40bitflags::bitflags! {41    impl MacroKinds: u8 {42        const BANG = 1 << 0;43        const ATTR = 1 << 1;44        const DERIVE = 1 << 2;45    }46}4748impl From<MacroKind> for MacroKinds {49    fn from(kind: MacroKind) -> Self {50        match kind {51            MacroKind::Bang => Self::BANG,52            MacroKind::Attr => Self::ATTR,53            MacroKind::Derive => Self::DERIVE,54        }55    }56}5758impl MacroKinds {59    /// Convert the MacroKinds to a static string.60    ///61    /// This hardcodes all the possibilities, in order to return a static string.62    pub fn descr(self) -> &'static str {63        match self {64            // FIXME: change this to "function-like macro" and fix all tests65            Self::BANG => "macro",66            Self::ATTR => "attribute macro",67            Self::DERIVE => "derive macro",68            _ if self == (Self::ATTR | Self::BANG) => "attribute/function macro",69            _ if self == (Self::DERIVE | Self::BANG) => "derive/function macro",70            _ if self == (Self::ATTR | Self::DERIVE) => "attribute/derive macro",71            _ if self.is_all() => "attribute/derive/function macro",72            _ if self.is_empty() => "useless macro",73            _ => unreachable!(),74        }75    }7677    /// Return an indefinite article (a/an) for use with `descr()`78    pub fn article(self) -> &'static str {79        if self.contains(Self::ATTR) { "an" } else { "a" }80    }81}8283/// An attribute that is not a macro; e.g., `#[inline]` or `#[rustfmt::skip]`.84#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, StableHash)]85pub enum NonMacroAttrKind {86    /// Single-segment attribute defined by the language (`#[inline]`)87    Builtin(Symbol),88    /// Multi-segment custom attribute living in a "tool module" (`#[rustfmt::skip]`).89    Tool,90    /// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`).91    DeriveHelper,92    /// Single-segment custom attribute registered by a derive macro93    /// but used before that derive macro was expanded (deprecated).94    DeriveHelperCompat,95}9697/// What kind of definition something is; e.g., `mod` vs `struct`.98/// `enum DefPathData` may need to be updated if a new variant is added here.99#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, StableHash)]100pub enum DefKind {101    // Type namespace102    Mod,103    /// Refers to the struct itself, [`DefKind::Ctor`] refers to its constructor if it exists.104    Struct,105    Union,106    Enum,107    /// Refers to the variant itself, [`DefKind::Ctor`] refers to its constructor if it exists.108    Variant,109    Trait,110    /// Type alias: `type Foo = Bar;`111    TyAlias,112    /// Type from an `extern` block.113    ForeignTy,114    /// Trait alias: `trait IntIterator = Iterator<Item = i32>;`115    TraitAlias,116    /// Associated type: `trait MyTrait { type Assoc; }`117    AssocTy,118    /// Type parameter: the `T` in `struct Vec<T> { ... }`119    TyParam,120121    // Value namespace122    Fn,123    Const {124        is_type_const: bool,125    },126    /// Constant generic parameter: `struct Foo<const N: usize> { ... }`127    ConstParam,128    Static {129        /// Whether it's a `unsafe static`, `safe static` (inside extern only) or just a `static`.130        safety: hir::Safety,131        /// Whether it's a `static mut` or just a `static`.132        mutability: ast::Mutability,133        /// Whether it's an anonymous static generated for nested allocations.134        nested: bool,135    },136    /// Refers to the struct or enum variant's constructor.137    ///138    /// The reason `Ctor` exists in addition to [`DefKind::Struct`] and139    /// [`DefKind::Variant`] is because structs and enum variants exist140    /// in the *type* namespace, whereas struct and enum variant *constructors*141    /// exist in the *value* namespace.142    ///143    /// You may wonder why enum variants exist in the type namespace as opposed144    /// to the value namespace. Check out [RFC 2593] for intuition on why that is.145    ///146    /// [RFC 2593]: https://github.com/rust-lang/rfcs/pull/2593147    Ctor(CtorOf, CtorKind),148    /// Associated function: `impl MyStruct { fn associated() {} }`149    /// or `trait Foo { fn associated() {} }`150    AssocFn,151    /// Associated constant: `trait MyTrait { const ASSOC: usize; }`152    AssocConst {153        is_type_const: bool,154    },155156    // Macro namespace157    Macro(MacroKinds),158159    // Not namespaced (or they are, but we don't treat them so)160    ExternCrate,161    Use,162    /// An `extern` block.163    ForeignMod,164    /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]`.165    ///166    /// Not all anon-consts are actually still relevant in the HIR. We lower167    /// trivial const-arguments directly to `hir::ConstArgKind::Path`, at which168    /// point the definition for the anon-const ends up unused and incomplete.169    ///170    /// We do not provide any a `Span` for the definition and pretty much all other171    /// queries also ICE when using this `DefId`. Given that the `DefId` of such172    /// constants should only be reachable by iterating all definitions of a173    /// given crate, you should not have to worry about this.174    AnonConst,175    /// An inline constant, e.g. `const { 1 + 2 }`176    InlineConst,177    /// Opaque type, aka `impl Trait`.178    OpaqueTy,179    /// A field in a struct, enum or union. e.g.180    /// - `bar` in `struct Foo { bar: u8 }`181    /// - `Foo::Bar::0` in `enum Foo { Bar(u8) }`182    Field,183    /// Lifetime parameter: the `'a` in `struct Foo<'a> { ... }`184    LifetimeParam,185    /// A use of `global_asm!`.186    GlobalAsm,187    Impl {188        of_trait: bool,189    },190    /// A closure, coroutine, or coroutine-closure.191    ///192    /// These are all represented with the same `ExprKind::Closure` in the AST and HIR,193    /// which makes it difficult to distinguish these during def collection. Therefore,194    /// we treat them all the same, and code which needs to distinguish them can match195    /// on `hir::ClosureKind` or `type_of`.196    Closure,197    /// The definition of a synthetic coroutine body created by the lowering of a198    /// coroutine-closure, such as an async closure.199    SyntheticCoroutineBody,200}201202impl DefKind {203    /// Get an English description for the item's kind.204    ///205    /// If you have access to `TyCtxt`, use `TyCtxt::def_descr` or206    /// `TyCtxt::def_kind_descr` instead, because they give better207    /// information for coroutines and associated functions.208    pub fn descr(self, def_id: DefId) -> &'static str {209        match self {210            DefKind::Fn => "function",211            DefKind::Mod if def_id.is_crate_root() && !def_id.is_local() => "crate",212            DefKind::Mod => "module",213            DefKind::Static { .. } => "static",214            DefKind::Enum => "enum",215            DefKind::Variant => "variant",216            DefKind::Ctor(CtorOf::Variant, CtorKind::Fn) => "tuple variant",217            DefKind::Ctor(CtorOf::Variant, CtorKind::Const) => "unit variant",218            DefKind::Struct => "struct",219            DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct",220            DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct",221            DefKind::OpaqueTy => "opaque type",222            DefKind::TyAlias => "type alias",223            DefKind::TraitAlias => "trait alias",224            DefKind::AssocTy => "associated type",225            DefKind::Union => "union",226            DefKind::Trait => "trait",227            DefKind::ForeignTy => "foreign type",228            DefKind::AssocFn => "associated function",229            DefKind::Const { .. } => "constant",230            DefKind::AssocConst { .. } => "associated constant",231            DefKind::TyParam => "type parameter",232            DefKind::ConstParam => "const parameter",233            DefKind::Macro(kinds) => kinds.descr(),234            DefKind::LifetimeParam => "lifetime parameter",235            DefKind::Use => "import",236            DefKind::ForeignMod => "foreign module",237            DefKind::AnonConst => "constant expression",238            DefKind::InlineConst => "inline constant",239            DefKind::Field => "field",240            DefKind::Impl { .. } => "implementation",241            DefKind::Closure => "closure",242            DefKind::ExternCrate => "extern crate",243            DefKind::GlobalAsm => "global assembly block",244            DefKind::SyntheticCoroutineBody => "synthetic mir body",245        }246    }247248    /// Gets an English article for the definition.249    ///250    /// If you have access to `TyCtxt`, use `TyCtxt::def_descr_article` or251    /// `TyCtxt::def_kind_descr_article` instead, because they give better252    /// information for coroutines and associated functions.253    pub fn article(&self) -> &'static str {254        match *self {255            DefKind::AssocTy256            | DefKind::AssocConst { .. }257            | DefKind::AssocFn258            | DefKind::Enum259            | DefKind::OpaqueTy260            | DefKind::Impl { .. }261            | DefKind::Use262            | DefKind::InlineConst263            | DefKind::ExternCrate => "an",264            DefKind::Macro(kinds) => kinds.article(),265            _ => "a",266        }267    }268269    pub fn ns(&self) -> Option<Namespace> {270        match self {271            DefKind::Mod272            | DefKind::Struct273            | DefKind::Union274            | DefKind::Enum275            | DefKind::Variant276            | DefKind::Trait277            | DefKind::TyAlias278            | DefKind::ForeignTy279            | DefKind::TraitAlias280            | DefKind::AssocTy281            | DefKind::TyParam => Some(Namespace::TypeNS),282283            DefKind::Fn284            | DefKind::Const { .. }285            | DefKind::ConstParam286            | DefKind::Static { .. }287            | DefKind::Ctor(..)288            | DefKind::AssocFn289            | DefKind::AssocConst { .. } => Some(Namespace::ValueNS),290291            DefKind::Macro(..) => Some(Namespace::MacroNS),292293            // Not namespaced.294            DefKind::AnonConst295            | DefKind::InlineConst296            | DefKind::Field297            | DefKind::LifetimeParam298            | DefKind::ExternCrate299            | DefKind::Closure300            | DefKind::Use301            | DefKind::ForeignMod302            | DefKind::GlobalAsm303            | DefKind::Impl { .. }304            | DefKind::OpaqueTy305            | DefKind::SyntheticCoroutineBody => None,306        }307    }308309    // Some `DefKind`s require a name, some don't. Panics if one is needed but310    // not provided. (`AssocTy` is an exception, see below.)311    pub fn def_path_data(self, name: Option<Symbol>) -> DefPathData {312        match self {313            DefKind::Mod314            | DefKind::Struct315            | DefKind::Union316            | DefKind::Enum317            | DefKind::Variant318            | DefKind::Trait319            | DefKind::TyAlias320            | DefKind::ForeignTy321            | DefKind::TraitAlias322            | DefKind::TyParam323            | DefKind::ExternCrate => DefPathData::TypeNs(name.unwrap()),324325            // An associated type name will be missing for an RPITIT (DefPathData::AnonAssocTy),326            // but those provide their own DefPathData.327            DefKind::AssocTy => DefPathData::TypeNs(name.unwrap()),328329            DefKind::Fn330            | DefKind::Const { .. }331            | DefKind::ConstParam332            | DefKind::Static { .. }333            | DefKind::AssocFn334            | DefKind::AssocConst { .. }335            | DefKind::Field => DefPathData::ValueNs(name.unwrap()),336            DefKind::Macro(..) => DefPathData::MacroNs(name.unwrap()),337            DefKind::LifetimeParam => DefPathData::LifetimeNs(name.unwrap()),338            DefKind::Ctor(..) => DefPathData::Ctor,339            DefKind::Use => DefPathData::Use,340            DefKind::ForeignMod => DefPathData::ForeignMod,341            DefKind::AnonConst => DefPathData::AnonConst,342            DefKind::InlineConst => DefPathData::AnonConst,343            DefKind::OpaqueTy => DefPathData::OpaqueTy,344            DefKind::GlobalAsm => DefPathData::GlobalAsm,345            DefKind::Impl { .. } => DefPathData::Impl,346            DefKind::Closure => DefPathData::Closure,347            DefKind::SyntheticCoroutineBody => DefPathData::SyntheticCoroutineBody,348        }349    }350351    pub fn is_assoc(self) -> bool {352        matches!(self, DefKind::AssocConst { .. } | DefKind::AssocFn | DefKind::AssocTy)353    }354355    /// This is a "module" in name resolution sense.356    #[inline]357    pub fn is_module_like(self) -> bool {358        matches!(self, DefKind::Mod | DefKind::Enum | DefKind::Trait)359    }360361    #[inline]362    pub fn is_adt(self) -> bool {363        matches!(self, DefKind::Struct | DefKind::Union | DefKind::Enum)364    }365366    #[inline]367    pub fn is_fn_like(self) -> bool {368        matches!(369            self,370            DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::SyntheticCoroutineBody371        )372    }373374    /// Whether the corresponding item has generic parameters, i.e. the `generics_of` query works.375    pub fn has_generics(self) -> bool {376        match self {377            DefKind::AnonConst378            | DefKind::AssocConst { .. }379            | DefKind::AssocFn380            | DefKind::AssocTy381            | DefKind::Closure382            | DefKind::Const { .. }383            | DefKind::Ctor(..)384            | DefKind::Enum385            | DefKind::Field386            | DefKind::Fn387            | DefKind::ForeignTy388            | DefKind::Impl { .. }389            | DefKind::InlineConst390            | DefKind::OpaqueTy391            | DefKind::Static { .. }392            | DefKind::Struct393            | DefKind::SyntheticCoroutineBody394            | DefKind::Trait395            | DefKind::TraitAlias396            | DefKind::TyAlias397            | DefKind::Union398            | DefKind::Variant => true,399            DefKind::ConstParam400            | DefKind::ExternCrate401            | DefKind::ForeignMod402            | DefKind::GlobalAsm403            | DefKind::LifetimeParam404            | DefKind::Macro(_)405            | DefKind::Mod406            | DefKind::TyParam407            | DefKind::Use => false,408        }409    }410411    /// Whether `query get_codegen_attrs` should be used with this definition.412    pub fn has_codegen_attrs(self) -> bool {413        match self {414            DefKind::Fn415            | DefKind::AssocFn416            | DefKind::Ctor(..)417            | DefKind::Closure418            | DefKind::Static { .. }419            | DefKind::SyntheticCoroutineBody => true,420            DefKind::Mod421            | DefKind::Struct422            | DefKind::Union423            | DefKind::Enum424            | DefKind::Variant425            | DefKind::Trait426            | DefKind::TyAlias427            | DefKind::ForeignTy428            | DefKind::TraitAlias429            | DefKind::AssocTy430            | DefKind::Const { .. }431            | DefKind::AssocConst { .. }432            | DefKind::Macro(..)433            | DefKind::Use434            | DefKind::ForeignMod435            | DefKind::OpaqueTy436            | DefKind::Impl { .. }437            | DefKind::Field438            | DefKind::TyParam439            | DefKind::ConstParam440            | DefKind::LifetimeParam441            | DefKind::AnonConst442            | DefKind::InlineConst443            | DefKind::GlobalAsm444            | DefKind::ExternCrate => false,445        }446    }447448    /// Returns `true` if `self` is a kind of definition that does not have its own449    /// type-checking context, i.e. closure, coroutine or inline const.450    #[inline]451    pub fn is_typeck_child(self) -> bool {452        match self {453            DefKind::Closure | DefKind::InlineConst | DefKind::SyntheticCoroutineBody => true,454            DefKind::Mod455            | DefKind::Struct456            | DefKind::Union457            | DefKind::Enum458            | DefKind::Variant459            | DefKind::Trait460            | DefKind::TyAlias461            | DefKind::ForeignTy462            | DefKind::TraitAlias463            | DefKind::AssocTy464            | DefKind::TyParam465            | DefKind::Fn466            | DefKind::Const { .. }467            | DefKind::ConstParam468            | DefKind::Static { .. }469            | DefKind::Ctor(_, _)470            | DefKind::AssocFn471            | DefKind::AssocConst { .. }472            | DefKind::Macro(_)473            | DefKind::ExternCrate474            | DefKind::Use475            | DefKind::ForeignMod476            | DefKind::AnonConst477            | DefKind::OpaqueTy478            | DefKind::Field479            | DefKind::LifetimeParam480            | DefKind::GlobalAsm481            | DefKind::Impl { .. } => false,482        }483    }484}485486/// The resolution of a path or export.487///488/// For every path or identifier in Rust, the compiler must determine489/// what the path refers to. This process is called name resolution,490/// and `Res` is the primary result of name resolution.491///492/// For example, everything prefixed with `/* Res */` in this example has493/// an associated `Res`:494///495/// ```ignore (illustrative)496/// fn str_to_string(s: & /* Res */ str) -> /* Res */ String {497///     /* Res */ String::from(/* Res */ s)498/// }499///500/// /* Res */ str_to_string("hello");501/// ```502///503/// The associated `Res`s will be:504///505/// - `str` will resolve to [`Res::PrimTy`];506/// - `String` will resolve to [`Res::Def`], and the `Res` will include the [`DefId`]507///   for `String` as defined in the standard library;508/// - `String::from` will also resolve to [`Res::Def`], with the [`DefId`]509///   pointing to `String::from`;510/// - `s` will resolve to [`Res::Local`];511/// - the call to `str_to_string` will resolve to [`Res::Def`], with the [`DefId`]512///   pointing to the definition of `str_to_string` in the current crate.513//514#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, StableHash)]515pub enum Res<Id = hir::HirId> {516    /// Definition having a unique ID (`DefId`), corresponds to something defined in user code.517    ///518    /// **Not bound to a specific namespace.**519    Def(DefKind, DefId),520521    // Type namespace522    /// A primitive type such as `i32` or `str`.523    ///524    /// **Belongs to the type namespace.**525    PrimTy(hir::PrimTy),526527    /// The `Self` type, as used within a trait.528    ///529    /// **Belongs to the type namespace.**530    ///531    /// See the examples on [`Res::SelfTyAlias`] for details.532    SelfTyParam {533        /// The trait this `Self` is a generic parameter for.534        trait_: DefId,535    },536537    /// The `Self` type, as used somewhere other than within a trait.538    ///539    /// **Belongs to the type namespace.**540    ///541    /// Examples:542    /// ```543    /// struct Bar(Box<Self>); // SelfTyAlias544    ///545    /// trait Foo {546    ///     fn foo() -> Box<Self>; // SelfTyParam547    /// }548    ///549    /// impl Bar {550    ///     fn blah() {551    ///         let _: Self; // SelfTyAlias552    ///     }553    /// }554    ///555    /// impl Foo for Bar {556    ///     fn foo() -> Box<Self /* SelfTyAlias */> {557    ///         let _: Self;        // SelfTyAlias558    ///559    ///         todo!()560    ///     }561    /// }562    /// ```563    /// *See also [`Res::SelfCtor`].*564    ///565    SelfTyAlias {566        /// The item introducing the `Self` type alias. Can be used in the `type_of` query567        /// to get the underlying type.568        alias_to: DefId,569570        /// Is this within an `impl Foo for bar`?571        is_trait_impl: bool,572    },573574    // Value namespace575    /// The `Self` constructor, along with the [`DefId`]576    /// of the impl it is associated with.577    ///578    /// **Belongs to the value namespace.**579    ///580    /// *See also [`Res::SelfTyParam`] and [`Res::SelfTyAlias`].*581    SelfCtor(DefId),582583    /// A local variable or function parameter.584    ///585    /// **Belongs to the value namespace.**586    Local(Id),587588    /// A tool attribute module; e.g., the `rustfmt` in `#[rustfmt::skip]`.589    ///590    /// **Belongs to the type namespace.**591    ToolMod,592593    /// The resolution for an open module in a namespaced crate. E.g. `my_api`594    /// in the namespaced crate `my_api::utils` when `my_api` isn't part of the595    /// extern prelude.596    ///597    /// **Belongs to the type namespace.**598    OpenMod(Symbol),599600    // Macro namespace601    /// An attribute that is *not* implemented via macro.602    /// E.g., `#[inline]` and `#[rustfmt::skip]`, which are essentially directives,603    /// as opposed to `#[test]`, which is a builtin macro.604    ///605    /// **Belongs to the macro namespace.**606    NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]`607608    // All namespaces609    /// Name resolution failed. We use a dummy `Res` variant so later phases610    /// of the compiler won't crash and can instead report more errors.611    ///612    /// **Not bound to a specific namespace.**613    Err,614}615616impl<Id> IntoDiagArg for Res<Id> {617    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {618        DiagArgValue::Str(Cow::Borrowed(self.descr()))619    }620}621622/// The result of resolving a path before lowering to HIR,623/// with "module" segments resolved and associated item624/// segments deferred to type checking.625/// `base_res` is the resolution of the resolved part of the626/// path, `unresolved_segments` is the number of unresolved627/// segments.628///629/// ```text630/// module::Type::AssocX::AssocY::MethodOrAssocType631/// ^~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~632/// base_res      unresolved_segments = 3633///634/// <T as Trait>::AssocX::AssocY::MethodOrAssocType635///       ^~~~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~636///       base_res        unresolved_segments = 2637/// ```638#[derive(Copy, Clone, Debug)]639pub struct PartialRes {640    base_res: Res<NodeId>,641    unresolved_segments: usize,642}643644impl PartialRes {645    #[inline]646    pub fn new(base_res: Res<NodeId>) -> Self {647        PartialRes { base_res, unresolved_segments: 0 }648    }649650    #[inline]651    pub fn with_unresolved_segments(base_res: Res<NodeId>, mut unresolved_segments: usize) -> Self {652        if base_res == Res::Err {653            unresolved_segments = 0654        }655        PartialRes { base_res, unresolved_segments }656    }657658    #[inline]659    pub fn base_res(&self) -> Res<NodeId> {660        self.base_res661    }662663    #[inline]664    pub fn unresolved_segments(&self) -> usize {665        self.unresolved_segments666    }667668    #[inline]669    pub fn full_res(&self) -> Option<Res<NodeId>> {670        (self.unresolved_segments == 0).then_some(self.base_res)671    }672673    #[inline]674    pub fn expect_full_res(&self) -> Res<NodeId> {675        self.full_res().expect("unexpected unresolved segments")676    }677}678679/// Different kinds of symbols can coexist even if they share the same textual name.680/// Therefore, they each have a separate universe (known as a "namespace").681#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]682#[derive(StableHash)]683pub enum Namespace {684    /// The type namespace includes `struct`s, `enum`s, `union`s, `trait`s, and `mod`s685    /// (and, by extension, crates).686    ///687    /// Note that the type namespace includes other items; this is not an688    /// exhaustive list.689    TypeNS,690    /// The value namespace includes `fn`s, `const`s, `static`s, and local variables (including function arguments).691    ValueNS,692    /// The macro namespace includes `macro_rules!` macros, declarative `macro`s,693    /// procedural macros, attribute macros, `derive` macros, and non-macro attributes694    /// like `#[inline]` and `#[rustfmt::skip]`.695    MacroNS,696}697698impl Namespace {699    /// The English description of the namespace.700    pub fn descr(self) -> &'static str {701        match self {702            Self::TypeNS => "type",703            Self::ValueNS => "value",704            Self::MacroNS => "macro",705        }706    }707}708709impl IntoDiagArg for Namespace {710    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {711        DiagArgValue::Str(Cow::Borrowed(self.descr()))712    }713}714715impl ToStableHashKey for Namespace {716    type KeyType = Namespace;717718    #[inline]719    fn to_stable_hash_key<Hcx>(&self, _: &mut Hcx) -> Namespace {720        *self721    }722}723724/// Just a helper ‒ separate structure for each namespace.725#[derive(Copy, Clone, Default, Debug, StableHash)]726pub struct PerNS<T> {727    pub value_ns: T,728    pub type_ns: T,729    pub macro_ns: T,730}731732impl<T> PerNS<T> {733    pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> PerNS<U> {734        PerNS { value_ns: f(self.value_ns), type_ns: f(self.type_ns), macro_ns: f(self.macro_ns) }735    }736737    /// Note: Do you really want to use this? Often you know which namespace a738    /// name will belong in, and you can consider just that namespace directly,739    /// rather than iterating through all of them.740    pub fn into_iter(self) -> IntoIter<T, 3> {741        [self.value_ns, self.type_ns, self.macro_ns].into_iter()742    }743744    /// Note: Do you really want to use this? Often you know which namespace a745    /// name will belong in, and you can consider just that namespace directly,746    /// rather than iterating through all of them.747    pub fn iter(&self) -> IntoIter<&T, 3> {748        [&self.value_ns, &self.type_ns, &self.macro_ns].into_iter()749    }750}751752impl<T> ::std::ops::Index<Namespace> for PerNS<T> {753    type Output = T;754755    fn index(&self, ns: Namespace) -> &T {756        match ns {757            Namespace::ValueNS => &self.value_ns,758            Namespace::TypeNS => &self.type_ns,759            Namespace::MacroNS => &self.macro_ns,760        }761    }762}763764impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> {765    fn index_mut(&mut self, ns: Namespace) -> &mut T {766        match ns {767            Namespace::ValueNS => &mut self.value_ns,768            Namespace::TypeNS => &mut self.type_ns,769            Namespace::MacroNS => &mut self.macro_ns,770        }771    }772}773774impl<T> PerNS<Option<T>> {775    /// Returns `true` if all the items in this collection are `None`.776    pub fn is_empty(&self) -> bool {777        self.type_ns.is_none() && self.value_ns.is_none() && self.macro_ns.is_none()778    }779780    /// Returns an iterator over the items which are `Some`.781    ///782    /// Note: Do you really want to use this? Often you know which namespace a783    /// name will belong in, and you can consider just that namespace directly,784    /// rather than iterating through all of them.785    pub fn present_items(self) -> impl Iterator<Item = T> {786        [self.type_ns, self.value_ns, self.macro_ns].into_iter().flatten()787    }788}789790impl CtorKind {791    pub fn from_ast(vdata: &ast::VariantData) -> Option<(CtorKind, NodeId)> {792        match *vdata {793            ast::VariantData::Tuple(_, node_id) => Some((CtorKind::Fn, node_id)),794            ast::VariantData::Unit(node_id) => Some((CtorKind::Const, node_id)),795            ast::VariantData::Struct { .. } => None,796        }797    }798}799800impl NonMacroAttrKind {801    pub fn descr(self) -> &'static str {802        match self {803            NonMacroAttrKind::Builtin(..) => "built-in attribute",804            NonMacroAttrKind::Tool => "tool attribute",805            NonMacroAttrKind::DeriveHelper | NonMacroAttrKind::DeriveHelperCompat => {806                "derive helper attribute"807            }808        }809    }810811    // Currently trivial, but exists in case a new kind is added in the future whose name starts812    // with a vowel.813    pub fn article(self) -> &'static str {814        "a"815    }816817    /// Users of some attributes cannot mark them as used, so they are considered always used.818    pub fn is_used(self) -> bool {819        match self {820            NonMacroAttrKind::Tool821            | NonMacroAttrKind::DeriveHelper822            | NonMacroAttrKind::DeriveHelperCompat => true,823            NonMacroAttrKind::Builtin(..) => false,824        }825    }826}827828impl<Id> Res<Id> {829    /// Return the `DefId` of this `Def` if it has an ID, else panic.830    pub fn def_id(&self) -> DefId831    where832        Id: Debug,833    {834        self.opt_def_id().unwrap_or_else(|| panic!("attempted .def_id() on invalid res: {self:?}"))835    }836837    /// Return `Some(..)` with the `DefId` of this `Res` if it has a ID, else `None`.838    pub fn opt_def_id(&self) -> Option<DefId> {839        match *self {840            Res::Def(_, id) => Some(id),841842            Res::Local(..)843            | Res::PrimTy(..)844            | Res::SelfTyParam { .. }845            | Res::SelfTyAlias { .. }846            | Res::SelfCtor(..)847            | Res::ToolMod848            | Res::OpenMod(..)849            | Res::NonMacroAttr(..)850            | Res::Err => None,851        }852    }853854    /// Return the `DefId` of this `Res` if it represents a module.855    pub fn mod_def_id(&self) -> Option<DefId> {856        match *self {857            Res::Def(DefKind::Mod, id) => Some(id),858            _ => None,859        }860    }861862    /// If this is a "module" in name resolution sense, return its `DefId`.863    #[inline]864    pub fn module_like_def_id(&self) -> Option<DefId> {865        match self {866            Res::Def(def_kind, def_id) if def_kind.is_module_like() => Some(*def_id),867            _ => None,868        }869    }870871    /// A human readable name for the res kind ("function", "module", etc.).872    pub fn descr(&self) -> &'static str {873        match *self {874            Res::Def(kind, def_id) => kind.descr(def_id),875            Res::SelfCtor(..) => "self constructor",876            Res::PrimTy(..) => "builtin type",877            Res::Local(..) => "local variable",878            Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => "self type",879            Res::ToolMod => "tool module",880            Res::OpenMod(..) => "namespaced crate",881            Res::NonMacroAttr(attr_kind) => attr_kind.descr(),882            Res::Err => "unresolved item",883        }884    }885886    /// Gets an English article for the `Res`.887    pub fn article(&self) -> &'static str {888        match *self {889            Res::Def(kind, _) => kind.article(),890            Res::NonMacroAttr(kind) => kind.article(),891            Res::Err => "an",892            _ => "a",893        }894    }895896    pub fn map_id<R>(self, mut map: impl FnMut(Id) -> R) -> Res<R> {897        match self {898            Res::Def(kind, id) => Res::Def(kind, id),899            Res::SelfCtor(id) => Res::SelfCtor(id),900            Res::PrimTy(id) => Res::PrimTy(id),901            Res::Local(id) => Res::Local(map(id)),902            Res::SelfTyParam { trait_ } => Res::SelfTyParam { trait_ },903            Res::SelfTyAlias { alias_to, is_trait_impl } => {904                Res::SelfTyAlias { alias_to, is_trait_impl }905            }906            Res::ToolMod => Res::ToolMod,907            Res::OpenMod(sym) => Res::OpenMod(sym),908            Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),909            Res::Err => Res::Err,910        }911    }912913    pub fn apply_id<R, E>(self, mut map: impl FnMut(Id) -> Result<R, E>) -> Result<Res<R>, E> {914        Ok(match self {915            Res::Def(kind, id) => Res::Def(kind, id),916            Res::SelfCtor(id) => Res::SelfCtor(id),917            Res::PrimTy(id) => Res::PrimTy(id),918            Res::Local(id) => Res::Local(map(id)?),919            Res::SelfTyParam { trait_ } => Res::SelfTyParam { trait_ },920            Res::SelfTyAlias { alias_to, is_trait_impl } => {921                Res::SelfTyAlias { alias_to, is_trait_impl }922            }923            Res::ToolMod => Res::ToolMod,924            Res::OpenMod(sym) => Res::OpenMod(sym),925            Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),926            Res::Err => Res::Err,927        })928    }929930    #[track_caller]931    pub fn expect_non_local<OtherId>(self) -> Res<OtherId> {932        self.map_id(933            #[track_caller]934            |_| panic!("unexpected `Res::Local`"),935        )936    }937938    pub fn macro_kinds(self) -> Option<MacroKinds> {939        match self {940            Res::Def(DefKind::Macro(kinds), _) => Some(kinds),941            Res::NonMacroAttr(..) => Some(MacroKinds::ATTR),942            _ => None,943        }944    }945946    /// Returns `None` if this is `Res::Err`947    pub fn ns(&self) -> Option<Namespace> {948        match self {949            Res::Def(kind, ..) => kind.ns(),950            Res::PrimTy(..)951            | Res::SelfTyParam { .. }952            | Res::SelfTyAlias { .. }953            | Res::ToolMod954            | Res::OpenMod(..) => Some(Namespace::TypeNS),955            Res::SelfCtor(..) | Res::Local(..) => Some(Namespace::ValueNS),956            Res::NonMacroAttr(..) => Some(Namespace::MacroNS),957            Res::Err => None,958        }959    }960961    /// Always returns `true` if `self` is `Res::Err`962    pub fn matches_ns(&self, ns: Namespace) -> bool {963        self.ns().is_none_or(|actual_ns| actual_ns == ns)964    }965966    /// Returns whether such a resolved path can occur in a tuple struct/variant pattern967    pub fn expected_in_tuple_struct_pat(&self) -> bool {968        matches!(self, Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) | Res::SelfCtor(..))969    }970971    /// Returns whether such a resolved path can occur in a unit struct/variant pattern972    pub fn expected_in_unit_struct_pat(&self) -> bool {973        matches!(self, Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::SelfCtor(..))974    }975}976977/// Resolution for a lifetime appearing in a type.978#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]979pub enum LifetimeRes {980    /// Successfully linked the lifetime to a generic parameter.981    Param {982        /// Id of the generic parameter that introduced it.983        param: LocalDefId,984        /// Id of the introducing place. That can be:985        /// - an item's id, for the item's generic parameters;986        /// - a TraitRef's ref_id, identifying the `for<...>` binder;987        /// - a FnPtr type's id.988        ///989        /// This information is used for impl-trait lifetime captures, to know when to or not to990        /// capture any given lifetime.991        binder: NodeId,992    },993    /// Created a generic parameter for an anonymous lifetime.994    Fresh {995        /// Id of the generic parameter that introduced it.996        ///997        /// Creating the associated `LocalDefId` is the responsibility of lowering.998        param: NodeId,999        /// Id of the introducing place. See `Param`.1000        binder: NodeId,1001        /// Kind of elided lifetime1002        kind: hir::MissingLifetimeKind,1003    },1004    /// This variant is used for anonymous lifetimes that we did not resolve during1005    /// late resolution. Those lifetimes will be inferred by typechecking.1006    Infer,1007    /// `'static` lifetime.1008    Static,1009    /// Resolution failure.1010    Error(rustc_span::ErrorGuaranteed),1011    /// HACK: This is used to recover the NodeId of an elided lifetime.1012    ElidedAnchor { start: NodeId, end: NodeId },1013}10141015pub type DocLinkResMap = UnordMap<(Symbol, Namespace), Option<Res<NodeId>>>;

Code quality findings 27

Critical: Use of 'unsafe' keyword bypasses Rust's safety guarantees. Requires careful auditing, clear justification (FFI, specific optimizations), and minimal scope.
error safety unsafe-block
/// Whether it's a `unsafe static`, `safe static` (inside extern only) or just a `static`.
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
/// The reason `Ctor` exists in addition to [`DefKind::Struct`] and
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
/// to the value namespace. Check out [RFC 2593] for intuition on why that is.
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
| DefKind::ExternCrate => DefPathData::TypeNs(name.unwrap()),
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
DefKind::AssocTy => DefPathData::TypeNs(name.unwrap()),
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
| DefKind::Field => DefPathData::ValueNs(name.unwrap()),
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
DefKind::Macro(..) => DefPathData::MacroNs(name.unwrap()),
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
DefKind::LifetimeParam => DefPathData::LifetimeNs(name.unwrap()),
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
/// - `str` will resolve to [`Res::PrimTy`];
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
/// - `String` will resolve to [`Res::Def`], and the `Res` will include the [`DefId`]
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
/// - `String::from` will also resolve to [`Res::Def`], with the [`DefId`]
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
/// - `s` will resolve to [`Res::Local`];
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
/// - the call to `str_to_string` will resolve to [`Res::Def`], with the [`DefId`]
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
/// See the examples on [`Res::SelfTyAlias`] for details.
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
/// *See also [`Res::SelfCtor`].*
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
/// The `Self` constructor, along with the [`DefId`]
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
/// *See also [`Res::SelfTyParam`] and [`Res::SelfTyAlias`].*
Warning: '.expect()' will panic with a custom message on None/Err. While better than unwrap() for debugging, prefer non-panicking error handling in production code (match, if let, ?).
warning correctness expect-usage
self.full_res().expect("unexpected unresolved segments")
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match self {
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info correctness todo-unimplemented
/// todo!()
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match *self {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match self {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match *self {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match *self {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match self {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match self {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match self {

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.