Summary

Rust has a number of code lints, both built into the compiler and provided

与える
through external tools, which provide guidelines for code style. The linter behavior
ふるまい
can be customized by attaching attributes to regions of code to allow,
許可する、可能にする
warn, or forbid, certain lint checks.

The decision for allowing,

許可する、可能にする
warning on, or forbidding, specific
特定の
lints is occasionally placed in a comment above the attribute or, more often, left unstated. This RFC proposes adding
たす
syntax
文法
to the lint attributes to encode
符号化する
the documented reason for a lint configuration choice.

Motivation

The style guide for a project, team, or company can cover far more than just syntax

文法
layout. Rules for the semantic shape of a codebase are documented in natural language
言語
and often in automated checking programs, such as the Rust compiler and Clippy. Because the decisions about what rules to follow
下記の、次に続く、追従する
or ignore
無視する
shape the codebase and its growth, the decisions are worth storing in the project directly
直接
with the settings they affect.

It is common wisdom that only the text the environment

環境
can read stays true; text it ignores
無視する
will drift out of sync with the code over time, if it was even in sync to begin. Lint settings should have an explanation for their use to explain why they were chosen and where they are or are not applicable. As they are text that is read by some lint program, they have an opportunity to include an explanation similar
似ている、同様の
to the way Rust documentation
文書
is a first-class attribute on code.

The RFC template asks three questions for motivation:

  • Why are we doing this?

We are adding

たす
this behavior
ふるまい
to give projects a mechanism
仕組み、機構
for storing human design
設計(する)
choices about code in a manner that the tools can track and use to empower human work. For example, the compiler could use the contents of the lint explanation when it emits lint messages, or the documenter could collect them into a set
セットする、集合
of code style information.

  • What use cases does it support?

This supports the use cases of projects, teams, or organizations using specific

特定の
sets
セットする、集合
of code style guidelines beyond the Rust defaults. This also enables the creation and maintenance of documented practices and preferences that can be standardized in a useful way. Furthermore, this provides
与える
a standardized means of explaining decisions when a style gude must be violated
違反する
by attaching an overriding lint attribute to a specific
特定の
item.

  • What is the expected outcome?

The expected outcome of this RFC is that projects will have more information about the decisions and expectations of the project, and can have support from the tools to maintain and inform these decisions. Global and specific

特定の
choices can have their information checked and maintained by the tools, and the Rust ecosystem can have a somewhat more uniform means of establishing code guidelines and practices.

I expect Clippy will be a significant benefactor of this RFC, as Clippy lints are far more specific

特定の
and plentiful than the compiler lints, and from personal experience much more likely to want explanation for their use or disuse.

Guide-level explanation

When a linting tool such as the compiler or Clippy encounter a code span that they determine

決定する
breaks one of their rules, they emit a message indicating the problem and, often, how to fix it. These messages explain how to make the linter program happy, but carry very little information on why the code may be a problem from a human perspective.

These lints can be configured away from the default settings by the use of an attribute modifying the code span that triggers

引き起こす
a lint, or by setting the linter behavior
ふるまい
for a module or crate, with attributes like #[allow(rule)] and #![deny(rule)].

It is generally good practice to include an explanation for why certain rules are set

セットする、集合
so that programmers working on a project can know what the project expects from their work. These explanations can be embedded
埋め込む
directly
直接
in the lint attribute with the reason = "Your reasoning here" attribute.

For example, if you are implementing

実装する
Ord on an enum where the discriminants are not the correct ordering, you might have code like this:

#![allow(unused)] fn main() { enum Severity { Red, Blue, Green, Yellow } impl Ord for Severity { fn cmp(&self, other: &Self) -> Ordering { use Severity::*; use Ordering::*; match (*self, *other) { (Red, Red) | (Blue, Blue) | (Green, Green) | (Yellow, Yellow) => Equal, (Blue, _) => Greater, (Red, _) => Less, (Green, Blue) => Less, (Green, _) => Greater, (Yellow, Red) => Greater, (Yellow, _) => Less, } } } }

The ordering of the left hand side of the match

一致する、マッチさせる
branches
枝、分岐
is significant, and allows
許可する、可能にする
a compact
コンパクト
number of match
一致する、マッチさせる
arms. However, if you're using Clippy, this will cause
起こす
the match_same_arms lint to trip! You can silence the lint in this spot, and provide an explanation that indicates you are doing so deliberately, by placing this attribute above the match
一致する、マッチさせる
line:

#![allow(unused)] fn main() { #[allow(match_same_arms, reason = "The arms are order-dependent")] }

Now, when the lints run, no warning will be raised on this specific

特定の
instance,
実例
and there is an explanation of why you disabled the lint, directly
直接
in the lint command.

Similarly,

同様に
if you want to increase the strictness of a lint, you can explain why you think the lint is worth warning or forbidding directly
直接
in it:

#![allow(unused)] #![deny(float_arithmetic, reason = "This code runs in a context without floats")] fn main() { }

With a warning or denial marker, when a linting tool encounters such a lint trap it will emit its builtin diagnostic, but also include the reason in its output.

For instance,

実例
using the above Clippy lint and some floating-point
浮動小数点
arithmetic
算術
code will result
結果、戻り値
in the following lint output:

error: floating-point arithmetic detected reason: This code runs in a context without floats --> src/lib.rs:4:2 | 4 | a + b | ^^^^^ | note: lint level defined here --> src/lib.rs:1:44 | 1 | #![cfg_attr(deny(float_arithmetic, reason = "..."))] | ^^^^^^^^^^^^^^^^ = help: for further information visit ...

expect Lint Attribute

This RFC adds an expect lint attribute that functions identically to allow

許可する、可能にする
, but will cause
起こす
a lint to be emitted when the code it decorates does not raise a lint warning. This lint was inspired by Yehuda Katz:

@ManishEarth has anyone ever asked for something like #[expect(lint)] which would basically be like #[allow(lint)] but give you a lint warning if the problem ever went away?

I basically want to mark things as ok while doing initial

初期
work, but I need to know when safe to remove

Yehuda Katz (@wycats)

March 30, 2018

When the lint passes run, the expect attribute suppresses a lint generated

生成する
by the span to which it attached. It does not swallow any other lint raised, and when it does not receive a lint to suppress, it raises a lint warning itself. expect can take
とる
a reason field, which is printed when the lint is raised, just as with the allow
許可する、可能にする
/warn/deny markers.

This is used when prototyping and using code that will generate lints for now, but will eventually be refactored and stop generating lints and thus

それゆえに、従って、
no longer need the permission.

#![allow(unused)] fn main() { #[expect(unused_mut, reason = "Everything is mut until I get this figured out")] fn foo() -> usize { let mut a = Vec::new(); a.len() } }

will remain quiet while you're not mutating a, but when you do write code that mutates it, or decide you don't need it mutable and strip the mut, the expect lint will fire and inform you that there is no unused mutation in the span.

#![allow(unused)] fn main() { #[expect(unused_mut, reason = "...")] fn foo() { let a = Vec::new(); a.len() } }

will emit

warning: expected lint `unused_mut` did not appear reason: Everything is mut until I get this figured out --> src/lib.rs:1:1 | 1 | #[expect(unused_mut, reason = "...")] | -------^^^^^^^^^^----------------- | | | help: remove this `#[expect(...)]` | = note: #[warn(expectation_missing)] on by default

Reference-level explanation

This RFC adds a reason = STRING element

要素
to the three lint attributes. The diagnostic emitter in the compiler and other lint tools such as Clippy will need to be made aware of this element
要素
so that they can emit it in diagnostic text.

This RFC also adds the expect(lint_name, reason = STRING) lint attribute. The expect attribute uses the same lint-suppression mechanism

仕組み、機構
that allow
許可する、可能にする
does, but will raise a new lint, expectation_missing (name open to change), when the lint it expects does not arrive.

The expectation_missing lint is itself subject to allow

許可する、可能にする
/expect/warn/deny attributes in a higher scope, so it is possible to suppress expectation failures, lint when no expectation failures occur,
起こる
or fail the build when one occurs.
起こる、発生する
The default setting is #![warn(expectation_missing)].

That’s pretty much it, for technical details.

OPTIONAL
必須でない
Yet Another Comment Syntax
文法

A sugar for lint text MAY be the line comment //# or the block comment /*# #*/ with U+0023 # NUMBER SIGN as the signifying character.

文字
These comments MUST be placed immediately
直後に、直接的に
above a lint attribute. They are collected into a single
単一の
string and collapsed as the text content of the attribute they decorate using the same processing logic that documentation
文書
comments (/// and //! and their block variants) currently use. Example:

#![allow(unused)] fn main() { //# Floating Point Arithmetic Unsupported //# //# This crate is written to be run on an AVR processor which does not have //# floating-point capability in hardware. As such, all floating-point work is //# done in software routines that can take a significant amount of time and //# space to perform. Rather than pay this cost, floating-point work is //# statically disabled. All arithmetic is in fixed-point integer math, using //# the `FixedPoint` wrapper over integer primitives. #![deny(float_arithmetic)] }

The # character

文字
is chosen as the signifying character
文字
to provide room
余地
for possible future expansion these comments MAY in the future be repurposed as sugar for writing the text of an attribute that declares
宣言
a string parameter
仮引数
that can accept
受け付ける、受理する
such comments.

This comment syntax

文法
already pushes the edge of the scope of this RFC, and extension of all attributes is certainly beyond it.

Implementing

実装する
this comment syntax
文法
would require extending
拡張する
the existing transform pass that replaces documentation
文書
comments with documentation
文書
attributes. Specifically,
特に
the transform pass would ensure
保証する
that all lint comments are directly
直接
attached to a lint attribute, and then use the strip-and-trim method that the documentation
文書
comments experience to remove the comment markers and collapse the comment text, across multiple
複数の
consecutive comment spans, into a single
単一の
string that is then inserted
挿入する
as reason = STRING into the attribute.

Given

与えられた
that this is a lot of work and a huge addition
追加
to the comment grammar,
文法
the author does not expect it to be included in the main RFC at all, and is writing it solely
単に/単独で
to be a published prior art in case of future desire for such a feature.

Drawbacks

Why should we not do this?

Possibly

ことによると、可能性としてあり得ることに
low value add for the effort.

Rationale and alternatives
代わりのもの、選択肢

  • Why is this design

    設計(する)
    the best in the space of possible designs?

    Attributes taking

    とる
    descriptive text is a common pattern in Rust.

  • What other designs

    設計(する)
    have been considered
    みなす、考慮する
    and what is the rationale for not choosing them?

    None.

  • What is the impact of not doing this?

    None.

Prior art

The stable and unstable attributes both take

とる
descriptive text parameters
仮引数
that appear
現れる
in diagnostic and documentation
文書
output.

Unresolved questions

  • What parts of the design

    設計(する)
    do you expect to resolve
    解決する
    through the RFC process before this gets merged?

    The name of the reason parameter.

    仮引数

  • What parts of the design

    設計(する)
    do you expect to resolve
    解決する
    through the implementation
    実装
    of this feature before stabilization?

    The use sites of the reason parameter.

    仮引数

  • What related issues do you consider

    考える、みなす
    out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC?

    The means of filling the reason parameter,

    仮引数
    or what tools like rustdoc would do with them.