From 9660a7f16335a53aaded67c67974f323679259af Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 15 Jun 2025 19:03:06 -0700 Subject: [PATCH 01/11] Unwrap lint attributes --- src/attributes/diagnostics.md | 48 +++++++++-------------------------- 1 file changed, 12 insertions(+), 36 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index b294ec5fc7..c6424d5e5b 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -7,25 +7,18 @@ messages during compilation. r[attributes.diagnostics.lint] ## Lint check attributes -A lint check names a potentially undesirable coding pattern, such as -unreachable code or omitted documentation. +A lint check names a potentially undesirable coding pattern, such as unreachable code or omitted documentation. r[attributes.diagnostics.lint.level] -The lint attributes `allow`, -`expect`, `warn`, `deny`, and `forbid` use the [MetaListPaths] syntax -to specify a list of lint names to change the lint level for the entity -to which the attribute applies. +The lint attributes `allow`, `expect`, `warn`, `deny`, and `forbid` use the [MetaListPaths] syntax to specify a list of lint names to change the lint level for the entity to which the attribute applies. For any lint check `C`: r[attributes.diagnostics.lint.allow] -* `#[allow(C)]` overrides the check for `C` so that violations will go - unreported. +* `#[allow(C)]` overrides the check for `C` so that violations will go unreported. r[attributes.diagnostics.lint.expect] -* `#[expect(C)]` indicates that lint `C` is expected to be emitted. The - attribute will suppress the emission of `C` or issue a warning, if the - expectation is unfulfilled. +* `#[expect(C)]` indicates that lint `C` is expected to be emitted. The attribute will suppress the emission of `C` or issue a warning, if the expectation is unfulfilled. r[attributes.diagnostics.lint.warn] * `#[warn(C)]` warns about violations of `C` but continues compilation. @@ -34,8 +27,7 @@ r[attributes.diagnostics.lint.deny] * `#[deny(C)]` signals an error after encountering a violation of `C`, r[attributes.diagnostics.lint.forbid] -* `#[forbid(C)]` is the same as `deny(C)`, but also forbids changing the lint - level afterwards, +* `#[forbid(C)]` is the same as `deny(C)`, but also forbids changing the lint level afterwards, > [!NOTE] > The lint checks supported by `rustc` can be found via `rustc -W help`, along with their default settings and are documented in the [rustc book]. @@ -57,14 +49,9 @@ pub mod m1 { ``` r[attributes.diagnostics.lint.override] -Lint attributes can override the level specified from a previous attribute, as -long as the level does not attempt to change a forbidden lint -(except for `deny`, which is allowed inside a `forbid` context, but ignored). -Previous attributes are those from a higher level in the syntax tree, or from a -previous attribute on the same entity as listed in left-to-right source order. +Lint attributes can override the level specified from a previous attribute, as long as the level does not attempt to change a forbidden lint (except for `deny`, which is allowed inside a `forbid` context, but ignored). Previous attributes are those from a higher level in the syntax tree, or from a previous attribute on the same entity as listed in left-to-right source order. -This example shows how one can use `allow` and `warn` to toggle a particular -check on and off: +This example shows how one can use `allow` and `warn` to toggle a particular check on and off: ```rust #[warn(missing_docs)] @@ -85,8 +72,7 @@ pub mod m2 { } ``` -This example shows how one can use `forbid` to disallow uses of `allow` or -`expect` for that lint check: +This example shows how one can use `forbid` to disallow uses of `allow` or `expect` for that lint check: ```rust,compile_fail #[forbid(missing_docs)] @@ -104,9 +90,7 @@ pub mod m3 { r[attributes.diagnostics.lint.reason] ### Lint reasons -All lint attributes support an additional `reason` parameter, to give context why -a certain attribute was added. This reason will be displayed as part of the lint -message if the lint is emitted at the defined level. +All lint attributes support an additional `reason` parameter, to give context why a certain attribute was added. This reason will be displayed as part of the lint message if the lint is emitted at the defined level. ```rust,edition2015,compile_fail // `keyword_idents` is allowed by default. Here we deny it to @@ -142,11 +126,7 @@ r[attributes.diagnostics.expect] ### The `#[expect]` attribute r[attributes.diagnostics.expect.intro] -The `#[expect(C)]` attribute creates a lint expectation for lint `C`. The -expectation will be fulfilled, if a `#[warn(C)]` attribute at the same location -would result in a lint emission. If the expectation is unfulfilled, because -lint `C` would not be emitted, the `unfulfilled_lint_expectations` lint will -be emitted at the attribute. +The `#[expect(C)]` attribute creates a lint expectation for lint `C`. The expectation will be fulfilled, if a `#[warn(C)]` attribute at the same location would result in a lint emission. If the expectation is unfulfilled, because lint `C` would not be emitted, the `unfulfilled_lint_expectations` lint will be emitted at the attribute. ```rust fn main() { @@ -168,10 +148,7 @@ fn main() { ``` r[attributes.diagnostics.expect.fulfillment] -The lint expectation is only fulfilled by lint emissions which have been suppressed by -the `expect` attribute. If the lint level is modified in the scope with other level -attributes like `allow` or `warn`, the lint emission will be handled accordingly and the -expectation will remain unfulfilled. +The lint expectation is only fulfilled by lint emissions which have been suppressed by the `expect` attribute. If the lint level is modified in the scope with other level attributes like `allow` or `warn`, the lint emission will be handled accordingly and the expectation will remain unfulfilled. ```rust #[expect(unused_variables)] @@ -198,8 +175,7 @@ fn select_song() { ``` r[attributes.diagnostics.expect.independent] -If the `expect` attribute contains several lints, each one is expected separately. For a -lint group it's enough if one lint inside the group has been emitted: +If the `expect` attribute contains several lints, each one is expected separately. For a lint group it's enough if one lint inside the group has been emitted: ```rust // This expectation will be fulfilled by the unused value inside the function From 3ca94bd481685b85c962726c07848ffcb7d436a8 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 15 Jun 2025 19:41:46 -0700 Subject: [PATCH 02/11] Move examples to example blocks --- src/attributes/diagnostics.md | 147 +++++++++++++++++++--------------- 1 file changed, 81 insertions(+), 66 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index c6424d5e5b..642a27f175 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -13,6 +13,22 @@ r[attributes.diagnostics.lint.level] The lint attributes `allow`, `expect`, `warn`, `deny`, and `forbid` use the [MetaListPaths] syntax to specify a list of lint names to change the lint level for the entity to which the attribute applies. For any lint check `C`: +> [!EXAMPLE] +> ```rust +> pub mod m1 { +> // Missing documentation is ignored here +> #[allow(missing_docs)] +> pub fn undocumented_one() -> i32 { 1 } +> +> // Missing documentation signals a warning here +> #[warn(missing_docs)] +> pub fn undocumented_too() -> i32 { 2 } +> +> // Missing documentation signals an error here +> #[deny(missing_docs)] +> pub fn undocumented_end() -> i32 { 3 } +> } +> ``` r[attributes.diagnostics.lint.allow] * `#[allow(C)]` overrides the check for `C` so that violations will go unreported. @@ -32,57 +48,14 @@ r[attributes.diagnostics.lint.forbid] > [!NOTE] > The lint checks supported by `rustc` can be found via `rustc -W help`, along with their default settings and are documented in the [rustc book]. -```rust -pub mod m1 { - // Missing documentation is ignored here - #[allow(missing_docs)] - pub fn undocumented_one() -> i32 { 1 } - - // Missing documentation signals a warning here - #[warn(missing_docs)] - pub fn undocumented_too() -> i32 { 2 } - - // Missing documentation signals an error here - #[deny(missing_docs)] - pub fn undocumented_end() -> i32 { 3 } -} ``` r[attributes.diagnostics.lint.override] Lint attributes can override the level specified from a previous attribute, as long as the level does not attempt to change a forbidden lint (except for `deny`, which is allowed inside a `forbid` context, but ignored). Previous attributes are those from a higher level in the syntax tree, or from a previous attribute on the same entity as listed in left-to-right source order. -This example shows how one can use `allow` and `warn` to toggle a particular check on and off: - -```rust -#[warn(missing_docs)] -pub mod m2 { - #[allow(missing_docs)] - pub mod nested { - // Missing documentation is ignored here - pub fn undocumented_one() -> i32 { 1 } - - // Missing documentation signals a warning here, - // despite the allow above. - #[warn(missing_docs)] - pub fn undocumented_two() -> i32 { 2 } - } - // Missing documentation signals a warning here - pub fn undocumented_too() -> i32 { 3 } -} -``` -This example shows how one can use `forbid` to disallow uses of `allow` or `expect` for that lint check: -```rust,compile_fail -#[forbid(missing_docs)] -pub mod m3 { - // Attempting to toggle warning signals an error here - #[allow(missing_docs)] - /// Returns 2. - pub fn undocumented_too() -> i32 { 2 } -} -``` > [!NOTE] > `rustc` allows setting lint levels on the [command-line][rustc-lint-cli], and also supports [setting caps][rustc-lint-caps] on the lints that are reported. @@ -92,35 +65,77 @@ r[attributes.diagnostics.lint.reason] All lint attributes support an additional `reason` parameter, to give context why a certain attribute was added. This reason will be displayed as part of the lint message if the lint is emitted at the defined level. -```rust,edition2015,compile_fail -// `keyword_idents` is allowed by default. Here we deny it to -// avoid migration of identifiers when we update the edition. -#![deny( - keyword_idents, - reason = "we want to avoid these idents to be future compatible" -)] -// This name was allowed in Rust's 2015 edition. We still aim to avoid -// this to be future compatible and not confuse end users. -fn dyn() {} -``` -Here is another example, where the lint is allowed with a reason: +> [!EXAMPLE] +> This example shows how one can use `allow` and `warn` to toggle a particular check on and off: +> +> ```rust +> #[warn(missing_docs)] +> pub mod m2 { +> #[allow(missing_docs)] +> pub mod nested { +> // Missing documentation is ignored here +> pub fn undocumented_one() -> i32 { 1 } +> +> // Missing documentation signals a warning here, +> // despite the allow above. +> #[warn(missing_docs)] +> pub fn undocumented_two() -> i32 { 2 } +> } +> +> // Missing documentation signals a warning here +> pub fn undocumented_too() -> i32 { 3 } +> } +> ``` -```rust -use std::path::PathBuf; +> [!EXAMPLE] +> This example shows how one can use `forbid` to disallow uses of `allow` or `expect` for that lint check: +> +> ```rust,compile_fail,E0453 +> #[forbid(missing_docs)] +> pub mod m3 { +> // Attempting to toggle warning signals an error here +> #[allow(missing_docs)] +> /// Returns 2. +> pub fn undocumented_too() -> i32 { 2 } +> } +> ``` -pub fn get_path() -> PathBuf { - // The `reason` parameter on `allow` attributes acts as documentation for the reader. - #[allow(unused_mut, reason = "this is only modified on some platforms")] - let mut file_name = PathBuf::from("git"); - #[cfg(target_os = "windows")] - file_name.set_extension("exe"); - file_name -} -``` +> [!EXAMPLE] +> This example shows a reason explaining why a lint is denied. +> +> ```rust,edition2015,compile_fail +> // `keyword_idents` is allowed by default. Here we deny it to +> // avoid migration of identifiers when we update the edition. +> #![deny( +> keyword_idents, +> reason = "we want to avoid these idents to be future compatible" +> )] +> +> // This name was allowed in Rust's 2015 edition. We still aim to avoid +> // this to be future compatible and not confuse end users. +> fn dyn() {} +> ``` +> +> Here is another example, where the lint is allowed with a reason: +> +> ```rust +> use std::path::PathBuf; +> +> pub fn get_path() -> PathBuf { +> // The `reason` parameter on `allow` attributes acts as documentation for the reader. +> #[allow(unused_mut, reason = "this is only modified on some platforms")] +> let mut file_name = PathBuf::from("git"); +> +> #[cfg(target_os = "windows")] +> file_name.set_extension("exe"); +> +> file_name +> } +> ``` r[attributes.diagnostics.expect] ### The `#[expect]` attribute From a3ca827d9a8b0764c4fa9fff66ef1fb55b16413e Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 15 Jun 2025 19:42:58 -0700 Subject: [PATCH 03/11] Reword the lint check intro This is intended to be a general intro for all of the lint check attributes, so name them here. --- src/attributes/diagnostics.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index 642a27f175..ed6760789a 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -7,10 +7,12 @@ messages during compilation. r[attributes.diagnostics.lint] ## Lint check attributes -A lint check names a potentially undesirable coding pattern, such as unreachable code or omitted documentation. +r[attributes.diagnostics.lint.intro] +A *lint check* names a potentially undesirable coding pattern, such as unreachable code or omitted documentation. r[attributes.diagnostics.lint.level] The lint attributes `allow`, `expect`, `warn`, `deny`, and `forbid` use the [MetaListPaths] syntax to specify a list of lint names to change the lint level for the entity to which the attribute applies. +The *`allow`, `expect`, `warn`, `deny`, and `forbid` [attributes]* control the level of reporting for a lint check. For any lint check `C`: > [!EXAMPLE] From 8e5a5826cc02c72fd9cc9d8e1fbae690271a7446 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 15 Jun 2025 19:43:30 -0700 Subject: [PATCH 04/11] Move the notes to the intro --- src/attributes/diagnostics.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index ed6760789a..3943880dec 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -34,9 +34,13 @@ For any lint check `C`: r[attributes.diagnostics.lint.allow] * `#[allow(C)]` overrides the check for `C` so that violations will go unreported. +> [!NOTE] +> The lint checks supported by `rustc` can be found via `rustc -W help`, along with their default settings and are documented in the [rustc book]. r[attributes.diagnostics.lint.expect] * `#[expect(C)]` indicates that lint `C` is expected to be emitted. The attribute will suppress the emission of `C` or issue a warning, if the expectation is unfulfilled. +> [!NOTE] +> `rustc` allows setting lint levels on the [command-line][rustc-lint-cli], and also supports [setting caps][rustc-lint-caps] on the lints that are reported. r[attributes.diagnostics.lint.warn] * `#[warn(C)]` warns about violations of `C` but continues compilation. @@ -47,8 +51,6 @@ r[attributes.diagnostics.lint.deny] r[attributes.diagnostics.lint.forbid] * `#[forbid(C)]` is the same as `deny(C)`, but also forbids changing the lint level afterwards, -> [!NOTE] -> The lint checks supported by `rustc` can be found via `rustc -W help`, along with their default settings and are documented in the [rustc book]. ``` @@ -59,8 +61,6 @@ Lint attributes can override the level specified from a previous attribute, as l -> [!NOTE] -> `rustc` allows setting lint levels on the [command-line][rustc-lint-cli], and also supports [setting caps][rustc-lint-caps] on the lints that are reported. r[attributes.diagnostics.lint.reason] ### Lint reasons From c74f484d539dc8b01a7e8a9a8bfc7660263dc7dc Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 15 Jun 2025 19:45:00 -0700 Subject: [PATCH 05/11] Rework lint attributes to follow the attribute template This adds the corresponding rules, and reworks a little to be explicit about the syntax. --- src/attributes/diagnostics.md | 50 ++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index 3943880dec..c772881f39 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -10,11 +10,8 @@ r[attributes.diagnostics.lint] r[attributes.diagnostics.lint.intro] A *lint check* names a potentially undesirable coding pattern, such as unreachable code or omitted documentation. -r[attributes.diagnostics.lint.level] -The lint attributes `allow`, `expect`, `warn`, `deny`, and `forbid` use the [MetaListPaths] syntax to specify a list of lint names to change the lint level for the entity to which the attribute applies. The *`allow`, `expect`, `warn`, `deny`, and `forbid` [attributes]* control the level of reporting for a lint check. -For any lint check `C`: > [!EXAMPLE] > ```rust > pub mod m1 { @@ -32,42 +29,56 @@ For any lint check `C`: > } > ``` -r[attributes.diagnostics.lint.allow] -* `#[allow(C)]` overrides the check for `C` so that violations will go unreported. > [!NOTE] > The lint checks supported by `rustc` can be found via `rustc -W help`, along with their default settings and are documented in the [rustc book]. -r[attributes.diagnostics.lint.expect] -* `#[expect(C)]` indicates that lint `C` is expected to be emitted. The attribute will suppress the emission of `C` or issue a warning, if the expectation is unfulfilled. > [!NOTE] > `rustc` allows setting lint levels on the [command-line][rustc-lint-cli], and also supports [setting caps][rustc-lint-caps] on the lints that are reported. -r[attributes.diagnostics.lint.warn] -* `#[warn(C)]` warns about violations of `C` but continues compilation. +r[attributes.diagnostics.lint.syntax] +The syntax for the lint attributes is: -r[attributes.diagnostics.lint.deny] -* `#[deny(C)]` signals an error after encountering a violation of `C`, +```grammar,attributes +@root LintAttribute -> + LintAttrName `(` `)` + | LintAttrName `(` LintReason `,`? `)` + | LintAttrName `(` LintNames (`,` LintReason)? `,`? `)` -r[attributes.diagnostics.lint.forbid] -* `#[forbid(C)]` is the same as `deny(C)`, but also forbids changing the lint level afterwards, +LintAttrName -> `allow` | `expect` | `warn` | `deny` | `forbid` +LintNames -> SimplePath (`,` SimplePath)* +LintReason -> `reason` `=` (STRING_LITERAL | RAW_STRING_LITERAL) ``` -r[attributes.diagnostics.lint.override] -Lint attributes can override the level specified from a previous attribute, as long as the level does not attempt to change a forbidden lint (except for `deny`, which is allowed inside a `forbid` context, but ignored). Previous attributes are those from a higher level in the syntax tree, or from a previous attribute on the same entity as listed in left-to-right source order. +The [LintNames] list the lint checks that are affected. The optional [LintReason] is described in [attributes.diagnostics.lint.reason]. +r[attributes.diagnostics.lint.allowed-positions] +The lint attributes are allowed anywhere attributes are allowed. +r[attributes.diagnostics.lint.duplicates] +When a lint attribute is specified multiple times, it combines the union of all specified lints. The order matters when multiple levels are specified in the same place, which is described in [attributes.diagnostics.lint.override]. +r[attributes.diagnostics.lint.level] +Each lint attribute sets the level of the specified lint checks. The following describes the behavior for each attribute for any lint `C`: +r[attributes.diagnostics.lint.allow] +* `#[allow(C)]` overrides the check for `C` so that violations will go unreported. +r[attributes.diagnostics.lint.expect] +* `#[expect(C)]` indicates that lint `C` is expected to be emitted. The attribute will suppress the emission of `C` or issue a warning, if the expectation is unfulfilled. See [attributes.diagnostics.expect] for a complete description. -r[attributes.diagnostics.lint.reason] -### Lint reasons +r[attributes.diagnostics.lint.warn] +* `#[warn(C)]` warns about violations of `C` but continues compilation. -All lint attributes support an additional `reason` parameter, to give context why a certain attribute was added. This reason will be displayed as part of the lint message if the lint is emitted at the defined level. +r[attributes.diagnostics.lint.deny] +* `#[deny(C)]` signals an error after encountering a violation of `C`. +r[attributes.diagnostics.lint.forbid] +* `#[forbid(C)]` is the same as `deny(C)`, but also forbids changing the lint level afterwards. +r[attributes.diagnostics.lint.override] +Lint attributes can override the level specified from a previous attribute, as long as the level does not attempt to change a forbidden lint (except for `deny`, which is allowed inside a `forbid` context, but ignored). Previous attributes are those from a higher level in the syntax tree, or from a previous attribute on the same entity as listed in left-to-right source order. > [!EXAMPLE] > This example shows how one can use `allow` and `warn` to toggle a particular check on and off: @@ -104,7 +115,10 @@ All lint attributes support an additional `reason` parameter, to give context wh > } > ``` +r[attributes.diagnostics.lint.reason] +### Lint reasons +All lint attributes support an additional `reason` parameter, to give context why a certain attribute was added. This reason will be displayed as part of the lint message if the lint is emitted at the defined level. > [!EXAMPLE] > This example shows a reason explaining why a lint is denied. From 9e01da6c4db29c01b45bc116e503560c1f03c754 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 16 Jun 2025 08:12:36 -0700 Subject: [PATCH 06/11] Normalize the way we refer to diagnostic attributes The style we have generally settled on is to *not* surround the name of the attribute with `#[]`. --- src/attributes/diagnostics.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index c772881f39..4ee4901595 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -63,19 +63,19 @@ r[attributes.diagnostics.lint.level] Each lint attribute sets the level of the specified lint checks. The following describes the behavior for each attribute for any lint `C`: r[attributes.diagnostics.lint.allow] -* `#[allow(C)]` overrides the check for `C` so that violations will go unreported. +* `allow(C)` overrides the check for `C` so that violations will go unreported. r[attributes.diagnostics.lint.expect] -* `#[expect(C)]` indicates that lint `C` is expected to be emitted. The attribute will suppress the emission of `C` or issue a warning, if the expectation is unfulfilled. See [attributes.diagnostics.expect] for a complete description. +* `expect(C)` indicates that lint `C` is expected to be emitted. The attribute will suppress the emission of `C` or issue a warning, if the expectation is unfulfilled. See [attributes.diagnostics.expect] for a complete description. r[attributes.diagnostics.lint.warn] -* `#[warn(C)]` warns about violations of `C` but continues compilation. +* `warn(C)` warns about violations of `C` but continues compilation. r[attributes.diagnostics.lint.deny] -* `#[deny(C)]` signals an error after encountering a violation of `C`. +* `deny(C)` signals an error after encountering a violation of `C`. r[attributes.diagnostics.lint.forbid] -* `#[forbid(C)]` is the same as `deny(C)`, but also forbids changing the lint level afterwards. +* `forbid(C)` is the same as `deny(C)`, but also forbids changing the lint level afterwards. r[attributes.diagnostics.lint.override] Lint attributes can override the level specified from a previous attribute, as long as the level does not attempt to change a forbidden lint (except for `deny`, which is allowed inside a `forbid` context, but ignored). Previous attributes are those from a higher level in the syntax tree, or from a previous attribute on the same entity as listed in left-to-right source order. @@ -154,10 +154,10 @@ All lint attributes support an additional `reason` parameter, to give context wh > ``` r[attributes.diagnostics.expect] -### The `#[expect]` attribute +### The `expect` attribute r[attributes.diagnostics.expect.intro] -The `#[expect(C)]` attribute creates a lint expectation for lint `C`. The expectation will be fulfilled, if a `#[warn(C)]` attribute at the same location would result in a lint emission. If the expectation is unfulfilled, because lint `C` would not be emitted, the `unfulfilled_lint_expectations` lint will be emitted at the attribute. +The `expect(C)` attribute creates a lint expectation for lint `C`. The expectation will be fulfilled, if a `warn(C)` attribute at the same location would result in a lint emission. If the expectation is unfulfilled, because lint `C` would not be emitted, the `unfulfilled_lint_expectations` lint will be emitted at the attribute. ```rust fn main() { @@ -229,7 +229,7 @@ pub fn another_example() { ``` > [!NOTE] -> The behavior of `#[expect(unfulfilled_lint_expectations)]` is currently defined to always generate the `unfulfilled_lint_expectations` lint. +> The behavior of `expect(unfulfilled_lint_expectations)` is currently defined to always generate the `unfulfilled_lint_expectations` lint. r[attributes.diagnostics.lint.group] ### Lint groups From bb861201eb821c42e2335199d71302622c4f9de1 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 16 Jun 2025 08:17:15 -0700 Subject: [PATCH 07/11] Rename expect intro rule I'd like to avoid "intro" rules that are the core definition of a thing. --- src/attributes/diagnostics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index 4ee4901595..c3d354de85 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -156,7 +156,7 @@ All lint attributes support an additional `reason` parameter, to give context wh r[attributes.diagnostics.expect] ### The `expect` attribute -r[attributes.diagnostics.expect.intro] +r[attributes.diagnostics.expect.behavior] The `expect(C)` attribute creates a lint expectation for lint `C`. The expectation will be fulfilled, if a `warn(C)` attribute at the same location would result in a lint emission. If the expectation is unfulfilled, because lint `C` would not be emitted, the `unfulfilled_lint_expectations` lint will be emitted at the attribute. ```rust From 435d191bd2dd492806138d54946d118ee74d37ce Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 16 Jun 2025 08:19:07 -0700 Subject: [PATCH 08/11] Move expect examples to example blocks --- src/attributes/diagnostics.md | 125 +++++++++++++++++----------------- 1 file changed, 64 insertions(+), 61 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index c3d354de85..6a9bc7de92 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -159,74 +159,77 @@ r[attributes.diagnostics.expect] r[attributes.diagnostics.expect.behavior] The `expect(C)` attribute creates a lint expectation for lint `C`. The expectation will be fulfilled, if a `warn(C)` attribute at the same location would result in a lint emission. If the expectation is unfulfilled, because lint `C` would not be emitted, the `unfulfilled_lint_expectations` lint will be emitted at the attribute. -```rust -fn main() { - // This `#[expect]` attribute creates a lint expectation, that the `unused_variables` - // lint would be emitted by the following statement. This expectation is - // unfulfilled, since the `question` variable is used by the `println!` macro. - // Therefore, the `unfulfilled_lint_expectations` lint will be emitted at the - // attribute. - #[expect(unused_variables)] - let question = "who lives in a pineapple under the sea?"; - println!("{question}"); - - // This `#[expect]` attribute creates a lint expectation that will be fulfilled, since - // the `answer` variable is never used. The `unused_variables` lint, that would usually - // be emitted, is suppressed. No warning will be issued for the statement or attribute. - #[expect(unused_variables)] - let answer = "SpongeBob SquarePants!"; -} -``` +> [!EXAMPLE] +> ```rust +> fn main() { +> // This `#[expect]` attribute creates a lint expectation, that the `unused_variables` +> // lint would be emitted by the following statement. This expectation is +> // unfulfilled, since the `question` variable is used by the `println!` macro. +> // Therefore, the `unfulfilled_lint_expectations` lint will be emitted at the +> // attribute. +> #[expect(unused_variables)] +> let question = "who lives in a pineapple under the sea?"; +> println!("{question}"); +> +> // This `#[expect]` attribute creates a lint expectation that will be fulfilled, since +> // the `answer` variable is never used. The `unused_variables` lint, that would usually +> // be emitted, is suppressed. No warning will be issued for the statement or attribute. +> #[expect(unused_variables)] +> let answer = "SpongeBob SquarePants!"; +> } +> ``` r[attributes.diagnostics.expect.fulfillment] The lint expectation is only fulfilled by lint emissions which have been suppressed by the `expect` attribute. If the lint level is modified in the scope with other level attributes like `allow` or `warn`, the lint emission will be handled accordingly and the expectation will remain unfulfilled. -```rust -#[expect(unused_variables)] -fn select_song() { - // This will emit the `unused_variables` lint at the warn level - // as defined by the `warn` attribute. This will not fulfill the - // expectation above the function. - #[warn(unused_variables)] - let song_name = "Crab Rave"; - - // The `allow` attribute suppresses the lint emission. This will not - // fulfill the expectation as it has been suppressed by the `allow` - // attribute and not the `expect` attribute above the function. - #[allow(unused_variables)] - let song_creator = "Noisestorm"; - - // This `expect` attribute will suppress the `unused_variables` lint emission - // at the variable. The `expect` attribute above the function will still not - // be fulfilled, since this lint emission has been suppressed by the local - // expect attribute. - #[expect(unused_variables)] - let song_version = "Monstercat Release"; -} -``` +> [!EXAMPLE] +> ```rust +> #[expect(unused_variables)] +> fn select_song() { +> // This will emit the `unused_variables` lint at the warn level +> // as defined by the `warn` attribute. This will not fulfill the +> // expectation above the function. +> #[warn(unused_variables)] +> let song_name = "Crab Rave"; +> +> // The `allow` attribute suppresses the lint emission. This will not +> // fulfill the expectation as it has been suppressed by the `allow` +> // attribute and not the `expect` attribute above the function. +> #[allow(unused_variables)] +> let song_creator = "Noisestorm"; +> +> // This `expect` attribute will suppress the `unused_variables` lint emission +> // at the variable. The `expect` attribute above the function will still not +> // be fulfilled, since this lint emission has been suppressed by the local +> // expect attribute. +> #[expect(unused_variables)] +> let song_version = "Monstercat Release"; +> } +> ``` r[attributes.diagnostics.expect.independent] -If the `expect` attribute contains several lints, each one is expected separately. For a lint group it's enough if one lint inside the group has been emitted: - -```rust -// This expectation will be fulfilled by the unused value inside the function -// since the emitted `unused_variables` lint is inside the `unused` lint group. -#[expect(unused)] -pub fn thoughts() { - let unused = "I'm running out of examples"; -} - -pub fn another_example() { - // This attribute creates two lint expectations. The `unused_mut` lint will be - // suppressed and with that fulfill the first expectation. The `unused_variables` - // wouldn't be emitted, since the variable is used. That expectation will therefore - // be unsatisfied, and a warning will be emitted. - #[expect(unused_mut, unused_variables)] - let mut link = "https://www.rust-lang.org/"; +If the `expect` attribute contains several lints, each one is expected separately. For a lint group it's enough if one lint inside the group has been emitted. - println!("Welcome to our community: {link}"); -} -``` +> [!EXAMPLE] +> ```rust +> // This expectation will be fulfilled by the unused value inside the function +> // since the emitted `unused_variables` lint is inside the `unused` lint group. +> #[expect(unused)] +> pub fn thoughts() { +> let unused = "I'm running out of examples"; +> } +> +> pub fn another_example() { +> // This attribute creates two lint expectations. The `unused_mut` lint will be +> // suppressed and with that fulfill the first expectation. The `unused_variables` +> // wouldn't be emitted, since the variable is used. That expectation will therefore +> // be unsatisfied, and a warning will be emitted. +> #[expect(unused_mut, unused_variables)] +> let mut link = "https://www.rust-lang.org/"; +> +> println!("Welcome to our community: {link}"); +> } +> ``` > [!NOTE] > The behavior of `expect(unfulfilled_lint_expectations)` is currently defined to always generate the `unfulfilled_lint_expectations` lint. From 5d66874bece9b6d9b6db4512a33104eea902b7ba Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 16 Jun 2025 08:20:52 -0700 Subject: [PATCH 09/11] Move expect note This moves the note so that it isn't dangling at the bottom of the section. I generally would like to avoid these, since it isn't clear if the note is tied to the previous rule, or the entire section. This seems to fit with this rule better, anyways. --- src/attributes/diagnostics.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index 6a9bc7de92..80d8ef7f25 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -179,6 +179,9 @@ The `expect(C)` attribute creates a lint expectation for lint `C`. The expectati > } > ``` +> [!NOTE] +> The behavior of `expect(unfulfilled_lint_expectations)` is currently defined to always generate the `unfulfilled_lint_expectations` lint. + r[attributes.diagnostics.expect.fulfillment] The lint expectation is only fulfilled by lint emissions which have been suppressed by the `expect` attribute. If the lint level is modified in the scope with other level attributes like `allow` or `warn`, the lint emission will be handled accordingly and the expectation will remain unfulfilled. @@ -231,9 +234,6 @@ If the `expect` attribute contains several lints, each one is expected separatel > } > ``` -> [!NOTE] -> The behavior of `expect(unfulfilled_lint_expectations)` is currently defined to always generate the `unfulfilled_lint_expectations` lint. - r[attributes.diagnostics.lint.group] ### Lint groups From 95cd8e4027ea0408e7293ad7447b5041255ac6c7 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 30 Jun 2025 10:16:58 -0700 Subject: [PATCH 10/11] Remove a comma that doesn't seem to help --- src/attributes/diagnostics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index 80d8ef7f25..189eda0c30 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -66,7 +66,7 @@ r[attributes.diagnostics.lint.allow] * `allow(C)` overrides the check for `C` so that violations will go unreported. r[attributes.diagnostics.lint.expect] -* `expect(C)` indicates that lint `C` is expected to be emitted. The attribute will suppress the emission of `C` or issue a warning, if the expectation is unfulfilled. See [attributes.diagnostics.expect] for a complete description. +* `expect(C)` indicates that lint `C` is expected to be emitted. The attribute will suppress the emission of `C` or issue a warning if the expectation is unfulfilled. See [attributes.diagnostics.expect] for a complete description. r[attributes.diagnostics.lint.warn] * `warn(C)` warns about violations of `C` but continues compilation. From c06733cc5daae0d296c78b6873661467044b107d Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 7 Oct 2025 14:12:44 -0700 Subject: [PATCH 11/11] Update diagnostics for updated attribute template --- src/attributes/diagnostics.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index 189eda0c30..613c4c4cd5 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -4,6 +4,7 @@ r[attributes.diagnostics] The following [attributes] are used for controlling or generating diagnostic messages during compilation. + r[attributes.diagnostics.lint] ## Lint check attributes