From 946c58d511b66bc5d1dbd54d0b85adc139adbf6f Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 16 Apr 2021 17:44:49 -0400 Subject: [PATCH 01/11] Document inert vs active attributes This PR adds a subsection to the 'Syntax and AST' section describing inert vs active attributes. For consistency, I've also updated the '#[test] implementation' page to stop referring to `#[test]' as a 'built in' attribute, since that has a specific meaning defined on this page. --- src/SUMMARY.md | 1 + src/attributes.md | 49 ++++++++++++++++++++++++++++++++++++++ src/test-implementation.md | 2 +- 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 src/attributes.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 3f14c2642..fb4acfa75 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -77,6 +77,7 @@ - [Lexing and Parsing](./the-parser.md) - [Macro expansion](./macro-expansion.md) - [Name resolution](./name-resolution.md) + - [Attributes](./attributes.md) - [`#[test]` Implementation](./test-implementation.md) - [Panic Implementation](./panic-implementation.md) - [AST Validation](./ast-validation.md) diff --git a/src/attributes.md b/src/attributes.md new file mode 100644 index 000000000..32d2d46fc --- /dev/null +++ b/src/attributes.md @@ -0,0 +1,49 @@ +# Attributes + +Attributes come in two types - 'builtin'/'inert' attributes, and 'non-builtin'/'active' attributes: + +## 'Builtin'/'inert' attributes + +These attributes are defined in the compiler itself, in +[`compiler/rustc_feature/src/builtin_attrs.rs`][builtin_attrs] + +Example include `#[allow]` and `#[macro_use]` + +[builtin_attrs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_feature/builtin_attrs/index.html + +These attributes have several important characteristics: +* They are always in scope, and do not participate in typical path-based resolution. +* They cannot be renamed. For example, `use allow as foo` will compile, but writing `#[foo]` will + produce an error. +* They are 'inert', meaning they are left as-is by the macro expansion code. + As a result, any behavior comes as a result of the compiler explicitly checking for their presence + (for example, lint-related code explicitly checks for `#[allow]`, `#[warn]`, `#[deny]`, and +`#[forbid]`) + +## 'Non-builtin'/'active' attributes + +These attributes are defined by a crate - either the standard library, or a proc-macro crate. +**Important**: Many non-builtin attributes, such as `#[derive]`, are still considered part of the +core Rust language. However, they are **not** called 'builtin attributes', since they have a +corresponding definition in the standard library. + +Definitions of non-builtin attributes take two forms: + +1. Proc-macro attributes, defined via a function annotated with `#[proc_macro_attribute]` in a + proc-macro crate. +2. Ast-based attributes, defined in the standard library. These attributes have special 'stub' + macros defined in places like [`library/core/src/macros/mod.rs`][core_macros] + +[core_macros]: https://github.com/rust-lang/rust/blob/master/library/core/src/macros/mod.rs + +These definitions exist to allow the macros to participate in typical path-based resolution - they +can be imported, re-exported, and renamed just like any other item definition. However, the body of +the definition is empty. Instead, the macro is annotated with the `#[rustc_builtin_macro]` +attribute, which tells the compiler to run a corresponding function in `rustc_builtin_macros`. + +All non-builtin attributes have the following characteristics: +* Like all other definitions (e.g. structs), they must be brought into scope via an import. + Many standard library attributes are included in the prelude - this is why writing `#[derive]` + works without an import. +* They participate in macro expansion. The implementation of the macro may leave the attribute + target unchanged, modify the target, produce new AST nodes, or remove the target entirely. diff --git a/src/test-implementation.md b/src/test-implementation.md index 1a9283b59..06d32a62a 100644 --- a/src/test-implementation.md +++ b/src/test-implementation.md @@ -2,7 +2,7 @@ -Today, rust programmers rely on a built in attribute called `#[test]`. All +Today, rust programmers rely on an attribute called `#[test]`. All you have to do is mark a function as a test and include some asserts like so: ```rust,ignore From 27029e6a173a0bd101ecbd4e4b3c1de659d70686 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 23 Jun 2024 16:04:01 +0200 Subject: [PATCH 02/11] Update src/attributes.md Co-authored-by: Noah Lev --- src/attributes.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/attributes.md b/src/attributes.md index 32d2d46fc..fcc89125f 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -16,9 +16,9 @@ These attributes have several important characteristics: * They cannot be renamed. For example, `use allow as foo` will compile, but writing `#[foo]` will produce an error. * They are 'inert', meaning they are left as-is by the macro expansion code. - As a result, any behavior comes as a result of the compiler explicitly checking for their presence - (for example, lint-related code explicitly checks for `#[allow]`, `#[warn]`, `#[deny]`, and -`#[forbid]`) + As a result, any behavior comes as a result of the compiler explicitly checking for their presence. + For example, lint-related code explicitly checks for `#[allow]`, `#[warn]`, `#[deny]`, and + `#[forbid]`, rather than the behavior coming from the expansion of the attributes themselves. ## 'Non-builtin'/'active' attributes From a21ee89fa0aa525a924860dd15b8904b3c76cc82 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 23 Jun 2024 16:04:08 +0200 Subject: [PATCH 03/11] Update src/attributes.md Co-authored-by: Noah Lev --- src/attributes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/attributes.md b/src/attributes.md index fcc89125f..90f884d02 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -31,8 +31,8 @@ Definitions of non-builtin attributes take two forms: 1. Proc-macro attributes, defined via a function annotated with `#[proc_macro_attribute]` in a proc-macro crate. -2. Ast-based attributes, defined in the standard library. These attributes have special 'stub' - macros defined in places like [`library/core/src/macros/mod.rs`][core_macros] +2. AST-based attributes, defined in the standard library. These attributes have special 'stub' + macros defined in places like [`library/core/src/macros/mod.rs`][core_macros]. [core_macros]: https://github.com/rust-lang/rust/blob/master/library/core/src/macros/mod.rs From ce455cb8fa3a56e4db889479d6344dc715482eac Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 23 Jun 2024 16:04:26 +0200 Subject: [PATCH 04/11] Update src/attributes.md Co-authored-by: Noah Lev --- src/attributes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/attributes.md b/src/attributes.md index 90f884d02..b702f7138 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -5,9 +5,9 @@ Attributes come in two types - 'builtin'/'inert' attributes, and 'non-builtin'/' ## 'Builtin'/'inert' attributes These attributes are defined in the compiler itself, in -[`compiler/rustc_feature/src/builtin_attrs.rs`][builtin_attrs] +[`compiler/rustc_feature/src/builtin_attrs.rs`][builtin_attrs]. -Example include `#[allow]` and `#[macro_use]` +Examples include `#[allow]` and `#[macro_use]`. [builtin_attrs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_feature/builtin_attrs/index.html From 78e6a6441c362fdb2485ce3da36820f1165a6e8d Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 23 Jun 2024 16:04:37 +0200 Subject: [PATCH 05/11] Update src/attributes.md Co-authored-by: Noah Lev --- src/attributes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/attributes.md b/src/attributes.md index b702f7138..9b4e14e48 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -23,6 +23,7 @@ These attributes have several important characteristics: ## 'Non-builtin'/'active' attributes These attributes are defined by a crate - either the standard library, or a proc-macro crate. + **Important**: Many non-builtin attributes, such as `#[derive]`, are still considered part of the core Rust language. However, they are **not** called 'builtin attributes', since they have a corresponding definition in the standard library. From 069e271d4dd6e6c9eec6c647d1e2fdacdf527cbb Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 23 Jun 2024 16:04:49 +0200 Subject: [PATCH 06/11] Update src/attributes.md Co-authored-by: pierwill <19642016+pierwill@users.noreply.github.com> --- src/attributes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attributes.md b/src/attributes.md index 9b4e14e48..783e5ebcd 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -1,6 +1,6 @@ # Attributes -Attributes come in two types - 'builtin'/'inert' attributes, and 'non-builtin'/'active' attributes: +Attributes come in two types: *inert* (or *built-in*) and *active* (*non-builtin*). ## 'Builtin'/'inert' attributes From bc3c874b575bdcdfe80274cc6f303b5a485d3689 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 23 Jun 2024 16:04:57 +0200 Subject: [PATCH 07/11] Update src/test-implementation.md Co-authored-by: pierwill <19642016+pierwill@users.noreply.github.com> --- src/test-implementation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test-implementation.md b/src/test-implementation.md index 06d32a62a..7583f2fc6 100644 --- a/src/test-implementation.md +++ b/src/test-implementation.md @@ -2,7 +2,7 @@ -Today, rust programmers rely on an attribute called `#[test]`. All +Today, Rust programmers rely on an attribute called `#[test]`. All you have to do is mark a function as a test and include some asserts like so: ```rust,ignore From b118f5362c52db2f7b3f02cea6c80704c8f0375d Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 23 Jun 2024 16:05:07 +0200 Subject: [PATCH 08/11] Update src/attributes.md Co-authored-by: pierwill <19642016+pierwill@users.noreply.github.com> --- src/attributes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attributes.md b/src/attributes.md index 783e5ebcd..aae856348 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -2,7 +2,7 @@ Attributes come in two types: *inert* (or *built-in*) and *active* (*non-builtin*). -## 'Builtin'/'inert' attributes +## Builtin/inert attributes These attributes are defined in the compiler itself, in [`compiler/rustc_feature/src/builtin_attrs.rs`][builtin_attrs]. From 1966dad1b3754502ba9e023cbbaa6462c8546bc6 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 23 Jun 2024 16:07:45 +0200 Subject: [PATCH 09/11] Update src/test-implementation.md --- src/test-implementation.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test-implementation.md b/src/test-implementation.md index 279ae4572..61cffef83 100644 --- a/src/test-implementation.md +++ b/src/test-implementation.md @@ -6,7 +6,6 @@ - Many Rust programmers rely on a built-in attribute called `#[test]`. All you have to do is mark a function and include some asserts like so: From c90a04e98a660c6b8b5d9262409a1a808b45007c Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 23 Jun 2024 16:07:53 +0200 Subject: [PATCH 10/11] Update src/test-implementation.md --- src/test-implementation.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test-implementation.md b/src/test-implementation.md index 61cffef83..08b97d254 100644 --- a/src/test-implementation.md +++ b/src/test-implementation.md @@ -5,7 +5,6 @@ - Many Rust programmers rely on a built-in attribute called `#[test]`. All you have to do is mark a function and include some asserts like so: From 17b4cecfb6c0b12f9c14661221db369fbeefeff2 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 23 Jun 2024 16:08:00 +0200 Subject: [PATCH 11/11] Update src/test-implementation.md --- src/test-implementation.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test-implementation.md b/src/test-implementation.md index 08b97d254..bee783c0f 100644 --- a/src/test-implementation.md +++ b/src/test-implementation.md @@ -4,7 +4,6 @@ - Many Rust programmers rely on a built-in attribute called `#[test]`. All you have to do is mark a function and include some asserts like so: