mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
Auto merge of #82958 - camelid:res-docs, r=petrochenkov
Document `Res` and its friends I noticed [this Zulip conversation][z] and thought it would be a good idea to document `Res` and the other types near it. [z]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/.2382516.20-.20Add.20inherent.20associated.20types/near/227914819
This commit is contained in:
commit
0bbf473151
@ -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 {
|
||||
@ -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 {
|
||||
@ -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
|
||||
@ -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,
|
||||
@ -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
|
||||
PrimTy(hir::PrimTy),
|
||||
/// `Self`, with both an optional trait and impl `DefId`.
|
||||
/// A primitive type such as `i32` or `str`.
|
||||
///
|
||||
/// HACK(min_const_generics): impl self types also have an optional requirement to not mention
|
||||
/// **Belongs to the type namespace.**
|
||||
PrimTy(hir::PrimTy),
|
||||
/// 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
|
||||
///
|
||||
/// ```
|
||||
/// 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,
|
||||
}
|
||||
|
||||
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user