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.
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:
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.
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 ...
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
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.
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 () {
#![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.
Why should we not do this?
Possiblyことによると、可能性としてあり得ることに
low value add for the effort.
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.
The stable
and unstable
attributes both takeとる
descriptive text parameters仮引数
that appear現れる
in diagnostic and documentation文書
output.
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.