提交 0bbf4731 编写于 作者: B bors

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
...@@ -20,6 +20,7 @@ pub enum CtorOf { ...@@ -20,6 +20,7 @@ pub enum CtorOf {
Variant, Variant,
} }
/// What kind of constructor something is.
#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
#[derive(HashStable_Generic)] #[derive(HashStable_Generic)]
pub enum CtorKind { pub enum CtorKind {
...@@ -31,6 +32,7 @@ pub enum CtorKind { ...@@ -31,6 +32,7 @@ pub enum CtorKind {
Fictive, Fictive,
} }
/// An attribute that is not a macro; e.g., `#[inline]` or `#[rustfmt::skip]`.
#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
#[derive(HashStable_Generic)] #[derive(HashStable_Generic)]
pub enum NonMacroAttrKind { pub enum NonMacroAttrKind {
...@@ -47,33 +49,51 @@ pub enum NonMacroAttrKind { ...@@ -47,33 +49,51 @@ pub enum NonMacroAttrKind {
Registered, Registered,
} }
/// What kind of definition something is; e.g., `mod` vs `struct`.
#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
#[derive(HashStable_Generic)] #[derive(HashStable_Generic)]
pub enum DefKind { pub enum DefKind {
// Type namespace // Type namespace
Mod, 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, Struct,
Union, Union,
Enum, 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, Variant,
Trait, Trait,
/// `type Foo = Bar;` /// Type alias: `type Foo = Bar;`
TyAlias, TyAlias,
/// Type from an `extern` block.
ForeignTy, ForeignTy,
/// Trait alias: `trait IntIterator = Iterator<Item = i32>;`
TraitAlias, TraitAlias,
/// Associated type: `trait MyTrait { type Assoc; }`
AssocTy, AssocTy,
/// Type parameter: the `T` in `struct Vec<T> { ... }`
TyParam, TyParam,
// Value namespace // Value namespace
Fn, Fn,
Const, Const,
/// Constant generic parameter: `struct Foo<const N: usize> { ... }`
ConstParam, ConstParam,
Static, Static,
/// Refers to the struct or enum variant's constructor. /// 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), Ctor(CtorOf, CtorKind),
/// Associated function: `impl MyStruct { fn associated() {} }`
AssocFn, AssocFn,
/// Associated constant: `trait MyTrait { const ASSOC: usize; }`
AssocConst, AssocConst,
// Macro namespace // Macro namespace
...@@ -82,11 +102,16 @@ pub enum DefKind { ...@@ -82,11 +102,16 @@ pub enum DefKind {
// Not namespaced (or they are, but we don't treat them so) // Not namespaced (or they are, but we don't treat them so)
ExternCrate, ExternCrate,
Use, Use,
/// An `extern` block.
ForeignMod, ForeignMod,
/// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]`, or `const { 1 + 2}`
AnonConst, AnonConst,
/// Opaque type, aka `impl Trait`.
OpaqueTy, OpaqueTy,
Field, Field,
/// Lifetime parameter: the `'a` in `struct Foo<'a> { ... }`
LifetimeParam, LifetimeParam,
/// A use of [`global_asm!`].
GlobalAsm, GlobalAsm,
Impl, Impl,
Closure, Closure,
...@@ -196,35 +221,130 @@ pub fn ns(&self) -> Option<Namespace> { ...@@ -196,35 +221,130 @@ pub fn ns(&self) -> Option<Namespace> {
} }
/// The resolution of a path or export. /// 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(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
#[derive(HashStable_Generic)] #[derive(HashStable_Generic)]
pub enum Res<Id = hir::HirId> { 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), Def(DefKind, DefId),
// Type namespace // Type namespace
/// A primitive type such as `i32` or `str`.
///
/// **Belongs to the type namespace.**
PrimTy(hir::PrimTy), 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`: /// 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 /// 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. /// 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. /// FIXME(lazy_normalization_consts): Remove this bodge once that feature is stable.
SelfTy(Option<DefId> /* trait */, Option<(DefId, bool)> /* impl */), SelfTy(
ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]` /// 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 // 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), Local(Id),
// Macro namespace // 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]` NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]`
// All namespaces // 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, Err,
} }
...@@ -275,17 +395,26 @@ pub fn unresolved_segments(&self) -> usize { ...@@ -275,17 +395,26 @@ pub fn unresolved_segments(&self) -> usize {
} }
} }
/// Different kinds of symbols don't influence each other. /// 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").
/// Therefore, they have a separate universe (namespace).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum Namespace { 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, TypeNS,
/// The value namespace includes `fn`s, `const`s, `static`s, and local variables (including function arguments).
ValueNS, 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, MacroNS,
} }
impl Namespace { impl Namespace {
/// The English description of the namespace.
pub fn descr(self) -> &'static str { pub fn descr(self) -> &'static str {
match self { match self {
Self::TypeNS => "type", Self::TypeNS => "type",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册