Skip to content

Commit

Permalink
Document Res and its friends
Browse files Browse the repository at this point in the history
  • Loading branch information
camelid committed Apr 8, 2021
1 parent 3a5d45f commit 8563a19
Showing 1 changed file with 142 additions and 13 deletions.
155 changes: 142 additions & 13 deletions compiler/rustc_hir/src/def.rs
Expand Up @@ -20,6 +20,7 @@ pub enum CtorOf {
Variant,
}

/// What kind of constructor something is.
#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
#[derive(HashStable_Generic)]
pub enum CtorKind {
Expand All @@ -31,6 +32,7 @@ pub enum CtorKind {
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 {
Expand All @@ -47,33 +49,51 @@ pub enum NonMacroAttrKind {
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.
/// 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.
/// Refers to the variant itself, [`DefKind::Ctor`] refers to its constructor if it exists.
Variant,
Trait,
/// `type Foo = Bar;`
/// 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,
/// 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() {} }`
AssocFn,
/// Associated constant: `trait MyTrait { const ASSOC: usize; }`
AssocConst,

// Macro namespace
Expand All @@ -82,11 +102,16 @@ pub enum DefKind {
// 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]`, or `const { 1 + 2}`
AnonConst,
/// Opaque type, aka `impl Trait`.
OpaqueTy,
Field,
/// Lifetime parameter: the `'a` in `struct Foo<'a> { ... }`
LifetimeParam,
/// A use of [`global_asm!`].
GlobalAsm,
Impl,
Closure,
Expand Down Expand Up @@ -196,35 +221,130 @@ impl DefKind {
}

/// 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),
/// `Self`, with both an optional trait and impl `DefId`.
/// The `Self` type, optionally with the trait it is associated with
/// and optionally with the [`DefId`] of the impl it is associated with.
///
/// **Belongs to the type namespace.**
///
/// For example, the `Self` in
///
/// HACK(min_const_generics): impl self types also have an optional requirement to not mention
/// ```
/// trait Foo {
/// fn foo() -> Box<Self>;
/// }
/// ```
///
/// would have the [`DefId`] of `Foo` associated with it. The `Self` in
///
/// ```
/// struct Bar;
///
/// impl Bar {
/// fn new() -> Self { Bar }
/// }
/// ```
///
/// would have the [`DefId`] of the impl associated with it. Finally, the `Self` in
///
/// ```
/// impl Foo for Bar {
/// fn foo() -> Box<Self> { Box::new(Bar) }
/// }
/// ```
///
/// would have both the [`DefId`] of `Foo` and the [`DefId`] of the impl
/// associated with it.
///
/// *See also [`Res::SelfCtor`].*
///
/// -----
///
/// HACK(min_const_generics): impl self types also have an optional requirement to **not** mention
/// any generic parameters to allow the following with `min_const_generics`:
/// ```rust
/// impl Foo { fn test() -> [u8; std::mem::size_of::<Self>()] {} }
/// ```
/// impl Foo { fn test() -> [u8; std::mem::size_of::<Self>()] { todo!() } }
/// ```
/// 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.
///
/// FIXME(lazy_normalization_consts): Remove this bodge once that feature is stable.
SelfTy(Option<DefId> /* trait */, Option<(DefId, bool)> /* impl */),
ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]`
SelfTy(
/// Optionally, the trait associated with this `Self` type.
Option<DefId>,
/// Optionally, the impl associated with this `Self` type.
Option<(DefId, bool)>,
),
/// A tool attribute module; e.g., the `rustfmt` in `#[rustfmt::skip]`.
///
/// **Belongs to the type namespace.**
ToolMod,

// Value namespace
SelfCtor(DefId /* impl */), // `DefId` refers to the impl
/// 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,
}

Expand Down Expand Up @@ -275,17 +395,26 @@ impl PartialRes {
}
}

/// Different kinds of symbols don't influence each other.
///
/// Therefore, they have a separate universe (namespace).
/// 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",
Expand Down

0 comments on commit 8563a19

Please sign in to comment.