From 5db59a41242140ff85aa1a6f8cfbbdf5873d8d03 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 18 Feb 2025 11:10:24 -0800 Subject: [PATCH] Add rule identifiers to names chapters --- src/names/namespaces.md | 9 ++++++++ src/names/preludes.md | 42 +++++++++++++++++++++++++++++++---- src/names/scopes.md | 49 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 4 deletions(-) diff --git a/src/names/namespaces.md b/src/names/namespaces.md index b27511eb3..afe48a2e5 100644 --- a/src/names/namespaces.md +++ b/src/names/namespaces.md @@ -1,5 +1,7 @@ +r[names.namespaces] # Namespaces +r[names.namespaces.intro] A *namespace* is a logical grouping of declared [names]. Names are segregated into separate namespaces based on the kind of entity the name refers to. Namespaces allow the occurrence of a name in one namespace to not conflict @@ -10,6 +12,7 @@ entities. The usage of a name will look for the declaration of that name in different namespaces, based on the context, as described in the [name resolution] chapter. +r[names.namespaces.kinds] The following is a list of namespaces, with their corresponding entities: * Type Namespace @@ -81,6 +84,7 @@ fn example<'Foo>(f: Foo) { } ``` +r[names.namespaces.without] ## Named entities without a namespace The following entities have explicit names, but the names are not a part of @@ -88,6 +92,7 @@ any specific namespace. ### Fields +r[names.namespaces.without.fields] Even though struct, enum, and union fields are named, the named fields do not live in an explicit namespace. They can only be accessed via a [field expression], which only inspects the field names of the specific type being @@ -95,13 +100,16 @@ accessed. ### Use declarations +r[names.namespaces.without.use] A [use declaration] has named aliases that it imports into scope, but the `use` item itself does not belong to a specific namespace. Instead, it can introduce aliases into multiple namespaces, depending on the item kind being imported. +r[names.namespaces.sub-namespaces] ## Sub-namespaces +r[names.namespaces.sub-namespaces.intro] The macro namespace is split into two sub-namespaces: one for [bang-style macros] and one for [attributes]. When an attribute is resolved, any bang-style macros in scope will be ignored. And conversely resolving a bang-style macro will ignore attribute macros in scope. @@ -109,6 +117,7 @@ This prevents one style from shadowing another. For example, the [`cfg` attribute] and the [`cfg` macro] are two different entities with the same name in the macro namespace, but they can still be used in their respective context. +r[names.namespaces.sub-namespaces.use-shadow] It is still an error for a [`use` import] to shadow another macro, regardless of their sub-namespaces. [`cfg` attribute]: ../conditional-compilation.md#the-cfg-attribute diff --git a/src/names/preludes.md b/src/names/preludes.md index 8ec9c493a..218cb2151 100644 --- a/src/names/preludes.md +++ b/src/names/preludes.md @@ -1,5 +1,7 @@ +r[names.preludes] # Preludes +r[names.preludes.intro] A *prelude* is a collection of names that are automatically brought into scope of every module in a crate. @@ -8,6 +10,7 @@ queried during [name resolution]. For example, even though something like [`Box`] is in scope in every module, you cannot refer to it as `self::Box` because it is not a member of the current module. +r[names.preludes.kinds] There are several different preludes: - [Standard library prelude] @@ -16,9 +19,13 @@ There are several different preludes: - [`macro_use` prelude] - [Tool prelude] +r[names.preludes.std] ## Standard library prelude +r[names.preludes.std.intro] Each crate has a standard library prelude, which consists of the names from a single standard library module. + +r[names.preludes.std.module] The module used depends on the crate's edition, and on whether the [`no_std` attribute] is applied to the crate: Edition | `no_std` not applied | `no_std` applied @@ -35,16 +42,22 @@ Edition | `no_std` not applied | `no_std` applied > > [`core::prelude::rust_2015`] and [`core::prelude::rust_2018`] have the same contents as [`core::prelude::v1`]. +r[names.preludes.extern] ## Extern prelude +r[names.preludes.extern.intro] External crates imported with [`extern crate`] in the root module or provided to the compiler (as with the `--extern` flag with `rustc`) are added to the *extern prelude*. If imported with an alias such as `extern crate orig_name as new_name`, then the symbol `new_name` is instead added to the prelude. -The [`core`] crate is always added to the extern prelude. The [`std`] crate is -added as long as the [`no_std` attribute] is not specified in the crate root. +r[names.preludes.extern.core] +The [`core`] crate is always added to the extern prelude. + +r[names.preludes.extern.std] +The [`std`] crate is added as long as the [`no_std` attribute] is not specified in the crate root. +r[names.preludes.extern.edition2018] > **Edition differences**: In the 2015 edition, crates in the extern prelude > cannot be referenced via [use declarations], so it is generally standard > practice to include `extern crate` declarations to bring them into scope. @@ -70,19 +83,27 @@ See https://github.com/rust-lang/rust/issues/57288 for more about the alloc/test limitation. --> +r[names.preludes.extern.no_std] ### The `no_std` attribute +r[names.preludes.extern.no_std.intro] By default, the standard library is automatically included in the crate root module. The [`std`] crate is added to the root, along with an implicit [`macro_use` attribute] pulling in all macros exported from `std` into the [`macro_use` prelude]. Both [`core`] and [`std`] are added to the [extern prelude]. +r[names.preludes.extern.no_std.allowed-positions] The *`no_std` [attribute]* may be applied at the crate level to prevent the -[`std`] crate from being automatically added into scope. It does three things: +[`std`] crate from being automatically added into scope. +It does three things: + +r[names.preludes.extern.no_std.extern] * Prevents `std` from being added to the [extern prelude](#extern-prelude). +r[names.preludes.extern.no_std.module] * Affects which module is used to make up the [standard library prelude] (as described above). +r[names.preludes.extern.no_std.core] * Injects the [`core`] crate into the crate root instead of [`std`], and pulls in all macros exported from `core` in the [`macro_use` prelude]. @@ -95,10 +116,15 @@ The *`no_std` [attribute]* may be applied at the crate level to prevent the > [!WARNING] > Using `no_std` does not prevent the standard library from being linked in. It is still valid to put `extern crate std;` into the crate and dependencies can also link it in. +r[names.preludes.lang] ## Language prelude +r[names.preludes.lang.intro] The language prelude includes names of types and attributes that are built-in -to the language. The language prelude is always in scope. It includes the following: +to the language. The language prelude is always in scope. + +r[names.preludes.lang.entities] +It includes the following: * [Type namespace] * [Boolean type] --- `bool` @@ -109,25 +135,33 @@ to the language. The language prelude is always in scope. It includes the follow * [Macro namespace] * [Built-in attributes] +r[names.preludes.macro_use] ## `macro_use` prelude +r[names.preludes.macro_use.intro] The `macro_use` prelude includes macros from external crates that were imported by the [`macro_use` attribute] applied to an [`extern crate`]. +r[names.preludes.tool] ## Tool prelude +r[names.preludes.tool.intro] The tool prelude includes tool names for external tools in the [type namespace]. See the [tool attributes] section for more details. +r[names.preludes.no_implicit_prelude] ## The `no_implicit_prelude` attribute +r[names.preludes.no_implicit_prelude.intro] The *`no_implicit_prelude` [attribute]* may be applied at the crate level or on a module to indicate that it should not automatically bring the [standard library prelude], [extern prelude], or [tool prelude] into scope for that module or any of its descendants. +r[names.preludes.no_implicit_prelude.lang] This attribute does not affect the [language prelude]. +r[names.preludes.no_implicit_prelude.edition2018] > **Edition differences**: In the 2015 edition, the `no_implicit_prelude` > attribute does not affect the [`macro_use` prelude], and all macros exported > from the standard library are still included in the `macro_use` prelude. diff --git a/src/names/scopes.md b/src/names/scopes.md index 55ef159b4..30b34fcc4 100644 --- a/src/names/scopes.md +++ b/src/names/scopes.md @@ -1,46 +1,67 @@ +r[names.scopes] # Scopes +r[names.scopes.intro] A *scope* is the region of source text where a named [entity] may be referenced with that name. The following sections provide details on the scoping rules and behavior, which depend on the kind of entity and where it is declared. The process of how names are resolved to entities is described in the [name resolution] chapter. More information on "drop scopes" used for the purpose of running destructors may be found in the [destructors] chapter. +r[names.scopes.items] ## Item scopes +r[names.scopes.items.module] The name of an [item][items] declared directly in a [module] has a scope that extends from the start of the module to the end of the module. These items are also members of the module and can be referred to with a [path] leading from their module. +r[names.scopes.items.statement] The name of an item declared as a [statement] has a scope that extends from the start of the block the item statement is in until the end of the block. +r[names.scopes.items.duplicate] It is an error to introduce an item with a duplicate name of another item in the same [namespace] within the same module or block. [Asterisk glob imports] have special behavior for dealing with duplicate names and shadowing, see the linked chapter for more details. + +r[names.scopes.items.shadow-prelude] Items in a module may shadow items in a [prelude](#prelude-scopes). +r[names.scopes.items.nested-modules] Item names from outer modules are not in scope within a nested module. A [path] may be used to refer to an item in another module. +r[names.scopes.associated-items] ### Associated item scopes +r[names.scopes.associated-items.scope] [Associated items] are not scoped and can only be referred to by using a [path] leading from the type or trait they are associated with. [Methods] can also be referred to via [call expressions]. +r[names.scopes.associated-items.duplicate] Similar to items within a module or block, it is an error to introduce an item within a trait or implementation that is a duplicate of another item in the trait or impl in the same namespace. +r[names.scopes.pattern-bindings] ## Pattern binding scopes The scope of a local variable [pattern] binding depends on where it is used: +r[names.scopes.pattern-bindings.let] * [`let` statement] bindings range from just after the `let` statement until the end of the block where it is declared. +r[names.scopes.pattern-bindings.parameter] * [Function parameter] bindings are within the body of the function. +r[names.scopes.pattern-bindings.closure] * [Closure parameter] bindings are within the closure body. +r[names.scopes.pattern-bindings.loop] * [`for`] and [`while let`] bindings are within the loop body. +r[names.scopes.pattern-bindings.if-let] * [`if let`] bindings are within the consequent block. +r[names.scopes.pattern-bindings.match-arm] * [`match` arms] bindings are within the [match guard] and the match arm expression. +r[names.scopes.pattern-bindings.items] Local variable scopes do not extend into item declarations. ### Pattern binding shadowing +r[names.scopes.pattern-bindings.shadow] Pattern bindings are allowed to shadow any name in scope with the following exceptions which are an error: * [Const generic parameters] @@ -61,11 +82,14 @@ fn shadow_example() { } ``` +r[names.scopes.generic-parameters] ## Generic parameter scopes +r[names.scopes.generic-parameters.param-list] Generic parameters are declared in a [_GenericParams_] list. The scope of a generic parameter is within the item it is declared on. +r[names.scopes.generic-parameters.order-independent] All parameters are in scope within the generic parameter list regardless of the order they are declared. The following shows some examples where a parameter may be referenced before it is declared: @@ -78,6 +102,7 @@ fn params_scope<'a: 'b, 'b>() {} fn f, const N: usize>() {} ``` +r[names.scopes.generic-parameters.bounds] Generic parameters are also in scope for type bounds and where clauses, for example: ```rust @@ -90,6 +115,7 @@ fn where_scope<'a, T, U>() {} ``` +r[names.scopes.generic-parameters.inner-items] It is an error for [items] declared inside a function to refer to a generic parameter from their outer scope. ```rust,compile_fail @@ -100,6 +126,7 @@ fn example() { ### Generic parameter shadowing +r[names.scopes.generic-parameters.shadow] It is an error to shadow a generic parameter with the exception that items declared within functions are allowed to shadow generic parameter names from the function. ```rust @@ -120,19 +147,23 @@ trait SomeTrait<'a, T, const N: usize> { } ``` +r[names.scopes.lifetimes] ### Lifetime scopes Lifetime parameters are declared in a [_GenericParams_] list and [higher-ranked trait bounds][hrtb]. +r[names.scopes.lifetimes.special] The `'static` lifetime and [placeholder lifetime] `'_` have a special meaning and cannot be declared as a parameter. #### Lifetime generic parameter scopes +r[names.scopes.lifetimes.generic] [Constant] and [static] items and [const contexts] only ever allow `'static` lifetime references, so no other lifetime may be in scope within them. [Associated consts] do allow referring to lifetimes declared in their trait or implementation. #### Higher-ranked trait bound scopes +r[names.scopes.lifetimes.higher-ranked] The scope of a lifetime parameter declared as a [higher-ranked trait bound][hrtb] depends on the scenario where it is used. * As a [_TypeBoundWhereClauseItem_] the declared lifetimes are in scope in the type and the type bounds. @@ -162,6 +193,7 @@ type FnExample = for<'a> fn(x: Example<'a>) -> Example<'a>; #### Impl trait restrictions +r[names.scopes.lifetimes.impl-trait] [Impl trait] types can only reference lifetimes declared on a function or implementation. + +r[names.scopes.derive.shadow] Helper attributes shadow other attributes of the same name in scope. +r[names.scopes.self] ## `Self` scope +r[names.scopes.self.intro] Although [`Self`] is a keyword with special meaning, it interacts with name resolution in a way similar to normal names. +r[names.scopes.self.def-scope] The implicit `Self` type in the definition of a [struct], [enum], [union], [trait], or [implementation] is treated similarly to a [generic parameter](#generic-parameter-scopes), and is in scope in the same way as a generic type parameter. +r[names.scopes.self.impl-scope] The implicit `Self` constructor in the value [namespace] of an [implementation] is in scope within the body of the implementation (the implementation's [associated items]). ```rust